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 61 public DeleteZone(Context context, AttributeSet attrs) { 62 this(context, attrs, 0); 63 } 64 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 77 protected void onFinishInflate() { 78 super.onFinishInflate(); 79 mTransition = (TransitionDrawable) getDrawable(); 80 } 81 82 public boolean acceptDrop(DragSource source, int x, int y, int xOffset, int yOffset, 83 DragView dragView, Object dragInfo) { 84 return true; 85 } 86 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 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 appWidgetHost.deleteAppWidgetId(launcherAppWidgetInfo.appWidgetId); 120 } 121 } 122 LauncherModel.deleteItemFromDatabase(mLauncher, item); 123 } 124 125 public void onDragEnter(DragSource source, int x, int y, int xOffset, int yOffset, 126 DragView dragView, Object dragInfo) { 127 mTransition.reverseTransition(TRANSITION_DURATION); 128 dragView.setPaint(mTrashPaint); 129 } 130 131 public void onDragOver(DragSource source, int x, int y, int xOffset, int yOffset, 132 DragView dragView, Object dragInfo) { 133 } 134 135 public void onDragExit(DragSource source, int x, int y, int xOffset, int yOffset, 136 DragView dragView, Object dragInfo) { 137 mTransition.reverseTransition(TRANSITION_DURATION); 138 dragView.setPaint(null); 139 } 140 141 public void onDragStart(DragSource source, Object info, int dragAction) { 142 final ItemInfo item = (ItemInfo) info; 143 if (item != null) { 144 mTrashMode = true; 145 createAnimations(); 146 final int[] location = mLocation; 147 getLocationOnScreen(location); 148 mRegion.set(location[0], location[1], location[0] + mRight - mLeft, 149 location[1] + mBottom - mTop); 150 mDragController.setDeleteRegion(mRegion); 151 mTransition.resetTransition(); 152 startAnimation(mInAnimation); 153 mHandle.startAnimation(mHandleOutAnimation); 154 setVisibility(VISIBLE); 155 } 156 } 157 158 public void onDragEnd() { 159 if (mTrashMode) { 160 mTrashMode = false; 161 mDragController.setDeleteRegion(null); 162 startAnimation(mOutAnimation); 163 mHandle.startAnimation(mHandleInAnimation); 164 setVisibility(GONE); 165 } 166 } 167 168 private void createAnimations() { 169 if (mInAnimation == null) { 170 mInAnimation = new FastAnimationSet(); 171 final AnimationSet animationSet = mInAnimation; 172 animationSet.setInterpolator(new AccelerateInterpolator()); 173 animationSet.addAnimation(new AlphaAnimation(0.0f, 1.0f)); 174 if (mOrientation == ORIENTATION_HORIZONTAL) { 175 animationSet.addAnimation(new TranslateAnimation(Animation.ABSOLUTE, 0.0f, 176 Animation.ABSOLUTE, 0.0f, Animation.RELATIVE_TO_SELF, 1.0f, 177 Animation.RELATIVE_TO_SELF, 0.0f)); 178 } else { 179 animationSet.addAnimation(new TranslateAnimation(Animation.RELATIVE_TO_SELF, 180 1.0f, Animation.RELATIVE_TO_SELF, 0.0f, Animation.ABSOLUTE, 0.0f, 181 Animation.ABSOLUTE, 0.0f)); 182 } 183 animationSet.setDuration(ANIMATION_DURATION); 184 } 185 if (mHandleInAnimation == null) { 186 mHandleInAnimation = new AlphaAnimation(0.0f, 1.0f); 187 mHandleInAnimation.setDuration(ANIMATION_DURATION); 188 } 189 if (mOutAnimation == null) { 190 mOutAnimation = new FastAnimationSet(); 191 final AnimationSet animationSet = mOutAnimation; 192 animationSet.setInterpolator(new AccelerateInterpolator()); 193 animationSet.addAnimation(new AlphaAnimation(1.0f, 0.0f)); 194 if (mOrientation == ORIENTATION_HORIZONTAL) { 195 animationSet.addAnimation(new FastTranslateAnimation(Animation.ABSOLUTE, 0.0f, 196 Animation.ABSOLUTE, 0.0f, Animation.RELATIVE_TO_SELF, 0.0f, 197 Animation.RELATIVE_TO_SELF, 1.0f)); 198 } else { 199 animationSet.addAnimation(new FastTranslateAnimation(Animation.RELATIVE_TO_SELF, 200 0.0f, Animation.RELATIVE_TO_SELF, 1.0f, Animation.ABSOLUTE, 0.0f, 201 Animation.ABSOLUTE, 0.0f)); 202 } 203 animationSet.setDuration(ANIMATION_DURATION); 204 } 205 if (mHandleOutAnimation == null) { 206 mHandleOutAnimation = new AlphaAnimation(1.0f, 0.0f); 207 mHandleOutAnimation.setFillAfter(true); 208 mHandleOutAnimation.setDuration(ANIMATION_DURATION); 209 } 210 } 211 212 void setLauncher(Launcher launcher) { 213 mLauncher = launcher; 214 } 215 216 void setDragController(DragController dragController) { 217 mDragController = dragController; 218 } 219 220 void setHandle(View view) { 221 mHandle = view; 222 } 223 224 private static class FastTranslateAnimation extends TranslateAnimation { 225 public FastTranslateAnimation(int fromXType, float fromXValue, int toXType, float toXValue, 226 int fromYType, float fromYValue, int toYType, float toYValue) { 227 super(fromXType, fromXValue, toXType, toXValue, 228 fromYType, fromYValue, toYType, toYValue); 229 } 230 231 @Override 232 public boolean willChangeTransformationMatrix() { 233 return true; 234 } 235 236 @Override 237 public boolean willChangeBounds() { 238 return false; 239 } 240 } 241 242 private static class FastAnimationSet extends AnimationSet { 243 FastAnimationSet() { 244 super(false); 245 } 246 247 @Override 248 public boolean willChangeTransformationMatrix() { 249 return true; 250 } 251 252 @Override 253 public boolean willChangeBounds() { 254 return false; 255 } 256 } 257 } 258