DragLayer.java revision 31dd503c6aa69018e694d91724d46db49ea09327
131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project/*
231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project *
431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * you may not use this file except in compliance with the License.
631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * You may obtain a copy of the License at
731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project *
831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project *
1031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
1131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
1231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * See the License for the specific language governing permissions and
1431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * limitations under the License.
1531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */
1631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectpackage com.android.launcher;
1831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.content.Context;
2031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.graphics.Bitmap;
2131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.graphics.Canvas;
2231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.graphics.Matrix;
2331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.graphics.Rect;
2431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.graphics.RectF;
2531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.graphics.Paint;
2631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.graphics.PorterDuffColorFilter;
2731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.graphics.PorterDuff;
2831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.os.Vibrator;
2931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.os.SystemClock;
3031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.util.AttributeSet;
3131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.view.MotionEvent;
3231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.view.View;
3331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.view.ViewGroup;
3431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.view.KeyEvent;
3531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.view.inputmethod.InputMethodManager;
3631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.widget.FrameLayout;
3731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
3831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project/**
3931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * A ViewGroup that coordinated dragging across its dscendants
4031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */
4131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectpublic class DragLayer extends FrameLayout implements DragController {
4231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private static final int SCROLL_DELAY = 600;
4331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private static final int SCROLL_ZONE = 20;
4431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private static final int VIBRATE_DURATION = 35;
4531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private static final int ANIMATION_SCALE_UP_DURATION = 110;
4631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
4731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private static final boolean PROFILE_DRAWING_DURING_DRAG = false;
4831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
4931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    // Number of pixels to add to the dragged item for scaling
5031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private static final float DRAG_SCALE = 24.0f;
5131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
5231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private boolean mDragging = false;
5331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private boolean mShouldDrop;
5431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private float mLastMotionX;
5531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private float mLastMotionY;
5631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
5731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
5831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * The bitmap that is currently being dragged
5931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
6031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private Bitmap mDragBitmap = null;
6131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private View mOriginator;
6231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
6331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private int mBitmapOffsetX;
6431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private int mBitmapOffsetY;
6531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
6631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
6731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * X offset from where we touched on the cell to its upper-left corner
6831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
6931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private float mTouchOffsetX;
7031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
7131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
7231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Y offset from where we touched on the cell to its upper-left corner
7331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
7431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private float mTouchOffsetY;
7531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
7631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
7731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Utility rectangle
7831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
7931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private Rect mDragRect = new Rect();
8031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
8131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
8231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Where the drag originated
8331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
8431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private DragSource mDragSource;
8531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
8631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
8731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * The data associated with the object being dragged
8831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
8931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private Object mDragInfo;
9031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
9131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private final Rect mRect = new Rect();
9231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private final int[] mDropCoordinates = new int[2];
9331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
9431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private final Vibrator mVibrator = new Vibrator();
9531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
9631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private DragListener mListener;
9731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
9831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private DragScroller mDragScroller;
9931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
10031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private static final int SCROLL_OUTSIDE_ZONE = 0;
10131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private static final int SCROLL_WAITING_IN_ZONE = 1;
10231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
10331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private static final int SCROLL_LEFT = 0;
10431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private static final int SCROLL_RIGHT = 1;
10531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
10631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private int mScrollState = SCROLL_OUTSIDE_ZONE;
10731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
10831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private ScrollRunnable mScrollRunnable = new ScrollRunnable();
10931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private View mIgnoredDropTarget;
11031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
11131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private RectF mDragRegion;
11231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private boolean mEnteredRegion;
11331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private DropTarget mLastDropTarget;
11431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
11531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private final Paint mTrashPaint = new Paint();
11631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private Paint mDragPaint;
11731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
11831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private static final int ANIMATION_STATE_STARTING = 1;
11931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private static final int ANIMATION_STATE_RUNNING = 2;
12031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private static final int ANIMATION_STATE_DONE = 3;
12131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
12231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private static final int ANIMATION_TYPE_SCALE = 1;
12331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
12431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private float mAnimationFrom;
12531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private float mAnimationTo;
12631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private int mAnimationDuration;
12731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private long mAnimationStartTime;
12831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private int mAnimationType;
12931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private int mAnimationState = ANIMATION_STATE_DONE;
13031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
13131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private InputMethodManager mInputMethodManager;
13231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
13331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
13431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Used to create a new DragLayer from XML.
13531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
13631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param context The application's context.
13731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param attrs The attribtues set containing the Workspace's customization values.
13831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
13931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public DragLayer(Context context, AttributeSet attrs) {
14031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super(context, attrs);
14131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
14231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        final int srcColor = context.getResources().getColor(R.color.delete_color_filter);
14331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mTrashPaint.setColorFilter(new PorterDuffColorFilter(srcColor, PorterDuff.Mode.SRC_ATOP));
14431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
14531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
14631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void startDrag(View v, DragSource source, Object dragInfo, int dragAction) {
14731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (PROFILE_DRAWING_DURING_DRAG) {
14831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            android.os.Debug.startMethodTracing("Launcher");
14931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
15031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
15131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        // Hide soft keyboard, if visible
15231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (mInputMethodManager == null) {
15331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            mInputMethodManager = (InputMethodManager)
15431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
15531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
15631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mInputMethodManager.hideSoftInputFromWindow(getWindowToken(), 0);
15731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
15831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (mListener != null) {
15931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            mListener.onDragStart(v, source, dragInfo, dragAction);
16031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
16131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
16231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        Rect r = mDragRect;
16331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        r.set(v.getScrollX(), v.getScrollY(), 0, 0);
16431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
16531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        offsetDescendantRectToMyCoords(v, r);
16631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mTouchOffsetX = mLastMotionX - r.left;
16731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mTouchOffsetY = mLastMotionY - r.top;
16831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
16931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        v.clearFocus();
17031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        v.setPressed(false);
17131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
17231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        boolean willNotCache = v.willNotCacheDrawing();
17331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        v.setWillNotCacheDrawing(false);
17431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        v.buildDrawingCache();
17531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
17631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        Bitmap viewBitmap = v.getDrawingCache();
17731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        int width = viewBitmap.getWidth();
17831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        int height = viewBitmap.getHeight();
17931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
18031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        Matrix scale = new Matrix();
18131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        float scaleFactor = v.getWidth();
18231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        scaleFactor = (scaleFactor + DRAG_SCALE) /scaleFactor;
18331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        scale.setScale(scaleFactor, scaleFactor);
18431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
18531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mAnimationTo = 1.0f;
18631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mAnimationFrom = 1.0f / scaleFactor;
18731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mAnimationDuration = ANIMATION_SCALE_UP_DURATION;
18831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mAnimationState = ANIMATION_STATE_STARTING;
18931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mAnimationType = ANIMATION_TYPE_SCALE;
19031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
19131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mDragBitmap = Bitmap.createBitmap(viewBitmap, 0, 0, width, height, scale, true);
19231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        v.destroyDrawingCache();
19331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        v.setWillNotCacheDrawing(willNotCache);
19431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
19531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        final Bitmap dragBitmap = mDragBitmap;
19631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mBitmapOffsetX = (dragBitmap.getWidth() - width) / 2;
19731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mBitmapOffsetY = (dragBitmap.getHeight() - height) / 2;
19831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
19931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (dragAction == DRAG_ACTION_MOVE) {
20031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            v.setVisibility(GONE);
20131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
20231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
20331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mDragPaint = null;
20431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mDragging = true;
20531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mShouldDrop = true;
20631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mOriginator = v;
20731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mDragSource = source;
20831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mDragInfo = dragInfo;
20931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
21031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mVibrator.vibrate(VIBRATE_DURATION);
21131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
21231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mEnteredRegion = false;
21331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
21431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        invalidate();
21531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
21631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
21731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
21831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public boolean dispatchKeyEvent(KeyEvent event) {
21931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        return mDragging || super.dispatchKeyEvent(event);
22031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
22131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
22231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
22331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    protected void dispatchDraw(Canvas canvas) {
22431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        super.dispatchDraw(canvas);
22531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
22631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (mDragging && mDragBitmap != null) {
22731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if (mAnimationState == ANIMATION_STATE_STARTING) {
22831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                mAnimationStartTime = SystemClock.uptimeMillis();
22931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                mAnimationState = ANIMATION_STATE_RUNNING;
23031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
23131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
23231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if (mAnimationState == ANIMATION_STATE_RUNNING) {
23331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                float normalized = (float) (SystemClock.uptimeMillis() - mAnimationStartTime) /
23431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        mAnimationDuration;
23531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                if (normalized >= 1.0f) {
23631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    mAnimationState = ANIMATION_STATE_DONE;
23731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                }
23831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                normalized = Math.min(normalized, 1.0f);
23931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                final float value = mAnimationFrom  + (mAnimationTo - mAnimationFrom) * normalized;
24031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
24131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                switch (mAnimationType) {
24231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    case ANIMATION_TYPE_SCALE:
24331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        final Bitmap dragBitmap = mDragBitmap;
24431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        canvas.save();
24531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        canvas.translate(mScrollX + mLastMotionX - mTouchOffsetX - mBitmapOffsetX,
24631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                                mScrollY + mLastMotionY - mTouchOffsetY - mBitmapOffsetY);
24731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        canvas.translate((dragBitmap.getWidth() * (1.0f - value)) / 2,
24831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                                (dragBitmap.getHeight() * (1.0f - value)) / 2);
24931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        canvas.scale(value, value);
25031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        canvas.drawBitmap(dragBitmap, 0.0f, 0.0f, mDragPaint);
25131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        canvas.restore();
25231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        break;
25331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                }
25431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            } else {
25531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                canvas.drawBitmap(mDragBitmap,
25631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        mScrollX + mLastMotionX - mTouchOffsetX - mBitmapOffsetX,
25731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        mScrollY + mLastMotionY - mTouchOffsetY - mBitmapOffsetY, mDragPaint);
25831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
25931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
26031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
26131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
26231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private void endDrag() {
26331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (mDragging) {
26431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            mDragging = false;
26531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if (mDragBitmap != null) {
26631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                mDragBitmap.recycle();
26731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
26831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if (mOriginator != null) {
26931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                mOriginator.setVisibility(VISIBLE);
27031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
27131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if (mListener != null) {
27231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                mListener.onDragEnd();
27331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
27431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
27531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
27631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
27731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
27831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public boolean onInterceptTouchEvent(MotionEvent ev) {
27931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        final int action = ev.getAction();
28031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
28131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        final float x = ev.getX();
28231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        final float y = ev.getY();
28331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
28431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        switch (action) {
28531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            case MotionEvent.ACTION_MOVE:
28631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                break;
28731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
28831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            case MotionEvent.ACTION_DOWN:
28931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                // Remember location of down touch
29031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                mLastMotionX = x;
29131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                mLastMotionY = y;
29231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                mLastDropTarget = null;
29331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                break;
29431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
29531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            case MotionEvent.ACTION_CANCEL:
29631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            case MotionEvent.ACTION_UP:
29731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                if (mShouldDrop && drop(x, y)) {
29831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    mShouldDrop = false;
29931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                }
30031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                endDrag();
30131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                break;
30231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
30331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
30431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        return mDragging;
30531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
30631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
30731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    @Override
30831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public boolean onTouchEvent(MotionEvent ev) {
30931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (!mDragging) {
31031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            return false;
31131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
31231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
31331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        final int action = ev.getAction();
31431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        final float x = ev.getX();
31531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        final float y = ev.getY();
31631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
31731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        switch (action) {
31831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        case MotionEvent.ACTION_DOWN:
31931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
32031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            // Remember where the motion event started
32131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            mLastMotionX = x;
32231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            mLastMotionY = y;
32331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
32431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if ((x < SCROLL_ZONE) || (x > getWidth() - SCROLL_ZONE)) {
32531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                mScrollState = SCROLL_WAITING_IN_ZONE;
32631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                postDelayed(mScrollRunnable, SCROLL_DELAY);
32731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            } else {
32831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                mScrollState = SCROLL_OUTSIDE_ZONE;
32931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
33031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
33131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            break;
33231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        case MotionEvent.ACTION_MOVE:
33331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            final int scrollX = mScrollX;
33431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            final int scrollY = mScrollY;
33531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
33631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            final float touchX = mTouchOffsetX;
33731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            final float touchY = mTouchOffsetY;
33831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
33931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            final int offsetX = mBitmapOffsetX;
34031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            final int offsetY = mBitmapOffsetY;
34131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
34231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            int left = (int) (scrollX + mLastMotionX - touchX - offsetX);
34331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            int top = (int) (scrollY + mLastMotionY - touchY - offsetY);
34431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
34531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            final Bitmap dragBitmap = mDragBitmap;
34631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            final int width = dragBitmap.getWidth();
34731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            final int height = dragBitmap.getHeight();
34831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
34931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            final Rect rect = mRect;
35031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            rect.set(left - 1, top - 1, left + width + 1, top + height + 1);
35131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
35231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            mLastMotionX = x;
35331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            mLastMotionY = y;
35431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
35531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            left = (int) (scrollX + x - touchX - offsetX);
35631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            top = (int) (scrollY + y - touchY - offsetY);
35731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
35831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            rect.union(left - 1, top - 1, left + width + 1, top + height + 1);
35931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            invalidate(rect);
36031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
36131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            final int[] coordinates = mDropCoordinates;
36231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            DropTarget dropTarget = findDropTarget((int) x, (int) y, coordinates);
36331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if (dropTarget != null) {
36431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                if (mLastDropTarget == dropTarget) {
36531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    dropTarget.onDragOver(mDragSource, coordinates[0], coordinates[1],
36631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        (int) mTouchOffsetX, (int) mTouchOffsetY, mDragInfo);
36731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                } else {
36831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    if (mLastDropTarget != null) {
36931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        mLastDropTarget.onDragExit(mDragSource, coordinates[0], coordinates[1],
37031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                            (int) mTouchOffsetX, (int) mTouchOffsetY, mDragInfo);
37131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    }
37231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    dropTarget.onDragEnter(mDragSource, coordinates[0], coordinates[1],
37331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        (int) mTouchOffsetX, (int) mTouchOffsetY, mDragInfo);
37431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                }
37531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            } else {
37631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                if (mLastDropTarget != null) {
37731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    mLastDropTarget.onDragExit(mDragSource, coordinates[0], coordinates[1],
37831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        (int) mTouchOffsetX, (int) mTouchOffsetY, mDragInfo);
37931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                }
38031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
38131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            mLastDropTarget = dropTarget;
38231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
38331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            boolean inDragRegion = false;
38431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if (mDragRegion != null) {
38531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                final RectF region = mDragRegion;
38631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                final boolean inRegion = region.contains(ev.getRawX(), ev.getRawY());
38731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                if (!mEnteredRegion && inRegion) {
38831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    mDragPaint = mTrashPaint;
38931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    mEnteredRegion = true;
39031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    inDragRegion = true;
39131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                } else if (mEnteredRegion && !inRegion) {
39231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    mDragPaint = null;
39331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    mEnteredRegion = false;
39431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                }
39531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
39631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
39731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if (!inDragRegion && x < SCROLL_ZONE) {
39831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                if (mScrollState == SCROLL_OUTSIDE_ZONE) {
39931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    mScrollState = SCROLL_WAITING_IN_ZONE;
40031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    mScrollRunnable.setDirection(SCROLL_LEFT);
40131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    postDelayed(mScrollRunnable, SCROLL_DELAY);
40231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                }
40331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            } else if (!inDragRegion && x > getWidth() - SCROLL_ZONE) {
40431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                if (mScrollState == SCROLL_OUTSIDE_ZONE) {
40531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    mScrollState = SCROLL_WAITING_IN_ZONE;
40631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    mScrollRunnable.setDirection(SCROLL_RIGHT);
40731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    postDelayed(mScrollRunnable, SCROLL_DELAY);
40831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                }
40931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            } else {
41031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                if (mScrollState == SCROLL_WAITING_IN_ZONE) {
41131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    mScrollState = SCROLL_OUTSIDE_ZONE;
41231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    mScrollRunnable.setDirection(SCROLL_RIGHT);
41331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    removeCallbacks(mScrollRunnable);
41431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                }
41531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
41631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
41731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            break;
41831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        case MotionEvent.ACTION_UP:
41931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            removeCallbacks(mScrollRunnable);
42031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if (mShouldDrop) {
42131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                drop(x, y);
42231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                mShouldDrop = false;
42331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
42431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            endDrag();
42531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
42631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            break;
42731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        case MotionEvent.ACTION_CANCEL:
42831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            endDrag();
42931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
43031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
43131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        return true;
43231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
43331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
43431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private boolean drop(float x, float y) {
43531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        invalidate();
43631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
43731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        final int[] coordinates = mDropCoordinates;
43831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        DropTarget dropTarget = findDropTarget((int) x, (int) y, coordinates);
43931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
44031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        if (dropTarget != null) {
44131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            dropTarget.onDragExit(mDragSource, coordinates[0], coordinates[1],
44231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    (int) mTouchOffsetX, (int) mTouchOffsetY, mDragInfo);
44331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if (dropTarget.acceptDrop(mDragSource, coordinates[0], coordinates[1],
44431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    (int) mTouchOffsetX, (int) mTouchOffsetY, mDragInfo)) {
44531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                dropTarget.onDrop(mDragSource, coordinates[0], coordinates[1],
44631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        (int) mTouchOffsetX, (int) mTouchOffsetY, mDragInfo);
44731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                mDragSource.onDropCompleted((View) dropTarget, true);
44831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                return true;
44931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            } else {
45031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                mDragSource.onDropCompleted((View) dropTarget, false);
45131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                return true;
45231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
45331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
45431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        return false;
45531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
45631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
45731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    DropTarget findDropTarget(int x, int y, int[] dropCoordinates) {
45831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        return findDropTarget(this, x, y, dropCoordinates);
45931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
46031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
46131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private DropTarget findDropTarget(ViewGroup container, int x, int y, int[] dropCoordinates) {
46231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        final Rect r = mDragRect;
46331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        final int count = container.getChildCount();
46431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        final int scrolledX = x + container.getScrollX();
46531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        final int scrolledY = y + container.getScrollY();
46631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        final View ignoredDropTarget = mIgnoredDropTarget;
46731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
46831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        for (int i = count - 1; i >= 0; i--) {
46931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            final View child = container.getChildAt(i);
47031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if (child.getVisibility() == VISIBLE && child != ignoredDropTarget) {
47131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                child.getHitRect(r);
47231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                if (r.contains(scrolledX, scrolledY)) {
47331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    DropTarget target = null;
47431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    if (child instanceof ViewGroup) {
47531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        x = scrolledX - child.getLeft();
47631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        y = scrolledY - child.getTop();
47731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        target = findDropTarget((ViewGroup) child, x, y, dropCoordinates);
47831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    }
47931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    if (target == null) {
48031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        if (child instanceof DropTarget) {
48131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                            dropCoordinates[0] = x;
48231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                            dropCoordinates[1] = y;
48331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                            return (DropTarget) child;
48431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        }
48531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    } else {
48631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                        return target;
48731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    }
48831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                }
48931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
49031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
49131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
49231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        return null;
49331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
49431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
49531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void setDragScoller(DragScroller scroller) {
49631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mDragScroller = scroller;
49731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
49831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
49931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void setDragListener(DragListener l) {
50031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mListener = l;
50131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
50231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
50331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    public void removeDragListener(DragListener l) {
50431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mListener = null;
50531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
50631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
50731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
50831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Specifies the view that must be ignored when looking for a drop target.
50931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
51031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param view The view that will not be taken into account while looking
51131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *        for a drop target.
51231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
51331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    void setIgnoredDropTarget(View view) {
51431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mIgnoredDropTarget = view;
51531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
51631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
51731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
51831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Specifies the delete region.
51931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *
52031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param region The rectangle in screen coordinates of the delete region.
52131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
52231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    void setDeleteRegion(RectF region) {
52331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        mDragRegion = region;
52431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
52531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
52631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    private class ScrollRunnable implements Runnable {
52731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        private int mDirection;
52831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
52931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        ScrollRunnable() {
53031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
53131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
53231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        public void run() {
53331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            if (mDragScroller != null) {
53431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                if (mDirection == SCROLL_LEFT) {
53531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    mDragScroller.scrollLeft();
53631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                } else {
53731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                    mDragScroller.scrollRight();
53831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                }
53931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project                mScrollState = SCROLL_OUTSIDE_ZONE;
54031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            }
54131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
54231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
54331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        void setDirection(int direction) {
54431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project            mDirection = direction;
54531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
54631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
54731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project}
548