DeleteDropTarget.java revision 947245ba8ad74aee3dadd02693514765dbb4b5a2
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; 28947245ba8ad74aee3dadd02693514765dbb4b5a2Winson Chungimport android.graphics.drawable.Drawable; 29967289b6d5fec77f5c381d11ffb2319f3bb5e737Winson Chungimport android.graphics.drawable.TransitionDrawable; 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; 429658b1e65932f0149a596f451e0bd966e7ee4e74Winson Chung private static int FLIND_DELETE_ANIMATION_DURATION = 350; 43043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung private static int MODE_FLING_DELETE_TO_TRASH = 0; 44043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung private static int MODE_FLING_DELETE_ALONG_VECTOR = 1; 45043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 46043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung private final int mFlingDeleteMode = MODE_FLING_DELETE_ALONG_VECTOR; 474c98d9235d164680186180974719f551cf935d08Winson Chung 48a62e9fd95ae10cff4676f2cc1f4d68334ca27a0bWinson Chung private ColorStateList mOriginalTextColor; 49ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen private TransitionDrawable mUninstallDrawable; 50ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen private TransitionDrawable mRemoveDrawable; 51ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen private TransitionDrawable mCurrentDrawable; 524c98d9235d164680186180974719f551cf935d08Winson Chung 534c98d9235d164680186180974719f551cf935d08Winson Chung public DeleteDropTarget(Context context, AttributeSet attrs) { 544c98d9235d164680186180974719f551cf935d08Winson Chung this(context, attrs, 0); 554c98d9235d164680186180974719f551cf935d08Winson Chung } 564c98d9235d164680186180974719f551cf935d08Winson Chung 574c98d9235d164680186180974719f551cf935d08Winson Chung public DeleteDropTarget(Context context, AttributeSet attrs, int defStyle) { 584c98d9235d164680186180974719f551cf935d08Winson Chung super(context, attrs, defStyle); 594c98d9235d164680186180974719f551cf935d08Winson Chung } 604c98d9235d164680186180974719f551cf935d08Winson Chung 614c98d9235d164680186180974719f551cf935d08Winson Chung @Override 624c98d9235d164680186180974719f551cf935d08Winson Chung protected void onFinishInflate() { 634c98d9235d164680186180974719f551cf935d08Winson Chung super.onFinishInflate(); 644c98d9235d164680186180974719f551cf935d08Winson Chung 654c98d9235d164680186180974719f551cf935d08Winson Chung // Get the drawable 66a6427b15c18d5b8f3078f553d78f8432de9f46e9Winson Chung mOriginalTextColor = getTextColors(); 674c98d9235d164680186180974719f551cf935d08Winson Chung 684c98d9235d164680186180974719f551cf935d08Winson Chung // Get the hover color 694c98d9235d164680186180974719f551cf935d08Winson Chung Resources r = getResources(); 704c98d9235d164680186180974719f551cf935d08Winson Chung mHoverColor = r.getColor(R.color.delete_target_hover_tint); 71ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen mUninstallDrawable = (TransitionDrawable) 72ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen r.getDrawable(R.drawable.uninstall_target_selector); 73ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen mRemoveDrawable = (TransitionDrawable) r.getDrawable(R.drawable.remove_target_selector); 74ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen 75ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen mRemoveDrawable.setCrossFadeEnabled(true); 76ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen mUninstallDrawable.setCrossFadeEnabled(true); 77ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen 78ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen // The current drawable is set to either the remove drawable or the uninstall drawable 79ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen // and is initially set to the remove drawable, as set in the layout xml. 80947245ba8ad74aee3dadd02693514765dbb4b5a2Winson Chung mCurrentDrawable = (TransitionDrawable) getCurrentDrawable(); 81201bc828d5a0078f505e8e37152156a0cb43c10aWinson Chung 82201bc828d5a0078f505e8e37152156a0cb43c10aWinson Chung // Remove the text in the Phone UI in landscape 83201bc828d5a0078f505e8e37152156a0cb43c10aWinson Chung int orientation = getResources().getConfiguration().orientation; 84201bc828d5a0078f505e8e37152156a0cb43c10aWinson Chung if (orientation == Configuration.ORIENTATION_LANDSCAPE) { 85201bc828d5a0078f505e8e37152156a0cb43c10aWinson Chung if (!LauncherApplication.isScreenLarge()) { 86a6427b15c18d5b8f3078f553d78f8432de9f46e9Winson Chung setText(""); 87201bc828d5a0078f505e8e37152156a0cb43c10aWinson Chung } 88201bc828d5a0078f505e8e37152156a0cb43c10aWinson Chung } 894c98d9235d164680186180974719f551cf935d08Winson Chung } 904c98d9235d164680186180974719f551cf935d08Winson Chung 914c98d9235d164680186180974719f551cf935d08Winson Chung private boolean isAllAppsApplication(DragSource source, Object info) { 924c98d9235d164680186180974719f551cf935d08Winson Chung return (source instanceof AppsCustomizePagedView) && (info instanceof ApplicationInfo); 934c98d9235d164680186180974719f551cf935d08Winson Chung } 944c98d9235d164680186180974719f551cf935d08Winson Chung private boolean isAllAppsWidget(DragSource source, Object info) { 9511a4937fbff0dbc50fb022513dc3b6c643154445Winson Chung if (source instanceof AppsCustomizePagedView) { 9611a4937fbff0dbc50fb022513dc3b6c643154445Winson Chung if (info instanceof PendingAddItemInfo) { 9711a4937fbff0dbc50fb022513dc3b6c643154445Winson Chung PendingAddItemInfo addInfo = (PendingAddItemInfo) info; 9811a4937fbff0dbc50fb022513dc3b6c643154445Winson Chung switch (addInfo.itemType) { 9911a4937fbff0dbc50fb022513dc3b6c643154445Winson Chung case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT: 10011a4937fbff0dbc50fb022513dc3b6c643154445Winson Chung case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET: 10111a4937fbff0dbc50fb022513dc3b6c643154445Winson Chung return true; 10211a4937fbff0dbc50fb022513dc3b6c643154445Winson Chung } 10311a4937fbff0dbc50fb022513dc3b6c643154445Winson Chung } 10411a4937fbff0dbc50fb022513dc3b6c643154445Winson Chung } 10511a4937fbff0dbc50fb022513dc3b6c643154445Winson Chung return false; 1064c98d9235d164680186180974719f551cf935d08Winson Chung } 1070b4870db57f6e1d96e72d299cfc05dccb1735caaMichael Jurka private boolean isDragSourceWorkspaceOrFolder(DragObject d) { 1080b4870db57f6e1d96e72d299cfc05dccb1735caaMichael Jurka return (d.dragSource instanceof Workspace) || (d.dragSource instanceof Folder); 1094c98d9235d164680186180974719f551cf935d08Winson Chung } 1100b4870db57f6e1d96e72d299cfc05dccb1735caaMichael Jurka private boolean isWorkspaceOrFolderApplication(DragObject d) { 1110b4870db57f6e1d96e72d299cfc05dccb1735caaMichael Jurka return isDragSourceWorkspaceOrFolder(d) && (d.dragInfo instanceof ShortcutInfo); 1120b4870db57f6e1d96e72d299cfc05dccb1735caaMichael Jurka } 1130b4870db57f6e1d96e72d299cfc05dccb1735caaMichael Jurka private boolean isWorkspaceOrFolderWidget(DragObject d) { 1140b4870db57f6e1d96e72d299cfc05dccb1735caaMichael Jurka return isDragSourceWorkspaceOrFolder(d) && (d.dragInfo instanceof LauncherAppWidgetInfo); 1154c98d9235d164680186180974719f551cf935d08Winson Chung } 1164c98d9235d164680186180974719f551cf935d08Winson Chung private boolean isWorkspaceFolder(DragObject d) { 1174c98d9235d164680186180974719f551cf935d08Winson Chung return (d.dragSource instanceof Workspace) && (d.dragInfo instanceof FolderInfo); 1184c98d9235d164680186180974719f551cf935d08Winson Chung } 1194c98d9235d164680186180974719f551cf935d08Winson Chung 120a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung private void setHoverColor() { 121a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung mCurrentDrawable.startTransition(mTransitionDuration); 122a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung setTextColor(mHoverColor); 123a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung } 124a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung private void resetHoverColor() { 125a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung mCurrentDrawable.resetTransition(); 126a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung setTextColor(mOriginalTextColor); 127a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung } 128a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung 1294c98d9235d164680186180974719f551cf935d08Winson Chung @Override 1304c98d9235d164680186180974719f551cf935d08Winson Chung public boolean acceptDrop(DragObject d) { 1314c98d9235d164680186180974719f551cf935d08Winson Chung // We can remove everything including App shortcuts, folders, widgets, etc. 1324c98d9235d164680186180974719f551cf935d08Winson Chung return true; 1334c98d9235d164680186180974719f551cf935d08Winson Chung } 1344c98d9235d164680186180974719f551cf935d08Winson Chung 1354c98d9235d164680186180974719f551cf935d08Winson Chung @Override 1364c98d9235d164680186180974719f551cf935d08Winson Chung public void onDragStart(DragSource source, Object info, int dragAction) { 1374c98d9235d164680186180974719f551cf935d08Winson Chung boolean isVisible = true; 1384c98d9235d164680186180974719f551cf935d08Winson Chung boolean isUninstall = false; 1394c98d9235d164680186180974719f551cf935d08Winson Chung 140f0ea4d3378be7b962c8e0bce2392df5e82491fb8Winson Chung // If we are dragging a widget from AppsCustomize, hide the delete target 1414c98d9235d164680186180974719f551cf935d08Winson Chung if (isAllAppsWidget(source, info)) { 1424c98d9235d164680186180974719f551cf935d08Winson Chung isVisible = false; 1434c98d9235d164680186180974719f551cf935d08Winson Chung } 1444c98d9235d164680186180974719f551cf935d08Winson Chung 1454c98d9235d164680186180974719f551cf935d08Winson Chung // If we are dragging an application from AppsCustomize, only show the control if we can 1464c98d9235d164680186180974719f551cf935d08Winson Chung // delete the app (it was downloaded), and rename the string to "uninstall" in such a case 1474c98d9235d164680186180974719f551cf935d08Winson Chung if (isAllAppsApplication(source, info)) { 1484c98d9235d164680186180974719f551cf935d08Winson Chung ApplicationInfo appInfo = (ApplicationInfo) info; 1494c98d9235d164680186180974719f551cf935d08Winson Chung if ((appInfo.flags & ApplicationInfo.DOWNLOADED_FLAG) != 0) { 1504c98d9235d164680186180974719f551cf935d08Winson Chung isUninstall = true; 1514c98d9235d164680186180974719f551cf935d08Winson Chung } else { 1524c98d9235d164680186180974719f551cf935d08Winson Chung isVisible = false; 1534c98d9235d164680186180974719f551cf935d08Winson Chung } 1544c98d9235d164680186180974719f551cf935d08Winson Chung } 1554c98d9235d164680186180974719f551cf935d08Winson Chung 156ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen if (isUninstall) { 157ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen setCompoundDrawablesWithIntrinsicBounds(mUninstallDrawable, null, null, null); 158ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen } else { 159ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen setCompoundDrawablesWithIntrinsicBounds(mRemoveDrawable, null, null, null); 160ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen } 161947245ba8ad74aee3dadd02693514765dbb4b5a2Winson Chung mCurrentDrawable = (TransitionDrawable) getCurrentDrawable(); 162ebea84d1c95f4c38ba8cee46cd586fd757b4fce2Adam Cohen 1634c98d9235d164680186180974719f551cf935d08Winson Chung mActive = isVisible; 164a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung resetHoverColor(); 165a6427b15c18d5b8f3078f553d78f8432de9f46e9Winson Chung ((ViewGroup) getParent()).setVisibility(isVisible ? View.VISIBLE : View.GONE); 166a6427b15c18d5b8f3078f553d78f8432de9f46e9Winson Chung if (getText().length() > 0) { 167a6427b15c18d5b8f3078f553d78f8432de9f46e9Winson Chung setText(isUninstall ? R.string.delete_target_uninstall_label 1684c98d9235d164680186180974719f551cf935d08Winson Chung : R.string.delete_target_label); 1694c98d9235d164680186180974719f551cf935d08Winson Chung } 1704c98d9235d164680186180974719f551cf935d08Winson Chung } 1714c98d9235d164680186180974719f551cf935d08Winson Chung 1724c98d9235d164680186180974719f551cf935d08Winson Chung @Override 1734c98d9235d164680186180974719f551cf935d08Winson Chung public void onDragEnd() { 1744c98d9235d164680186180974719f551cf935d08Winson Chung super.onDragEnd(); 1754c98d9235d164680186180974719f551cf935d08Winson Chung mActive = false; 1764c98d9235d164680186180974719f551cf935d08Winson Chung } 1774c98d9235d164680186180974719f551cf935d08Winson Chung 1784c98d9235d164680186180974719f551cf935d08Winson Chung public void onDragEnter(DragObject d) { 1794c98d9235d164680186180974719f551cf935d08Winson Chung super.onDragEnter(d); 1804c98d9235d164680186180974719f551cf935d08Winson Chung 181a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung setHoverColor(); 1824c98d9235d164680186180974719f551cf935d08Winson Chung } 1834c98d9235d164680186180974719f551cf935d08Winson Chung 1844c98d9235d164680186180974719f551cf935d08Winson Chung public void onDragExit(DragObject d) { 1854c98d9235d164680186180974719f551cf935d08Winson Chung super.onDragExit(d); 1864c98d9235d164680186180974719f551cf935d08Winson Chung 187aaa530adc9defb8c2b1599cae27bb268d58b2ddbWinson Chung if (!d.dragComplete) { 188a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung resetHoverColor(); 18961967cb17f8fa9ee01f93e9f25a1074559b54cf3Winson Chung } else { 19061967cb17f8fa9ee01f93e9f25a1074559b54cf3Winson Chung // Restore the hover color if we are deleting 19161967cb17f8fa9ee01f93e9f25a1074559b54cf3Winson Chung d.dragView.setColor(mHoverColor); 192aaa530adc9defb8c2b1599cae27bb268d58b2ddbWinson Chung } 1934c98d9235d164680186180974719f551cf935d08Winson Chung } 1944c98d9235d164680186180974719f551cf935d08Winson Chung 195ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen private void animateToTrashAndCompleteDrop(final DragObject d) { 196ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen DragLayer dragLayer = mLauncher.getDragLayer(); 197ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen Rect from = new Rect(); 198ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen dragLayer.getViewRectRelativeToSelf(d.dragView, from); 19961967cb17f8fa9ee01f93e9f25a1074559b54cf3Winson Chung Rect to = getIconRect(d.dragView.getMeasuredWidth(), d.dragView.getMeasuredHeight(), 20061967cb17f8fa9ee01f93e9f25a1074559b54cf3Winson Chung mCurrentDrawable.getIntrinsicWidth(), mCurrentDrawable.getIntrinsicHeight()); 20161967cb17f8fa9ee01f93e9f25a1074559b54cf3Winson Chung float scale = (float) to.width() / from.width(); 202ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen 203d4d7aa551ffdc80d810ff970fa72a6509960401eAdam Cohen mSearchDropTargetBar.deferOnDragEnd(); 204d4d7aa551ffdc80d810ff970fa72a6509960401eAdam Cohen Runnable onAnimationEndRunnable = new Runnable() { 205d4d7aa551ffdc80d810ff970fa72a6509960401eAdam Cohen @Override 206d4d7aa551ffdc80d810ff970fa72a6509960401eAdam Cohen public void run() { 207d4d7aa551ffdc80d810ff970fa72a6509960401eAdam Cohen mSearchDropTargetBar.onDragEnd(); 208d4d7aa551ffdc80d810ff970fa72a6509960401eAdam Cohen mLauncher.exitSpringLoadedDragMode(); 209d4d7aa551ffdc80d810ff970fa72a6509960401eAdam Cohen completeDrop(d); 210d4d7aa551ffdc80d810ff970fa72a6509960401eAdam Cohen } 211d4d7aa551ffdc80d810ff970fa72a6509960401eAdam Cohen }; 21261967cb17f8fa9ee01f93e9f25a1074559b54cf3Winson Chung dragLayer.animateView(d.dragView, from, to, scale, 1f, 1f, 0.1f, 0.1f, 213d4d7aa551ffdc80d810ff970fa72a6509960401eAdam Cohen DELETE_ANIMATION_DURATION, new DecelerateInterpolator(2), 21461967cb17f8fa9ee01f93e9f25a1074559b54cf3Winson Chung new LinearInterpolator(), onAnimationEndRunnable, 215ed66b2bac7447febe2e405b4ce725cae4f6b5988Adam Cohen DragLayer.ANIMATION_END_DISAPPEAR, null); 216d4d7aa551ffdc80d810ff970fa72a6509960401eAdam Cohen } 217d4d7aa551ffdc80d810ff970fa72a6509960401eAdam Cohen 218d4d7aa551ffdc80d810ff970fa72a6509960401eAdam Cohen private void completeDrop(DragObject d) { 2194c98d9235d164680186180974719f551cf935d08Winson Chung ItemInfo item = (ItemInfo) d.dragInfo; 2204c98d9235d164680186180974719f551cf935d08Winson Chung 2214c98d9235d164680186180974719f551cf935d08Winson Chung if (isAllAppsApplication(d.dragSource, item)) { 2224c98d9235d164680186180974719f551cf935d08Winson Chung // Uninstall the application if it is being dragged from AppsCustomize 2234c98d9235d164680186180974719f551cf935d08Winson Chung mLauncher.startApplicationUninstallActivity((ApplicationInfo) item); 2240b4870db57f6e1d96e72d299cfc05dccb1735caaMichael Jurka } else if (isWorkspaceOrFolderApplication(d)) { 2254c98d9235d164680186180974719f551cf935d08Winson Chung LauncherModel.deleteItemFromDatabase(mLauncher, item); 2264c98d9235d164680186180974719f551cf935d08Winson Chung } else if (isWorkspaceFolder(d)) { 2274c98d9235d164680186180974719f551cf935d08Winson Chung // Remove the folder from the workspace and delete the contents from launcher model 2284c98d9235d164680186180974719f551cf935d08Winson Chung FolderInfo folderInfo = (FolderInfo) item; 2294c98d9235d164680186180974719f551cf935d08Winson Chung mLauncher.removeFolder(folderInfo); 2304c98d9235d164680186180974719f551cf935d08Winson Chung LauncherModel.deleteFolderContentsFromDatabase(mLauncher, folderInfo); 2310b4870db57f6e1d96e72d299cfc05dccb1735caaMichael Jurka } else if (isWorkspaceOrFolderWidget(d)) { 2324c98d9235d164680186180974719f551cf935d08Winson Chung // Remove the widget from the workspace 2334c98d9235d164680186180974719f551cf935d08Winson Chung mLauncher.removeAppWidget((LauncherAppWidgetInfo) item); 2344c98d9235d164680186180974719f551cf935d08Winson Chung LauncherModel.deleteItemFromDatabase(mLauncher, item); 2354c98d9235d164680186180974719f551cf935d08Winson Chung 2364c98d9235d164680186180974719f551cf935d08Winson Chung final LauncherAppWidgetInfo launcherAppWidgetInfo = (LauncherAppWidgetInfo) item; 2374c98d9235d164680186180974719f551cf935d08Winson Chung final LauncherAppWidgetHost appWidgetHost = mLauncher.getAppWidgetHost(); 2384c98d9235d164680186180974719f551cf935d08Winson Chung if (appWidgetHost != null) { 2394c98d9235d164680186180974719f551cf935d08Winson Chung // Deleting an app widget ID is a void call but writes to disk before returning 2404c98d9235d164680186180974719f551cf935d08Winson Chung // to the caller... 2414c98d9235d164680186180974719f551cf935d08Winson Chung new Thread("deleteAppWidgetId") { 2424c98d9235d164680186180974719f551cf935d08Winson Chung public void run() { 2434c98d9235d164680186180974719f551cf935d08Winson Chung appWidgetHost.deleteAppWidgetId(launcherAppWidgetInfo.appWidgetId); 2444c98d9235d164680186180974719f551cf935d08Winson Chung } 2454c98d9235d164680186180974719f551cf935d08Winson Chung }.start(); 2464c98d9235d164680186180974719f551cf935d08Winson Chung } 2474c98d9235d164680186180974719f551cf935d08Winson Chung } 2484c98d9235d164680186180974719f551cf935d08Winson Chung } 249d4d7aa551ffdc80d810ff970fa72a6509960401eAdam Cohen 250d4d7aa551ffdc80d810ff970fa72a6509960401eAdam Cohen public void onDrop(DragObject d) { 251d4d7aa551ffdc80d810ff970fa72a6509960401eAdam Cohen animateToTrashAndCompleteDrop(d); 252d4d7aa551ffdc80d810ff970fa72a6509960401eAdam Cohen } 253043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 254043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung /** 255043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung * Creates an animation from the current drag view to the delete trash icon. 256043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung */ 257043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung private AnimatorUpdateListener createFlingToTrashAnimatorListener(final DragLayer dragLayer, 258043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung DragObject d, PointF vel, ViewConfiguration config) { 259043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung final Rect to = getIconRect(d.dragView.getMeasuredWidth(), d.dragView.getMeasuredHeight(), 260043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mCurrentDrawable.getIntrinsicWidth(), mCurrentDrawable.getIntrinsicHeight()); 261043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung final Rect from = new Rect(); 262043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung dragLayer.getViewRectRelativeToSelf(d.dragView, from); 263043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 264043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung // Calculate how far along the velocity vector we should put the intermediate point on 265043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung // the bezier curve 266043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung float velocity = Math.abs(vel.length()); 267043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung float vp = Math.min(1f, velocity / (config.getScaledMaximumFlingVelocity() / 2f)); 268043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung int offsetY = (int) (-from.top * vp); 269043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung int offsetX = (int) (offsetY / (vel.y / vel.x)); 270043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung final float y2 = from.top + offsetY; // intermediate t/l 271043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung final float x2 = from.left + offsetX; 272043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung final float x1 = from.left; // drag view t/l 273043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung final float y1 = from.top; 274043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung final float x3 = to.left; // delete target t/l 275043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung final float y3 = to.top; 276043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 277043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung final TimeInterpolator scaleAlphaInterpolator = new TimeInterpolator() { 278043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung @Override 279043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung public float getInterpolation(float t) { 280043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung return t * t * t * t * t * t * t * t; 281043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung } 282043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung }; 283043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung return new AnimatorUpdateListener() { 284043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung @Override 285043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung public void onAnimationUpdate(ValueAnimator animation) { 286043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung final DragView dragView = (DragView) dragLayer.getAnimatedView(); 287043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung float t = ((Float) animation.getAnimatedValue()).floatValue(); 288043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung float tp = scaleAlphaInterpolator.getInterpolation(t); 289043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung float initialScale = dragView.getInitialScale(); 290043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung float finalAlpha = 0.5f; 291043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung float scale = dragView.getScaleX(); 292043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung float x1o = ((1f - scale) * dragView.getMeasuredWidth()) / 2f; 293043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung float y1o = ((1f - scale) * dragView.getMeasuredHeight()) / 2f; 294043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung float x = (1f - t) * (1f - t) * (x1 - x1o) + 2 * (1f - t) * t * (x2 - x1o) + 295043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung (t * t) * x3; 296043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung float y = (1f - t) * (1f - t) * (y1 - y1o) + 2 * (1f - t) * t * (y2 - x1o) + 297043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung (t * t) * y3; 298043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 299043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung dragView.setTranslationX(x); 300043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung dragView.setTranslationY(y); 301043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung dragView.setScaleX(initialScale * (1f - tp)); 302043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung dragView.setScaleY(initialScale * (1f - tp)); 303043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung dragView.setAlpha(finalAlpha + (1f - finalAlpha) * (1f - tp)); 304043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung } 305043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung }; 306043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung } 307043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 308043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung /** 309043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung * Creates an animation from the current drag view along its current velocity vector. 310043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung * For this animation, the alpha runs for a fixed duration and we update the position 311043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung * progressively. 312043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung */ 313043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung private static class FlingAlongVectorAnimatorUpdateListener implements AnimatorUpdateListener { 314043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung private static float FRICTION = 0.93f; 315043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 316043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung private DragLayer mDragLayer; 317043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung private PointF mVelocity; 318043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung private Rect mFrom; 319043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung private long mPrevTime; 320043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung private boolean mHasOffsetForScale; 321043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 3229658b1e65932f0149a596f451e0bd966e7ee4e74Winson Chung private final TimeInterpolator mAlphaInterpolator = new DecelerateInterpolator(0.75f); 323043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 324043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung public FlingAlongVectorAnimatorUpdateListener(DragLayer dragLayer, PointF vel, Rect from, 325043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung long startTime) { 326043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mDragLayer = dragLayer; 327043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mVelocity = vel; 328043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mFrom = from; 329043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mPrevTime = startTime; 330043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung } 331043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 332043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung @Override 333043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung public void onAnimationUpdate(ValueAnimator animation) { 334043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung final DragView dragView = (DragView) mDragLayer.getAnimatedView(); 335043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung float t = ((Float) animation.getAnimatedValue()).floatValue(); 336043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung long curTime = AnimationUtils.currentAnimationTimeMillis(); 337043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 338043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung if (!mHasOffsetForScale) { 339043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mHasOffsetForScale = true; 340043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung float scale = dragView.getScaleX(); 341043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung float xOffset = ((scale - 1f) * dragView.getMeasuredWidth()) / 2f; 342043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung float yOffset = ((scale - 1f) * dragView.getMeasuredHeight()) / 2f; 343043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 344043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mFrom.left += xOffset; 345043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mFrom.top += yOffset; 346043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung } 347043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 348043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mFrom.left += (mVelocity.x * (curTime - mPrevTime) / 1000f); 349043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mFrom.top += (mVelocity.y * (curTime - mPrevTime) / 1000f); 350043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 351043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung dragView.setTranslationX(mFrom.left); 352043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung dragView.setTranslationY(mFrom.top); 353043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung dragView.setAlpha(1f - mAlphaInterpolator.getInterpolation(t)); 354043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 355043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mVelocity.x *= FRICTION; 356043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mVelocity.y *= FRICTION; 357043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mPrevTime = curTime; 358043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung } 359043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung }; 360043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung private AnimatorUpdateListener createFlingAlongVectorAnimatorListener(final DragLayer dragLayer, 361043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung DragObject d, PointF vel, final long startTime, final int duration, 362043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung ViewConfiguration config) { 363043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung final Rect from = new Rect(); 364043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung dragLayer.getViewRectRelativeToSelf(d.dragView, from); 365043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 366043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung return new FlingAlongVectorAnimatorUpdateListener(dragLayer, vel, from, startTime); 367043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung } 368043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 369043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung public void onFlingToDelete(final DragObject d, int x, int y, PointF vel) { 370a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung final boolean isAllApps = d.dragSource instanceof AppsCustomizePagedView; 371a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung 372043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung // Don't highlight the icon as it's animating 373043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung d.dragView.setColor(0); 374043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung d.dragView.updateInitialScaleToCurrentScale(); 375a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung // Don't highlight the target if we are flinging from AllApps 376a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung if (isAllApps) { 377a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung resetHoverColor(); 378a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung } 379043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 380043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung if (mFlingDeleteMode == MODE_FLING_DELETE_TO_TRASH) { 381043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung // Defer animating out the drop target if we are animating to it 382043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mSearchDropTargetBar.deferOnDragEnd(); 383043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mSearchDropTargetBar.finishAnimations(); 384043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung } 385043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 386043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung final ViewConfiguration config = ViewConfiguration.get(mLauncher); 387043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung final DragLayer dragLayer = mLauncher.getDragLayer(); 3889658b1e65932f0149a596f451e0bd966e7ee4e74Winson Chung final int duration = FLIND_DELETE_ANIMATION_DURATION; 389043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung final long startTime = AnimationUtils.currentAnimationTimeMillis(); 390043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 391043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung // NOTE: Because it takes time for the first frame of animation to actually be 392043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung // called and we expect the animation to be a continuation of the fling, we have 393043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung // to account for the time that has elapsed since the fling finished. And since 394043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung // we don't have a startDelay, we will always get call to update when we call 395043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung // start() (which we want to ignore). 396043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung final TimeInterpolator tInterpolator = new TimeInterpolator() { 397043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung private int mCount = -1; 398043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung private float mOffset = 0f; 399043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung 400043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung @Override 401043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung public float getInterpolation(float t) { 402043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung if (mCount < 0) { 403043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mCount++; 404043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung } else if (mCount == 0) { 405043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mOffset = Math.min(0.5f, (float) (AnimationUtils.currentAnimationTimeMillis() - 406043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung startTime) / duration); 407043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mCount++; 408043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung } 409043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung return Math.min(1f, mOffset + t); 410043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung } 411043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung }; 412043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung AnimatorUpdateListener updateCb = null; 413043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung if (mFlingDeleteMode == MODE_FLING_DELETE_TO_TRASH) { 414043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung updateCb = createFlingToTrashAnimatorListener(dragLayer, d, vel, config); 415043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung } else if (mFlingDeleteMode == MODE_FLING_DELETE_ALONG_VECTOR) { 416043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung updateCb = createFlingAlongVectorAnimatorListener(dragLayer, d, vel, startTime, 417043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung duration, config); 418043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung } 419043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung Runnable onAnimationEndRunnable = new Runnable() { 420043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung @Override 421043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung public void run() { 422043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung mSearchDropTargetBar.onDragEnd(); 423a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung 424a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung // If we are dragging from AllApps, then we allow AppsCustomizePagedView to clean up 425a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung // itself, otherwise, complete the drop to initiate the deletion process 426a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung if (!isAllApps) { 427a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung mLauncher.exitSpringLoadedDragMode(); 428a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung completeDrop(d); 429a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung } 430a48487a814c07a9f1f45eb3ffe3d873b3dc31b3bWinson Chung mLauncher.getDragController().onDeferredEndFling(d); 431043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung } 432043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung }; 433043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung dragLayer.animateView(d.dragView, updateCb, duration, tInterpolator, onAnimationEndRunnable, 434043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung DragLayer.ANIMATION_END_DISAPPEAR, null); 435043f2af567178b82b0b41f12d379e7dd12da2936Winson Chung } 4364c98d9235d164680186180974719f551cf935d08Winson Chung} 437