1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.launcher2; 18 19 import android.widget.ImageView; 20 import android.content.Context; 21 import android.content.res.TypedArray; 22 import android.graphics.Paint; 23 import android.graphics.PorterDuff; 24 import android.graphics.PorterDuffColorFilter; 25 import android.graphics.Rect; 26 import android.util.AttributeSet; 27 import android.view.View; 28 import android.view.animation.TranslateAnimation; 29 import android.view.animation.Animation; 30 import android.view.animation.AnimationSet; 31 import android.view.animation.AccelerateInterpolator; 32 import android.view.animation.AlphaAnimation; 33 import android.graphics.RectF; 34 import android.graphics.drawable.TransitionDrawable; 35 36 import com.android.launcher.R; 37 38 public class DeleteZone extends ImageView implements DropTarget, DragController.DragListener { 39 private static final int ORIENTATION_HORIZONTAL = 1; 40 private static final int TRANSITION_DURATION = 250; 41 private static final int ANIMATION_DURATION = 200; 42 43 private final int[] mLocation = new int[2]; 44 45 private Launcher mLauncher; 46 private boolean mTrashMode; 47 48 private AnimationSet mInAnimation; 49 private AnimationSet mOutAnimation; 50 private Animation mHandleInAnimation; 51 private Animation mHandleOutAnimation; 52 53 private int mOrientation; 54 private DragController mDragController; 55 56 private final RectF mRegion = new RectF(); 57 private TransitionDrawable mTransition; 58 private View mHandle; 59 private final Paint mTrashPaint = new Paint(); 60 DeleteZone(Context context, AttributeSet attrs)61 public DeleteZone(Context context, AttributeSet attrs) { 62 this(context, attrs, 0); 63 } 64 DeleteZone(Context context, AttributeSet attrs, int defStyle)65 public DeleteZone(Context context, AttributeSet attrs, int defStyle) { 66 super(context, attrs, defStyle); 67 68 final int srcColor = context.getResources().getColor(R.color.delete_color_filter); 69 mTrashPaint.setColorFilter(new PorterDuffColorFilter(srcColor, PorterDuff.Mode.SRC_ATOP)); 70 71 TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DeleteZone, defStyle, 0); 72 mOrientation = a.getInt(R.styleable.DeleteZone_direction, ORIENTATION_HORIZONTAL); 73 a.recycle(); 74 } 75 76 @Override onFinishInflate()77 protected void onFinishInflate() { 78 super.onFinishInflate(); 79 mTransition = (TransitionDrawable) getDrawable(); 80 } 81 acceptDrop(DragSource source, int x, int y, int xOffset, int yOffset, DragView dragView, Object dragInfo)82 public boolean acceptDrop(DragSource source, int x, int y, int xOffset, int yOffset, 83 DragView dragView, Object dragInfo) { 84 return true; 85 } 86 estimateDropLocation(DragSource source, int x, int y, int xOffset, int yOffset, DragView dragView, Object dragInfo, Rect recycle)87 public Rect estimateDropLocation(DragSource source, int x, int y, int xOffset, int yOffset, 88 DragView dragView, Object dragInfo, Rect recycle) { 89 return null; 90 } 91 onDrop(DragSource source, int x, int y, int xOffset, int yOffset, DragView dragView, Object dragInfo)92 public void onDrop(DragSource source, int x, int y, int xOffset, int yOffset, 93 DragView dragView, Object dragInfo) { 94 final ItemInfo item = (ItemInfo) dragInfo; 95 96 if (item.container == -1) return; 97 98 if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) { 99 if (item instanceof LauncherAppWidgetInfo) { 100 mLauncher.removeAppWidget((LauncherAppWidgetInfo) item); 101 } 102 } else { 103 if (source instanceof UserFolder) { 104 final UserFolder userFolder = (UserFolder) source; 105 final UserFolderInfo userFolderInfo = (UserFolderInfo) userFolder.getInfo(); 106 // Item must be a ShortcutInfo otherwise it couldn't have been in the folder 107 // in the first place. 108 userFolderInfo.remove((ShortcutInfo)item); 109 } 110 } 111 if (item instanceof UserFolderInfo) { 112 final UserFolderInfo userFolderInfo = (UserFolderInfo)item; 113 LauncherModel.deleteUserFolderContentsFromDatabase(mLauncher, userFolderInfo); 114 mLauncher.removeFolder(userFolderInfo); 115 } else if (item instanceof LauncherAppWidgetInfo) { 116 final LauncherAppWidgetInfo launcherAppWidgetInfo = (LauncherAppWidgetInfo) item; 117 final LauncherAppWidgetHost appWidgetHost = mLauncher.getAppWidgetHost(); 118 if (appWidgetHost != null) { 119 final int appWidgetId = launcherAppWidgetInfo.appWidgetId; 120 // Deleting an app widget ID is a void call but writes to disk before returning 121 // to the caller... 122 new Thread("deleteAppWidgetId") { 123 public void run() { 124 appWidgetHost.deleteAppWidgetId(launcherAppWidgetInfo.appWidgetId); 125 } 126 }.start(); 127 } 128 } 129 LauncherModel.deleteItemFromDatabase(mLauncher, item); 130 } 131 onDragEnter(DragSource source, int x, int y, int xOffset, int yOffset, DragView dragView, Object dragInfo)132 public void onDragEnter(DragSource source, int x, int y, int xOffset, int yOffset, 133 DragView dragView, Object dragInfo) { 134 mTransition.reverseTransition(TRANSITION_DURATION); 135 dragView.setPaint(mTrashPaint); 136 } 137 onDragOver(DragSource source, int x, int y, int xOffset, int yOffset, DragView dragView, Object dragInfo)138 public void onDragOver(DragSource source, int x, int y, int xOffset, int yOffset, 139 DragView dragView, Object dragInfo) { 140 } 141 onDragExit(DragSource source, int x, int y, int xOffset, int yOffset, DragView dragView, Object dragInfo)142 public void onDragExit(DragSource source, int x, int y, int xOffset, int yOffset, 143 DragView dragView, Object dragInfo) { 144 mTransition.reverseTransition(TRANSITION_DURATION); 145 dragView.setPaint(null); 146 } 147 onDragStart(DragSource source, Object info, int dragAction)148 public void onDragStart(DragSource source, Object info, int dragAction) { 149 final ItemInfo item = (ItemInfo) info; 150 if (item != null) { 151 mTrashMode = true; 152 createAnimations(); 153 final int[] location = mLocation; 154 getLocationOnScreen(location); 155 mRegion.set(location[0], location[1], location[0] + mRight - mLeft, 156 location[1] + mBottom - mTop); 157 mDragController.setDeleteRegion(mRegion); 158 mTransition.resetTransition(); 159 startAnimation(mInAnimation); 160 mHandle.startAnimation(mHandleOutAnimation); 161 setVisibility(VISIBLE); 162 } 163 } 164 onDragEnd()165 public void onDragEnd() { 166 if (mTrashMode) { 167 mTrashMode = false; 168 mDragController.setDeleteRegion(null); 169 startAnimation(mOutAnimation); 170 mHandle.startAnimation(mHandleInAnimation); 171 setVisibility(GONE); 172 } 173 } 174 createAnimations()175 private void createAnimations() { 176 if (mInAnimation == null) { 177 mInAnimation = new FastAnimationSet(); 178 final AnimationSet animationSet = mInAnimation; 179 animationSet.setInterpolator(new AccelerateInterpolator()); 180 animationSet.addAnimation(new AlphaAnimation(0.0f, 1.0f)); 181 if (mOrientation == ORIENTATION_HORIZONTAL) { 182 animationSet.addAnimation(new TranslateAnimation(Animation.ABSOLUTE, 0.0f, 183 Animation.ABSOLUTE, 0.0f, Animation.RELATIVE_TO_SELF, 1.0f, 184 Animation.RELATIVE_TO_SELF, 0.0f)); 185 } else { 186 animationSet.addAnimation(new TranslateAnimation(Animation.RELATIVE_TO_SELF, 187 1.0f, Animation.RELATIVE_TO_SELF, 0.0f, Animation.ABSOLUTE, 0.0f, 188 Animation.ABSOLUTE, 0.0f)); 189 } 190 animationSet.setDuration(ANIMATION_DURATION); 191 } 192 if (mHandleInAnimation == null) { 193 mHandleInAnimation = new AlphaAnimation(0.0f, 1.0f); 194 mHandleInAnimation.setDuration(ANIMATION_DURATION); 195 } 196 if (mOutAnimation == null) { 197 mOutAnimation = new FastAnimationSet(); 198 final AnimationSet animationSet = mOutAnimation; 199 animationSet.setInterpolator(new AccelerateInterpolator()); 200 animationSet.addAnimation(new AlphaAnimation(1.0f, 0.0f)); 201 if (mOrientation == ORIENTATION_HORIZONTAL) { 202 animationSet.addAnimation(new FastTranslateAnimation(Animation.ABSOLUTE, 0.0f, 203 Animation.ABSOLUTE, 0.0f, Animation.RELATIVE_TO_SELF, 0.0f, 204 Animation.RELATIVE_TO_SELF, 1.0f)); 205 } else { 206 animationSet.addAnimation(new FastTranslateAnimation(Animation.RELATIVE_TO_SELF, 207 0.0f, Animation.RELATIVE_TO_SELF, 1.0f, Animation.ABSOLUTE, 0.0f, 208 Animation.ABSOLUTE, 0.0f)); 209 } 210 animationSet.setDuration(ANIMATION_DURATION); 211 } 212 if (mHandleOutAnimation == null) { 213 mHandleOutAnimation = new AlphaAnimation(1.0f, 0.0f); 214 mHandleOutAnimation.setFillAfter(true); 215 mHandleOutAnimation.setDuration(ANIMATION_DURATION); 216 } 217 } 218 setLauncher(Launcher launcher)219 void setLauncher(Launcher launcher) { 220 mLauncher = launcher; 221 } 222 setDragController(DragController dragController)223 void setDragController(DragController dragController) { 224 mDragController = dragController; 225 } 226 setHandle(View view)227 void setHandle(View view) { 228 mHandle = view; 229 } 230 231 private static class FastTranslateAnimation extends TranslateAnimation { FastTranslateAnimation(int fromXType, float fromXValue, int toXType, float toXValue, int fromYType, float fromYValue, int toYType, float toYValue)232 public FastTranslateAnimation(int fromXType, float fromXValue, int toXType, float toXValue, 233 int fromYType, float fromYValue, int toYType, float toYValue) { 234 super(fromXType, fromXValue, toXType, toXValue, 235 fromYType, fromYValue, toYType, toYValue); 236 } 237 238 @Override willChangeTransformationMatrix()239 public boolean willChangeTransformationMatrix() { 240 return true; 241 } 242 243 @Override willChangeBounds()244 public boolean willChangeBounds() { 245 return false; 246 } 247 } 248 249 private static class FastAnimationSet extends AnimationSet { FastAnimationSet()250 FastAnimationSet() { 251 super(false); 252 } 253 254 @Override willChangeTransformationMatrix()255 public boolean willChangeTransformationMatrix() { 256 return true; 257 } 258 259 @Override willChangeBounds()260 public boolean willChangeBounds() { 261 return false; 262 } 263 } 264 } 265