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
17325dc23624160689e59fbac708cf6f222b20d025Daniel Sandlerpackage com.android.launcher3;
184c98d9235d164680186180974719f551cf935d08Winson Chung
19043f2af567178b82b0b41f12d379e7dd12da2936Winson Chungimport android.animation.TimeInterpolator;
20043f2af567178b82b0b41f12d379e7dd12da2936Winson Chungimport android.animation.ValueAnimator;
21043f2af567178b82b0b41f12d379e7dd12da2936Winson Chungimport android.animation.ValueAnimator.AnimatorUpdateListener;
221e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurkaimport android.content.ComponentName;
234c98d9235d164680186180974719f551cf935d08Winson Chungimport android.content.Context;
24a62e9fd95ae10cff4676f2cc1f4d68334ca27a0bWinson Chungimport android.content.res.ColorStateList;
25201bc828d5a0078f505e8e37152156a0cb43c10aWinson Chungimport android.content.res.Configuration;
264c98d9235d164680186180974719f551cf935d08Winson Chungimport android.content.res.Resources;
27043f2af567178b82b0b41f12d379e7dd12da2936Winson Chungimport android.graphics.PointF;
28d4d7aa551ffdc80d810ff970fa72a6509960401eAdam Cohenimport android.graphics.Rect;
29967289b6d5fec77f5c381d11ffb2319f3bb5e737Winson Chungimport android.graphics.drawable.TransitionDrawable;
304346746ef37413168a5cbec46bb6db8f96b0123aMichael Jurkaimport android.os.AsyncTask;
316a2c77856f1cfa402363cfbb04b5718b431bbc6eJason Monkimport android.os.Build;
326a2c77856f1cfa402363cfbb04b5718b431bbc6eJason Monkimport android.os.Bundle;
33950a467b180c78d3ce3bbe7b4a227a13d28b2536Jason Monkimport android.os.UserManager;
344c98d9235d164680186180974719f551cf935d08Winson Chungimport android.util.AttributeSet;
354c98d9235d164680186180974719f551cf935d08Winson Chungimport android.view.View;
36043f2af567178b82b0b41f12d379e7dd12da2936Winson Chungimport android.view.ViewConfiguration;
37a6427b15c18d5b8f3078f553d78f8432de9f46e9Winson Chungimport android.view.ViewGroup;
38043f2af567178b82b0b41f12d379e7dd12da2936Winson Chungimport android.view.animation.AnimationUtils;
39d4d7aa551ffdc80d810ff970fa72a6509960401eAdam Cohenimport android.view.animation.DecelerateInterpolator;
4061967cb17f8fa9ee01f93e9f25a1074559b54cf3Winson Chungimport android.view.animation.LinearInterpolator;
414c98d9235d164680186180974719f551cf935d08Winson Chung
42ed13187a745866483139e2878037e1f8427ce567Kenny Guyimport com.android.launcher3.compat.UserHandleCompat;
43ed13187a745866483139e2878037e1f8427ce567Kenny Guy
4461fa4197c4316bb0f9b05fcefb676f86197a2273Winson Chungpublic class DeleteDropTarget extends ButtonDropTarget {
45043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    private static int DELETE_ANIMATION_DURATION = 285;
466e1bdaf4198f9eb7b4124550d3ad07da2a0226e4Winson Chung    private static int FLING_DELETE_ANIMATION_DURATION = 350;
476e1bdaf4198f9eb7b4124550d3ad07da2a0226e4Winson Chung    private static float FLING_TO_DELETE_FRICTION = 0.035f;
48043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    private static int MODE_FLING_DELETE_TO_TRASH = 0;
49043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    private static int MODE_FLING_DELETE_ALONG_VECTOR = 1;
50043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
51043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    private final int mFlingDeleteMode = MODE_FLING_DELETE_ALONG_VECTOR;
524c98d9235d164680186180974719f551cf935d08Winson Chung
53a62e9fd95ae10cff4676f2cc1f4d68334ca27a0bWinson Chung    private ColorStateList mOriginalTextColor;
54ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen    private TransitionDrawable mUninstallDrawable;
55ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen    private TransitionDrawable mRemoveDrawable;
56ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen    private TransitionDrawable mCurrentDrawable;
574c98d9235d164680186180974719f551cf935d08Winson Chung
5824715c751513ea2b24058b8d1a1e5263f5c31607Michael Jurka    private boolean mWaitingForUninstall = false;
5924715c751513ea2b24058b8d1a1e5263f5c31607Michael Jurka
604c98d9235d164680186180974719f551cf935d08Winson Chung    public DeleteDropTarget(Context context, AttributeSet attrs) {
614c98d9235d164680186180974719f551cf935d08Winson Chung        this(context, attrs, 0);
624c98d9235d164680186180974719f551cf935d08Winson Chung    }
634c98d9235d164680186180974719f551cf935d08Winson Chung
644c98d9235d164680186180974719f551cf935d08Winson Chung    public DeleteDropTarget(Context context, AttributeSet attrs, int defStyle) {
654c98d9235d164680186180974719f551cf935d08Winson Chung        super(context, attrs, defStyle);
664c98d9235d164680186180974719f551cf935d08Winson Chung    }
674c98d9235d164680186180974719f551cf935d08Winson Chung
684c98d9235d164680186180974719f551cf935d08Winson Chung    @Override
694c98d9235d164680186180974719f551cf935d08Winson Chung    protected void onFinishInflate() {
704c98d9235d164680186180974719f551cf935d08Winson Chung        super.onFinishInflate();
714c98d9235d164680186180974719f551cf935d08Winson Chung
724c98d9235d164680186180974719f551cf935d08Winson Chung        // Get the drawable
73a6427b15c18d5b8f3078f553d78f8432de9f46e9Winson Chung        mOriginalTextColor = getTextColors();
744c98d9235d164680186180974719f551cf935d08Winson Chung
754c98d9235d164680186180974719f551cf935d08Winson Chung        // Get the hover color
764c98d9235d164680186180974719f551cf935d08Winson Chung        Resources r = getResources();
774c98d9235d164680186180974719f551cf935d08Winson Chung        mHoverColor = r.getColor(R.color.delete_target_hover_tint);
78ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen        mUninstallDrawable = (TransitionDrawable)
79ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen                r.getDrawable(R.drawable.uninstall_target_selector);
80ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen        mRemoveDrawable = (TransitionDrawable) r.getDrawable(R.drawable.remove_target_selector);
81ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen
82ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen        mRemoveDrawable.setCrossFadeEnabled(true);
83ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen        mUninstallDrawable.setCrossFadeEnabled(true);
84ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen
85ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen        // The current drawable is set to either the remove drawable or the uninstall drawable
86ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen        // and is initially set to the remove drawable, as set in the layout xml.
87947245ba8ad74aee3dadd02693514765dbb4b5a2Winson Chung        mCurrentDrawable = (TransitionDrawable) getCurrentDrawable();
88201bc828d5a0078f505e8e37152156a0cb43c10aWinson Chung
89201bc828d5a0078f505e8e37152156a0cb43c10aWinson Chung        // Remove the text in the Phone UI in landscape
90201bc828d5a0078f505e8e37152156a0cb43c10aWinson Chung        int orientation = getResources().getConfiguration().orientation;
91201bc828d5a0078f505e8e37152156a0cb43c10aWinson Chung        if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
92e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler            if (!LauncherAppState.getInstance().isScreenLarge()) {
93a6427b15c18d5b8f3078f553d78f8432de9f46e9Winson Chung                setText("");
94201bc828d5a0078f505e8e37152156a0cb43c10aWinson Chung            }
95201bc828d5a0078f505e8e37152156a0cb43c10aWinson Chung        }
964c98d9235d164680186180974719f551cf935d08Winson Chung    }
974c98d9235d164680186180974719f551cf935d08Winson Chung
984c98d9235d164680186180974719f551cf935d08Winson Chung    private boolean isAllAppsApplication(DragSource source, Object info) {
991eeb3fc9d874d98dfb43883d17efb4202d83d88aMathew Inwood        return source.supportsAppInfoDropTarget() && (info instanceof AppInfo);
1004c98d9235d164680186180974719f551cf935d08Winson Chung    }
1014c98d9235d164680186180974719f551cf935d08Winson Chung    private boolean isAllAppsWidget(DragSource source, Object info) {
10211a4937fbff0dbc50fb022513dc3b6c643154445Winson Chung        if (source instanceof AppsCustomizePagedView) {
10311a4937fbff0dbc50fb022513dc3b6c643154445Winson Chung            if (info instanceof PendingAddItemInfo) {
10411a4937fbff0dbc50fb022513dc3b6c643154445Winson Chung                PendingAddItemInfo addInfo = (PendingAddItemInfo) info;
10511a4937fbff0dbc50fb022513dc3b6c643154445Winson Chung                switch (addInfo.itemType) {
10611a4937fbff0dbc50fb022513dc3b6c643154445Winson Chung                    case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
10711a4937fbff0dbc50fb022513dc3b6c643154445Winson Chung                    case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
10811a4937fbff0dbc50fb022513dc3b6c643154445Winson Chung                        return true;
10911a4937fbff0dbc50fb022513dc3b6c643154445Winson Chung                }
11011a4937fbff0dbc50fb022513dc3b6c643154445Winson Chung            }
11111a4937fbff0dbc50fb022513dc3b6c643154445Winson Chung        }
11211a4937fbff0dbc50fb022513dc3b6c643154445Winson Chung        return false;
1134c98d9235d164680186180974719f551cf935d08Winson Chung    }
1140b4870db57f6e1d96e72d299cfc05dccb1735caaMichael Jurka    private boolean isDragSourceWorkspaceOrFolder(DragObject d) {
1150b4870db57f6e1d96e72d299cfc05dccb1735caaMichael Jurka        return (d.dragSource instanceof Workspace) || (d.dragSource instanceof Folder);
1164c98d9235d164680186180974719f551cf935d08Winson Chung    }
1170b4870db57f6e1d96e72d299cfc05dccb1735caaMichael Jurka    private boolean isWorkspaceOrFolderApplication(DragObject d) {
1180b4870db57f6e1d96e72d299cfc05dccb1735caaMichael Jurka        return isDragSourceWorkspaceOrFolder(d) && (d.dragInfo instanceof ShortcutInfo);
1190b4870db57f6e1d96e72d299cfc05dccb1735caaMichael Jurka    }
1200b4870db57f6e1d96e72d299cfc05dccb1735caaMichael Jurka    private boolean isWorkspaceOrFolderWidget(DragObject d) {
1210b4870db57f6e1d96e72d299cfc05dccb1735caaMichael Jurka        return isDragSourceWorkspaceOrFolder(d) && (d.dragInfo instanceof LauncherAppWidgetInfo);
1224c98d9235d164680186180974719f551cf935d08Winson Chung    }
1234c98d9235d164680186180974719f551cf935d08Winson Chung    private boolean isWorkspaceFolder(DragObject d) {
1244c98d9235d164680186180974719f551cf935d08Winson Chung        return (d.dragSource instanceof Workspace) && (d.dragInfo instanceof FolderInfo);
1254c98d9235d164680186180974719f551cf935d08Winson Chung    }
1264c98d9235d164680186180974719f551cf935d08Winson Chung
127a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung    private void setHoverColor() {
128fe9da818cde4d8be9903ad6ff42c7248ad54d822Adam Cohen        if (mCurrentDrawable != null) {
129fe9da818cde4d8be9903ad6ff42c7248ad54d822Adam Cohen            mCurrentDrawable.startTransition(mTransitionDuration);
130fe9da818cde4d8be9903ad6ff42c7248ad54d822Adam Cohen        }
131a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung        setTextColor(mHoverColor);
132a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung    }
133a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung    private void resetHoverColor() {
134fe9da818cde4d8be9903ad6ff42c7248ad54d822Adam Cohen        if (mCurrentDrawable != null) {
135fe9da818cde4d8be9903ad6ff42c7248ad54d822Adam Cohen            mCurrentDrawable.resetTransition();
136fe9da818cde4d8be9903ad6ff42c7248ad54d822Adam Cohen        }
137a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung        setTextColor(mOriginalTextColor);
138a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung    }
139a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung
1404c98d9235d164680186180974719f551cf935d08Winson Chung    @Override
1414c98d9235d164680186180974719f551cf935d08Winson Chung    public boolean acceptDrop(DragObject d) {
1427c4c5108295db764ba091cc0ffd7af335a166449Adam Cohen        return willAcceptDrop(d.dragInfo);
1437c4c5108295db764ba091cc0ffd7af335a166449Adam Cohen    }
1447c4c5108295db764ba091cc0ffd7af335a166449Adam Cohen
1457c4c5108295db764ba091cc0ffd7af335a166449Adam Cohen    public static boolean willAcceptDrop(Object info) {
1467c4c5108295db764ba091cc0ffd7af335a166449Adam Cohen        if (info instanceof ItemInfo) {
1477c4c5108295db764ba091cc0ffd7af335a166449Adam Cohen            ItemInfo item = (ItemInfo) info;
1487c4c5108295db764ba091cc0ffd7af335a166449Adam Cohen            if (item.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET ||
1497c4c5108295db764ba091cc0ffd7af335a166449Adam Cohen                    item.itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT) {
1507c4c5108295db764ba091cc0ffd7af335a166449Adam Cohen                return true;
1517c4c5108295db764ba091cc0ffd7af335a166449Adam Cohen            }
152ed3d4df1f5e9042742293e172c89b8cf273e969aMichael Jurka
15316f3ea870aac47292cd6cbe1a4b4343173097aa9Nilesh Agrawal            if (!LauncherAppState.isDisableAllApps() &&
1545e7af5d790d54a7c2ec85e29b75a741962846b0fMichael Jurka                    item.itemType == LauncherSettings.Favorites.ITEM_TYPE_FOLDER) {
155ed3d4df1f5e9042742293e172c89b8cf273e969aMichael Jurka                return true;
156ed3d4df1f5e9042742293e172c89b8cf273e969aMichael Jurka            }
157ed3d4df1f5e9042742293e172c89b8cf273e969aMichael Jurka
15816f3ea870aac47292cd6cbe1a4b4343173097aa9Nilesh Agrawal            if (!LauncherAppState.isDisableAllApps() &&
1595e7af5d790d54a7c2ec85e29b75a741962846b0fMichael Jurka                    item.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION &&
1605e7af5d790d54a7c2ec85e29b75a741962846b0fMichael Jurka                    item instanceof AppInfo) {
1615e7af5d790d54a7c2ec85e29b75a741962846b0fMichael Jurka                AppInfo appInfo = (AppInfo) info;
1625e7af5d790d54a7c2ec85e29b75a741962846b0fMichael Jurka                return (appInfo.flags & AppInfo.DOWNLOADED_FLAG) != 0;
1635e7af5d790d54a7c2ec85e29b75a741962846b0fMichael Jurka            }
1645e7af5d790d54a7c2ec85e29b75a741962846b0fMichael Jurka
1659bd4d28163e3872de9c9019528cbb570f504fe05Michael Jurka            if (item.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION &&
1661e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka                item instanceof ShortcutInfo) {
16716f3ea870aac47292cd6cbe1a4b4343173097aa9Nilesh Agrawal                if (LauncherAppState.isDisableAllApps()) {
1689bd4d28163e3872de9c9019528cbb570f504fe05Michael Jurka                    ShortcutInfo shortcutInfo = (ShortcutInfo) info;
1699bd4d28163e3872de9c9019528cbb570f504fe05Michael Jurka                    return (shortcutInfo.flags & AppInfo.DOWNLOADED_FLAG) != 0;
1709bd4d28163e3872de9c9019528cbb570f504fe05Michael Jurka                } else {
1719bd4d28163e3872de9c9019528cbb570f504fe05Michael Jurka                    return true;
1729bd4d28163e3872de9c9019528cbb570f504fe05Michael Jurka                }
1731e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka            }
174947dc5431981e40ffc8d687604f7777d35915034Adam Cohen        }
1757c4c5108295db764ba091cc0ffd7af335a166449Adam Cohen        return false;
1764c98d9235d164680186180974719f551cf935d08Winson Chung    }
1774c98d9235d164680186180974719f551cf935d08Winson Chung
1784c98d9235d164680186180974719f551cf935d08Winson Chung    @Override
1794c98d9235d164680186180974719f551cf935d08Winson Chung    public void onDragStart(DragSource source, Object info, int dragAction) {
1804c98d9235d164680186180974719f551cf935d08Winson Chung        boolean isVisible = true;
18116f3ea870aac47292cd6cbe1a4b4343173097aa9Nilesh Agrawal        boolean useUninstallLabel = !LauncherAppState.isDisableAllApps() &&
182addcba65e94a11af24028b792cd1a8e02d563938Michael Jurka                isAllAppsApplication(source, info);
1831eeb3fc9d874d98dfb43883d17efb4202d83d88aMathew Inwood        boolean useDeleteLabel = !useUninstallLabel && source.supportsDeleteDropTarget();
1844c98d9235d164680186180974719f551cf935d08Winson Chung
1854c98d9235d164680186180974719f551cf935d08Winson Chung        // If we are dragging an application from AppsCustomize, only show the control if we can
186e01af631dc98fa3e97b01b4d3ac135cf7ca5917eWinson Chung        // delete the app (it was downloaded), and rename the string to "uninstall" in such a case.
187e01af631dc98fa3e97b01b4d3ac135cf7ca5917eWinson Chung        // Hide the delete target if it is a widget from AppsCustomize.
188e01af631dc98fa3e97b01b4d3ac135cf7ca5917eWinson Chung        if (!willAcceptDrop(info) || isAllAppsWidget(source, info)) {
189947dc5431981e40ffc8d687604f7777d35915034Adam Cohen            isVisible = false;
1904c98d9235d164680186180974719f551cf935d08Winson Chung        }
191950a467b180c78d3ce3bbe7b4a227a13d28b2536Jason Monk        if (useUninstallLabel) {
1926a2c77856f1cfa402363cfbb04b5718b431bbc6eJason Monk            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
1936a2c77856f1cfa402363cfbb04b5718b431bbc6eJason Monk                UserManager userManager = (UserManager)
1946a2c77856f1cfa402363cfbb04b5718b431bbc6eJason Monk                        getContext().getSystemService(Context.USER_SERVICE);
1956a2c77856f1cfa402363cfbb04b5718b431bbc6eJason Monk                Bundle restrictions = userManager.getUserRestrictions();
1966a2c77856f1cfa402363cfbb04b5718b431bbc6eJason Monk                if (restrictions.getBoolean(UserManager.DISALLOW_APPS_CONTROL, false)
1976a2c77856f1cfa402363cfbb04b5718b431bbc6eJason Monk                        || restrictions.getBoolean(UserManager.DISALLOW_UNINSTALL_APPS, false)) {
1986a2c77856f1cfa402363cfbb04b5718b431bbc6eJason Monk                    isVisible = false;
1996a2c77856f1cfa402363cfbb04b5718b431bbc6eJason Monk                }
200950a467b180c78d3ce3bbe7b4a227a13d28b2536Jason Monk            }
201950a467b180c78d3ce3bbe7b4a227a13d28b2536Jason Monk        }
2024c98d9235d164680186180974719f551cf935d08Winson Chung
203addcba65e94a11af24028b792cd1a8e02d563938Michael Jurka        if (useUninstallLabel) {
204d6a33c6f348d1316e0fdc519eda43468fcdcbfe7Fabrice Di Meglio            setCompoundDrawablesRelativeWithIntrinsicBounds(mUninstallDrawable, null, null, null);
2051eeb3fc9d874d98dfb43883d17efb4202d83d88aMathew Inwood        } else if (useDeleteLabel) {
206d6a33c6f348d1316e0fdc519eda43468fcdcbfe7Fabrice Di Meglio            setCompoundDrawablesRelativeWithIntrinsicBounds(mRemoveDrawable, null, null, null);
2071eeb3fc9d874d98dfb43883d17efb4202d83d88aMathew Inwood        } else {
2081eeb3fc9d874d98dfb43883d17efb4202d83d88aMathew Inwood            isVisible = false;
209ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen        }
210947245ba8ad74aee3dadd02693514765dbb4b5a2Winson Chung        mCurrentDrawable = (TransitionDrawable) getCurrentDrawable();
211ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen
2124c98d9235d164680186180974719f551cf935d08Winson Chung        mActive = isVisible;
213a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung        resetHoverColor();
214a6427b15c18d5b8f3078f553d78f8432de9f46e9Winson Chung        ((ViewGroup) getParent()).setVisibility(isVisible ? View.VISIBLE : View.GONE);
2151eeb3fc9d874d98dfb43883d17efb4202d83d88aMathew Inwood        if (isVisible && getText().length() > 0) {
216addcba65e94a11af24028b792cd1a8e02d563938Michael Jurka            setText(useUninstallLabel ? R.string.delete_target_uninstall_label
2174c98d9235d164680186180974719f551cf935d08Winson Chung                : R.string.delete_target_label);
2184c98d9235d164680186180974719f551cf935d08Winson Chung        }
2194c98d9235d164680186180974719f551cf935d08Winson Chung    }
2204c98d9235d164680186180974719f551cf935d08Winson Chung
2214c98d9235d164680186180974719f551cf935d08Winson Chung    @Override
2224c98d9235d164680186180974719f551cf935d08Winson Chung    public void onDragEnd() {
2234c98d9235d164680186180974719f551cf935d08Winson Chung        super.onDragEnd();
2244c98d9235d164680186180974719f551cf935d08Winson Chung        mActive = false;
2254c98d9235d164680186180974719f551cf935d08Winson Chung    }
2264c98d9235d164680186180974719f551cf935d08Winson Chung
2274c98d9235d164680186180974719f551cf935d08Winson Chung    public void onDragEnter(DragObject d) {
2284c98d9235d164680186180974719f551cf935d08Winson Chung        super.onDragEnter(d);
2294c98d9235d164680186180974719f551cf935d08Winson Chung
230a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung        setHoverColor();
2314c98d9235d164680186180974719f551cf935d08Winson Chung    }
2324c98d9235d164680186180974719f551cf935d08Winson Chung
2334c98d9235d164680186180974719f551cf935d08Winson Chung    public void onDragExit(DragObject d) {
2344c98d9235d164680186180974719f551cf935d08Winson Chung        super.onDragExit(d);
2354c98d9235d164680186180974719f551cf935d08Winson Chung
236aaa530adc9defb8c2b1599cae27bb268d58b2ddbWinson Chung        if (!d.dragComplete) {
237a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung            resetHoverColor();
23861967cb17f8fa9ee01f93e9f25a1074559b54cf3Winson Chung        } else {
23961967cb17f8fa9ee01f93e9f25a1074559b54cf3Winson Chung            // Restore the hover color if we are deleting
24061967cb17f8fa9ee01f93e9f25a1074559b54cf3Winson Chung            d.dragView.setColor(mHoverColor);
241aaa530adc9defb8c2b1599cae27bb268d58b2ddbWinson Chung        }
2424c98d9235d164680186180974719f551cf935d08Winson Chung    }
2434c98d9235d164680186180974719f551cf935d08Winson Chung
244ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen    private void animateToTrashAndCompleteDrop(final DragObject d) {
2451e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka        final DragLayer dragLayer = mLauncher.getDragLayer();
2461e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka        final Rect from = new Rect();
247ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen        dragLayer.getViewRectRelativeToSelf(d.dragView, from);
248fe9da818cde4d8be9903ad6ff42c7248ad54d822Adam Cohen
249fe9da818cde4d8be9903ad6ff42c7248ad54d822Adam Cohen        int width = mCurrentDrawable == null ? 0 : mCurrentDrawable.getIntrinsicWidth();
250fe9da818cde4d8be9903ad6ff42c7248ad54d822Adam Cohen        int height = mCurrentDrawable == null ? 0 : mCurrentDrawable.getIntrinsicHeight();
2511e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka        final Rect to = getIconRect(d.dragView.getMeasuredWidth(), d.dragView.getMeasuredHeight(),
252fe9da818cde4d8be9903ad6ff42c7248ad54d822Adam Cohen                width, height);
2531e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka        final float scale = (float) to.width() / from.width();
254ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen
255d4d7aa551ffdc80d810ff970fa72a6509960401eAdam Cohen        mSearchDropTargetBar.deferOnDragEnd();
2561e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka        deferCompleteDropIfUninstalling(d);
2571e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka
258d4d7aa551ffdc80d810ff970fa72a6509960401eAdam Cohen        Runnable onAnimationEndRunnable = new Runnable() {
259d4d7aa551ffdc80d810ff970fa72a6509960401eAdam Cohen            @Override
260d4d7aa551ffdc80d810ff970fa72a6509960401eAdam Cohen            public void run() {
2611e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka                completeDrop(d);
262d4d7aa551ffdc80d810ff970fa72a6509960401eAdam Cohen                mSearchDropTargetBar.onDragEnd();
2638498eb40ee7b09a977251cac7e2a8df12289cbedSunny Goyal                mLauncher.exitSpringLoadedDragModeDelayed(true, 0, null);
264d4d7aa551ffdc80d810ff970fa72a6509960401eAdam Cohen            }
265d4d7aa551ffdc80d810ff970fa72a6509960401eAdam Cohen        };
26661967cb17f8fa9ee01f93e9f25a1074559b54cf3Winson Chung        dragLayer.animateView(d.dragView, from, to, scale, 1f, 1f, 0.1f, 0.1f,
267d4d7aa551ffdc80d810ff970fa72a6509960401eAdam Cohen                DELETE_ANIMATION_DURATION, new DecelerateInterpolator(2),
26861967cb17f8fa9ee01f93e9f25a1074559b54cf3Winson Chung                new LinearInterpolator(), onAnimationEndRunnable,
269ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen                DragLayer.ANIMATION_END_DISAPPEAR, null);
270d4d7aa551ffdc80d810ff970fa72a6509960401eAdam Cohen    }
271d4d7aa551ffdc80d810ff970fa72a6509960401eAdam Cohen
2721e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka    private void deferCompleteDropIfUninstalling(DragObject d) {
2731e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka        mWaitingForUninstall = false;
2745e7af5d790d54a7c2ec85e29b75a741962846b0fMichael Jurka        if (isUninstallFromWorkspace(d)) {
2751e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka            if (d.dragSource instanceof Folder) {
2761e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka                ((Folder) d.dragSource).deferCompleteDropAfterUninstallActivity();
2771e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka            } else if (d.dragSource instanceof Workspace) {
2781e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka                ((Workspace) d.dragSource).deferCompleteDropAfterUninstallActivity();
2791e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka            }
2801e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka            mWaitingForUninstall = true;
2811e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka        }
2821e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka    }
2831e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka
2845e7af5d790d54a7c2ec85e29b75a741962846b0fMichael Jurka    private boolean isUninstallFromWorkspace(DragObject d) {
28516f3ea870aac47292cd6cbe1a4b4343173097aa9Nilesh Agrawal        if (LauncherAppState.isDisableAllApps() && isWorkspaceOrFolderApplication(d)) {
2865e7af5d790d54a7c2ec85e29b75a741962846b0fMichael Jurka            ShortcutInfo shortcut = (ShortcutInfo) d.dragInfo;
287dff0bfeb901e767ca9b57f9b8051c7fd077626e9Nilesh Agrawal            // Only allow manifest shortcuts to initiate an un-install.
288dff0bfeb901e767ca9b57f9b8051c7fd077626e9Nilesh Agrawal            return !InstallShortcutReceiver.isValidShortcutLaunchIntent(shortcut.intent);
2895e7af5d790d54a7c2ec85e29b75a741962846b0fMichael Jurka        }
2905e7af5d790d54a7c2ec85e29b75a741962846b0fMichael Jurka        return false;
2911e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka    }
2924c98d9235d164680186180974719f551cf935d08Winson Chung
293f3007589e346df224d357b389069adfeb266545eMichael Jurka    private void completeDrop(DragObject d) {
2941e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka        ItemInfo item = (ItemInfo) d.dragInfo;
2951e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka        boolean wasWaitingForUninstall = mWaitingForUninstall;
2961e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka        mWaitingForUninstall = false;
2974c98d9235d164680186180974719f551cf935d08Winson Chung        if (isAllAppsApplication(d.dragSource, item)) {
2984c98d9235d164680186180974719f551cf935d08Winson Chung            // Uninstall the application if it is being dragged from AppsCustomize
299eadbfc564d84aaf1d800da3d0d6edf6312f89648Michael Jurka            AppInfo appInfo = (AppInfo) item;
300d31df54073fbd80a9db9d277dde8c0e7421ffa14Kenny Guy            mLauncher.startApplicationUninstallActivity(appInfo.componentName, appInfo.flags,
301d31df54073fbd80a9db9d277dde8c0e7421ffa14Kenny Guy                    appInfo.user);
3025e7af5d790d54a7c2ec85e29b75a741962846b0fMichael Jurka        } else if (isUninstallFromWorkspace(d)) {
3031e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka            ShortcutInfo shortcut = (ShortcutInfo) item;
304d31df54073fbd80a9db9d277dde8c0e7421ffa14Kenny Guy            if (shortcut.intent != null && shortcut.intent.getComponent() != null) {
305f3007589e346df224d357b389069adfeb266545eMichael Jurka                final ComponentName componentName = shortcut.intent.getComponent();
306f3007589e346df224d357b389069adfeb266545eMichael Jurka                final DragSource dragSource = d.dragSource;
307d31df54073fbd80a9db9d277dde8c0e7421ffa14Kenny Guy                final UserHandleCompat user = shortcut.user;
308d31df54073fbd80a9db9d277dde8c0e7421ffa14Kenny Guy                mWaitingForUninstall = mLauncher.startApplicationUninstallActivity(
309d31df54073fbd80a9db9d277dde8c0e7421ffa14Kenny Guy                        componentName, shortcut.flags, user);
310f3007589e346df224d357b389069adfeb266545eMichael Jurka                if (mWaitingForUninstall) {
311f3007589e346df224d357b389069adfeb266545eMichael Jurka                    final Runnable checkIfUninstallWasSuccess = new Runnable() {
312f3007589e346df224d357b389069adfeb266545eMichael Jurka                        @Override
313f3007589e346df224d357b389069adfeb266545eMichael Jurka                        public void run() {
314f3007589e346df224d357b389069adfeb266545eMichael Jurka                            mWaitingForUninstall = false;
315f3007589e346df224d357b389069adfeb266545eMichael Jurka                            String packageName = componentName.getPackageName();
316ed13187a745866483139e2878037e1f8427ce567Kenny Guy                            boolean uninstallSuccessful = !AllAppsList.packageHasActivities(
317d31df54073fbd80a9db9d277dde8c0e7421ffa14Kenny Guy                                    getContext(), packageName, user);
318f3007589e346df224d357b389069adfeb266545eMichael Jurka                            if (dragSource instanceof Folder) {
319f3007589e346df224d357b389069adfeb266545eMichael Jurka                                ((Folder) dragSource).
320f3007589e346df224d357b389069adfeb266545eMichael Jurka                                    onUninstallActivityReturned(uninstallSuccessful);
321f3007589e346df224d357b389069adfeb266545eMichael Jurka                            } else if (dragSource instanceof Workspace) {
322f3007589e346df224d357b389069adfeb266545eMichael Jurka                                ((Workspace) dragSource).
323f3007589e346df224d357b389069adfeb266545eMichael Jurka                                    onUninstallActivityReturned(uninstallSuccessful);
324f3007589e346df224d357b389069adfeb266545eMichael Jurka                            }
325f3007589e346df224d357b389069adfeb266545eMichael Jurka                        }
326f3007589e346df224d357b389069adfeb266545eMichael Jurka                    };
327f3007589e346df224d357b389069adfeb266545eMichael Jurka                    mLauncher.addOnResumeCallback(checkIfUninstallWasSuccess);
328f3007589e346df224d357b389069adfeb266545eMichael Jurka                }
3291e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka            }
3300b4870db57f6e1d96e72d299cfc05dccb1735caaMichael Jurka        } else if (isWorkspaceOrFolderApplication(d)) {
3314c98d9235d164680186180974719f551cf935d08Winson Chung            LauncherModel.deleteItemFromDatabase(mLauncher, item);
3324c98d9235d164680186180974719f551cf935d08Winson Chung        } else if (isWorkspaceFolder(d)) {
3334c98d9235d164680186180974719f551cf935d08Winson Chung            // Remove the folder from the workspace and delete the contents from launcher model
3344c98d9235d164680186180974719f551cf935d08Winson Chung            FolderInfo folderInfo = (FolderInfo) item;
3354c98d9235d164680186180974719f551cf935d08Winson Chung            mLauncher.removeFolder(folderInfo);
3364c98d9235d164680186180974719f551cf935d08Winson Chung            LauncherModel.deleteFolderContentsFromDatabase(mLauncher, folderInfo);
3370b4870db57f6e1d96e72d299cfc05dccb1735caaMichael Jurka        } else if (isWorkspaceOrFolderWidget(d)) {
3384c98d9235d164680186180974719f551cf935d08Winson Chung            // Remove the widget from the workspace
3394c98d9235d164680186180974719f551cf935d08Winson Chung            mLauncher.removeAppWidget((LauncherAppWidgetInfo) item);
3404c98d9235d164680186180974719f551cf935d08Winson Chung            LauncherModel.deleteItemFromDatabase(mLauncher, item);
3414c98d9235d164680186180974719f551cf935d08Winson Chung
3424c98d9235d164680186180974719f551cf935d08Winson Chung            final LauncherAppWidgetInfo launcherAppWidgetInfo = (LauncherAppWidgetInfo) item;
3434c98d9235d164680186180974719f551cf935d08Winson Chung            final LauncherAppWidgetHost appWidgetHost = mLauncher.getAppWidgetHost();
344651077bdd603bb182be039925fd17bdf0da15016Sunny Goyal            if ((appWidgetHost != null) && launcherAppWidgetInfo.isWidgetIdValid()) {
3454c98d9235d164680186180974719f551cf935d08Winson Chung                // Deleting an app widget ID is a void call but writes to disk before returning
3464c98d9235d164680186180974719f551cf935d08Winson Chung                // to the caller...
3474346746ef37413168a5cbec46bb6db8f96b0123aMichael Jurka                new AsyncTask<Void, Void, Void>() {
3484346746ef37413168a5cbec46bb6db8f96b0123aMichael Jurka                    public Void doInBackground(Void ... args) {
3494c98d9235d164680186180974719f551cf935d08Winson Chung                        appWidgetHost.deleteAppWidgetId(launcherAppWidgetInfo.appWidgetId);
3504346746ef37413168a5cbec46bb6db8f96b0123aMichael Jurka                        return null;
3514c98d9235d164680186180974719f551cf935d08Winson Chung                    }
3524346746ef37413168a5cbec46bb6db8f96b0123aMichael Jurka                }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void) null);
3534c98d9235d164680186180974719f551cf935d08Winson Chung            }
3544c98d9235d164680186180974719f551cf935d08Winson Chung        }
3551e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka        if (wasWaitingForUninstall && !mWaitingForUninstall) {
3561e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka            if (d.dragSource instanceof Folder) {
3571e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka                ((Folder) d.dragSource).onUninstallActivityReturned(false);
3581e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka            } else if (d.dragSource instanceof Workspace) {
3591e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka                ((Workspace) d.dragSource).onUninstallActivityReturned(false);
3601e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka            }
3611e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka        }
3624c98d9235d164680186180974719f551cf935d08Winson Chung    }
363d4d7aa551ffdc80d810ff970fa72a6509960401eAdam Cohen
364d4d7aa551ffdc80d810ff970fa72a6509960401eAdam Cohen    public void onDrop(DragObject d) {
365d4d7aa551ffdc80d810ff970fa72a6509960401eAdam Cohen        animateToTrashAndCompleteDrop(d);
366d4d7aa551ffdc80d810ff970fa72a6509960401eAdam Cohen    }
367043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
368043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    /**
369043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung     * Creates an animation from the current drag view to the delete trash icon.
370043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung     */
371043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    private AnimatorUpdateListener createFlingToTrashAnimatorListener(final DragLayer dragLayer,
372043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            DragObject d, PointF vel, ViewConfiguration config) {
373fe9da818cde4d8be9903ad6ff42c7248ad54d822Adam Cohen
374fe9da818cde4d8be9903ad6ff42c7248ad54d822Adam Cohen        int width = mCurrentDrawable == null ? 0 : mCurrentDrawable.getIntrinsicWidth();
375fe9da818cde4d8be9903ad6ff42c7248ad54d822Adam Cohen        int height = mCurrentDrawable == null ? 0 : mCurrentDrawable.getIntrinsicHeight();
376043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        final Rect to = getIconRect(d.dragView.getMeasuredWidth(), d.dragView.getMeasuredHeight(),
377fe9da818cde4d8be9903ad6ff42c7248ad54d822Adam Cohen                width, height);
378043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        final Rect from = new Rect();
379043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        dragLayer.getViewRectRelativeToSelf(d.dragView, from);
380043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
381043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // Calculate how far along the velocity vector we should put the intermediate point on
382043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // the bezier curve
383043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        float velocity = Math.abs(vel.length());
384043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        float vp = Math.min(1f, velocity / (config.getScaledMaximumFlingVelocity() / 2f));
385043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        int offsetY = (int) (-from.top * vp);
386043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        int offsetX = (int) (offsetY / (vel.y / vel.x));
387043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        final float y2 = from.top + offsetY;                        // intermediate t/l
388043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        final float x2 = from.left + offsetX;
389043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        final float x1 = from.left;                                 // drag view t/l
390043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        final float y1 = from.top;
391043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        final float x3 = to.left;                                   // delete target t/l
392043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        final float y3 = to.top;
393043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
394043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        final TimeInterpolator scaleAlphaInterpolator = new TimeInterpolator() {
395043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            @Override
396043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            public float getInterpolation(float t) {
397043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                return t * t * t * t * t * t * t * t;
398043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            }
399043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        };
400043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        return new AnimatorUpdateListener() {
401043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            @Override
402043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            public void onAnimationUpdate(ValueAnimator animation) {
403043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                final DragView dragView = (DragView) dragLayer.getAnimatedView();
404043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                float t = ((Float) animation.getAnimatedValue()).floatValue();
405043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                float tp = scaleAlphaInterpolator.getInterpolation(t);
406043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                float initialScale = dragView.getInitialScale();
407043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                float finalAlpha = 0.5f;
408043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                float scale = dragView.getScaleX();
409043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                float x1o = ((1f - scale) * dragView.getMeasuredWidth()) / 2f;
410043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                float y1o = ((1f - scale) * dragView.getMeasuredHeight()) / 2f;
411043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                float x = (1f - t) * (1f - t) * (x1 - x1o) + 2 * (1f - t) * t * (x2 - x1o) +
412043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                        (t * t) * x3;
413043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                float y = (1f - t) * (1f - t) * (y1 - y1o) + 2 * (1f - t) * t * (y2 - x1o) +
414043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                        (t * t) * y3;
415043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
416043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                dragView.setTranslationX(x);
417043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                dragView.setTranslationY(y);
418043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                dragView.setScaleX(initialScale * (1f - tp));
419043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                dragView.setScaleY(initialScale * (1f - tp));
420043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                dragView.setAlpha(finalAlpha + (1f - finalAlpha) * (1f - tp));
421043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            }
422043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        };
423043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    }
424043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
425043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    /**
426043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung     * Creates an animation from the current drag view along its current velocity vector.
427043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung     * For this animation, the alpha runs for a fixed duration and we update the position
428043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung     * progressively.
429043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung     */
430043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    private static class FlingAlongVectorAnimatorUpdateListener implements AnimatorUpdateListener {
431043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        private DragLayer mDragLayer;
432043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        private PointF mVelocity;
433043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        private Rect mFrom;
434043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        private long mPrevTime;
435043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        private boolean mHasOffsetForScale;
4366e1bdaf4198f9eb7b4124550d3ad07da2a0226e4Winson Chung        private float mFriction;
437043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
4389658b1e65932f0149a596f451e0bd966e7ee4e74Winson Chung        private final TimeInterpolator mAlphaInterpolator = new DecelerateInterpolator(0.75f);
439043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
440043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        public FlingAlongVectorAnimatorUpdateListener(DragLayer dragLayer, PointF vel, Rect from,
4416e1bdaf4198f9eb7b4124550d3ad07da2a0226e4Winson Chung                long startTime, float friction) {
442043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            mDragLayer = dragLayer;
443043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            mVelocity = vel;
444043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            mFrom = from;
445043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            mPrevTime = startTime;
4466e1bdaf4198f9eb7b4124550d3ad07da2a0226e4Winson Chung            mFriction = 1f - (dragLayer.getResources().getDisplayMetrics().density * friction);
447043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        }
448043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
449043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        @Override
450043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        public void onAnimationUpdate(ValueAnimator animation) {
451043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            final DragView dragView = (DragView) mDragLayer.getAnimatedView();
452043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            float t = ((Float) animation.getAnimatedValue()).floatValue();
453043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            long curTime = AnimationUtils.currentAnimationTimeMillis();
454043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
455043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            if (!mHasOffsetForScale) {
456043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                mHasOffsetForScale = true;
457043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                float scale = dragView.getScaleX();
458043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                float xOffset = ((scale - 1f) * dragView.getMeasuredWidth()) / 2f;
459043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                float yOffset = ((scale - 1f) * dragView.getMeasuredHeight()) / 2f;
460043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
461043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                mFrom.left += xOffset;
462043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                mFrom.top += yOffset;
463043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            }
464043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
465043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            mFrom.left += (mVelocity.x * (curTime - mPrevTime) / 1000f);
466043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            mFrom.top += (mVelocity.y * (curTime - mPrevTime) / 1000f);
467043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
468043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            dragView.setTranslationX(mFrom.left);
469043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            dragView.setTranslationY(mFrom.top);
470043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            dragView.setAlpha(1f - mAlphaInterpolator.getInterpolation(t));
471043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
4726e1bdaf4198f9eb7b4124550d3ad07da2a0226e4Winson Chung            mVelocity.x *= mFriction;
4736e1bdaf4198f9eb7b4124550d3ad07da2a0226e4Winson Chung            mVelocity.y *= mFriction;
474043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            mPrevTime = curTime;
475043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        }
476043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    };
477043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    private AnimatorUpdateListener createFlingAlongVectorAnimatorListener(final DragLayer dragLayer,
478043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            DragObject d, PointF vel, final long startTime, final int duration,
479043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            ViewConfiguration config) {
480043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        final Rect from = new Rect();
481043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        dragLayer.getViewRectRelativeToSelf(d.dragView, from);
482043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
4836e1bdaf4198f9eb7b4124550d3ad07da2a0226e4Winson Chung        return new FlingAlongVectorAnimatorUpdateListener(dragLayer, vel, from, startTime,
4846e1bdaf4198f9eb7b4124550d3ad07da2a0226e4Winson Chung                FLING_TO_DELETE_FRICTION);
485043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    }
486043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
487043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    public void onFlingToDelete(final DragObject d, int x, int y, PointF vel) {
488a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung        final boolean isAllApps = d.dragSource instanceof AppsCustomizePagedView;
489a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung
490043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // Don't highlight the icon as it's animating
491043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        d.dragView.setColor(0);
492043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        d.dragView.updateInitialScaleToCurrentScale();
493a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung        // Don't highlight the target if we are flinging from AllApps
494a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung        if (isAllApps) {
495a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung            resetHoverColor();
496a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung        }
497043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
498043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        if (mFlingDeleteMode == MODE_FLING_DELETE_TO_TRASH) {
499043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            // Defer animating out the drop target if we are animating to it
500043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            mSearchDropTargetBar.deferOnDragEnd();
501043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            mSearchDropTargetBar.finishAnimations();
502043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        }
503043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
504043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        final ViewConfiguration config = ViewConfiguration.get(mLauncher);
505043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        final DragLayer dragLayer = mLauncher.getDragLayer();
5066e1bdaf4198f9eb7b4124550d3ad07da2a0226e4Winson Chung        final int duration = FLING_DELETE_ANIMATION_DURATION;
507043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        final long startTime = AnimationUtils.currentAnimationTimeMillis();
508043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
509043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // NOTE: Because it takes time for the first frame of animation to actually be
510043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // called and we expect the animation to be a continuation of the fling, we have
511043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // to account for the time that has elapsed since the fling finished.  And since
512043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // we don't have a startDelay, we will always get call to update when we call
513043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        // start() (which we want to ignore).
514043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        final TimeInterpolator tInterpolator = new TimeInterpolator() {
515043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            private int mCount = -1;
516043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            private float mOffset = 0f;
517043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung
518043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            @Override
519043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            public float getInterpolation(float t) {
520043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                if (mCount < 0) {
521043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                    mCount++;
522043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                } else if (mCount == 0) {
523043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                    mOffset = Math.min(0.5f, (float) (AnimationUtils.currentAnimationTimeMillis() -
524043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                            startTime) / duration);
525043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                    mCount++;
526043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                }
527043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                return Math.min(1f, mOffset + t);
528043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            }
529043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        };
530043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        AnimatorUpdateListener updateCb = null;
531043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        if (mFlingDeleteMode == MODE_FLING_DELETE_TO_TRASH) {
532043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            updateCb = createFlingToTrashAnimatorListener(dragLayer, d, vel, config);
533043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        } else if (mFlingDeleteMode == MODE_FLING_DELETE_ALONG_VECTOR) {
534043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            updateCb = createFlingAlongVectorAnimatorListener(dragLayer, d, vel, startTime,
535043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                    duration, config);
536043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        }
5371e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka        deferCompleteDropIfUninstalling(d);
5381e2f465f46ded990ea30516cdb7f0fcf3280411fMichael Jurka
539043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        Runnable onAnimationEndRunnable = new Runnable() {
540043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            @Override
541043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            public void run() {
542a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung                // If we are dragging from AllApps, then we allow AppsCustomizePagedView to clean up
543a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung                // itself, otherwise, complete the drop to initiate the deletion process
544a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung                if (!isAllApps) {
545a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung                    mLauncher.exitSpringLoadedDragMode();
546a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung                    completeDrop(d);
547a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung                }
548a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung                mLauncher.getDragController().onDeferredEndFling(d);
549043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung            }
550043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        };
551043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung        dragLayer.animateView(d.dragView, updateCb, duration, tInterpolator, onAnimationEndRunnable,
552043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung                DragLayer.ANIMATION_END_DISAPPEAR, null);
553043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung    }
5544c98d9235d164680186180974719f551cf935d08Winson Chung}
555