DragController.java revision c07918d0053fc7d2a19d7b013565a5d2e7d4af51
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
17a5902524d4403885eb4c50360bf3465c6be796efJoe Onoratopackage com.android.launcher2;
1831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onoratoimport android.content.Context;
2000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onoratoimport android.graphics.Bitmap;
2100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onoratoimport android.graphics.Rect;
2200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onoratoimport android.graphics.RectF;
2300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onoratoimport android.os.Handler;
240280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurkaimport android.os.IBinder;
2500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onoratoimport android.os.Vibrator;
26e048e8a8eff51e8c2c271d16c864367dac438ca2Joe Onoratoimport android.util.DisplayMetrics;
2700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onoratoimport android.util.Log;
2800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onoratoimport android.view.KeyEvent;
2900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onoratoimport android.view.MotionEvent;
300280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurkaimport android.view.View;
31a16fd5a6bd5371d40a5679261d416f06f8efa022Patrick Dubroyimport android.view.ViewConfiguration;
32e048e8a8eff51e8c2c271d16c864367dac438ca2Joe Onoratoimport android.view.WindowManager;
3300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onoratoimport android.view.inputmethod.InputMethodManager;
3400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
35120980bd00f5eecec5717f49a3d7db96571025a9Adam Cohenimport com.android.launcher.R;
36c0dcf597084d00e4c23a7fea5fd0738f6c095a6bAdam Cohen
37c0dcf597084d00e4c23a7fea5fd0738f6c095a6bAdam Cohenimport java.util.ArrayList;
3831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
3931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project/**
4000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato * Class for initiating a drag within a view or across multiple views.
4131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */
4200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onoratopublic class DragController {
43ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy    @SuppressWarnings({"UnusedDeclaration"})
442e5c432a0aa7e83031575df73bed43a297e2eed3Joe Onorato    private static final String TAG = "Launcher.DragController";
452e5c432a0aa7e83031575df73bed43a297e2eed3Joe Onorato
4600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    /** Indicates the drag is a move.  */
4700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    public static int DRAG_ACTION_MOVE = 0;
4800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
4900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    /** Indicates the drag is a copy.  */
5000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    public static int DRAG_ACTION_COPY = 1;
5100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
5200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    private static final int SCROLL_DELAY = 600;
5300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    private static final int VIBRATE_DURATION = 35;
5400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
5500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    private static final boolean PROFILE_DRAWING_DURING_DRAG = false;
5600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
5700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    private static final int SCROLL_OUTSIDE_ZONE = 0;
5800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    private static final int SCROLL_WAITING_IN_ZONE = 1;
5900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
6054fa3b95557c283976e8c1aa8a157b460b0b4513Patrick Dubroy    static final int SCROLL_NONE = -1;
611262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    static final int SCROLL_LEFT = 0;
621262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    static final int SCROLL_RIGHT = 1;
6300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
6400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    private Context mContext;
6500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    private Handler mHandler;
6600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    private final Vibrator mVibrator = new Vibrator();
6700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
6800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    // temporaries to avoid gc thrash
6900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    private Rect mRectTemp = new Rect();
7000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    private final int[] mCoordinatesTemp = new int[2];
7100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
7200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    /** Whether or not we're dragging. */
7300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    private boolean mDragging;
7400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
7500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    /** X coordinate of the down event. */
76e3e27a854f3eca363d3c5ce353d19de475272d87Adam Cohen    private int mMotionDownX;
7700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
7800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    /** Y coordinate of the down event. */
79e3e27a854f3eca363d3c5ce353d19de475272d87Adam Cohen    private int mMotionDownY;
8000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
81e048e8a8eff51e8c2c271d16c864367dac438ca2Joe Onorato    /** Info about the screen for clamping. */
82e048e8a8eff51e8c2c271d16c864367dac438ca2Joe Onorato    private DisplayMetrics mDisplayMetrics = new DisplayMetrics();
83e048e8a8eff51e8c2c271d16c864367dac438ca2Joe Onorato
84658db74c24817892f1a379b16620744f38f60e40Joe Onorato    /** the area at the edge of the screen that makes the workspace go left
85658db74c24817892f1a379b16620744f38f60e40Joe Onorato     *   or right while you're dragging.
86658db74c24817892f1a379b16620744f38f60e40Joe Onorato     */
87658db74c24817892f1a379b16620744f38f60e40Joe Onorato    private int mScrollZone;
88658db74c24817892f1a379b16620744f38f60e40Joe Onorato
89cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen    private DropTarget.DragObject mDragObject = new DropTarget.DragObject();
9000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
9100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    /** Who can receive drop events */
9200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    private ArrayList<DropTarget> mDropTargets = new ArrayList<DropTarget>();
9300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
944ed6278e518cc6894cb150b606382e8e6a012599Patrick Dubroy    private ArrayList<DragListener> mListeners = new ArrayList<DragListener>();
9500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
9600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    /** The window token used as the parent for the DragView. */
9700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    private IBinder mWindowToken;
9800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
9900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    /** The view that will be scrolled when dragging to the left and right edges of the screen. */
10000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    private View mScrollView;
10100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
102ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy    private View mMoveTarget;
103ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy
10400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    private DragScroller mDragScroller;
10500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    private int mScrollState = SCROLL_OUTSIDE_ZONE;
10600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    private ScrollRunnable mScrollRunnable = new ScrollRunnable();
10700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
10800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    private RectF mDeleteRegion;
10900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    private DropTarget mLastDropTarget;
11000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
11100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    private InputMethodManager mInputMethodManager;
11200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
113a16fd5a6bd5371d40a5679261d416f06f8efa022Patrick Dubroy    private int mLastTouch[] = new int[2];
114a16fd5a6bd5371d40a5679261d416f06f8efa022Patrick Dubroy    private int mDistanceSinceScroll = 0;
115a16fd5a6bd5371d40a5679261d416f06f8efa022Patrick Dubroy
11631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
11731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Interface to receive notifications when a drag starts or stops
11831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
11931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    interface DragListener {
12031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
12131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        /**
12231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project         * A drag has begun
12331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project         *
12431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project         * @param source An object representing where the drag originated
12531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project         * @param info The data associated with the object that is being dragged
12631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project         * @param dragAction The drag action: either {@link DragController#DRAG_ACTION_MOVE}
12731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project         *        or {@link DragController#DRAG_ACTION_COPY}
12831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project         */
1295162ea9b1f41dbebe00fd9ec4d1e15a697971439Joe Onorato        void onDragStart(DragSource source, Object info, int dragAction);
13031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
13131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        /**
132e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung         * The drag has ended
13331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project         */
13431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        void onDragEnd();
13531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
13631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
13731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
13800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     * Used to create a new DragLayer from XML.
13900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     *
14000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     * @param context The application's context.
14131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
14200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    public DragController(Context context) {
14300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        mContext = context;
14400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        mHandler = new Handler();
145658db74c24817892f1a379b16620744f38f60e40Joe Onorato        mScrollZone = context.getResources().getDimensionPixelSize(R.dimen.scroll_zone);
14600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    }
14731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1481262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    public boolean dragging() {
1491262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy        return mDragging;
1501262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy    }
1511262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy
15231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
1535162ea9b1f41dbebe00fd9ec4d1e15a697971439Joe Onorato     * Starts a drag.
154a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka     *
15531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param v The view that is being dragged
15631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param source An object representing where the drag originated
157ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy     * @param dragInfo The data associated with the object that is being dragged
15831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * @param dragAction The drag action: either {@link #DRAG_ACTION_MOVE} or
15931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     *        {@link #DRAG_ACTION_COPY}
16031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
16100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    public void startDrag(View v, DragSource source, Object dragInfo, int dragAction) {
162a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        startDrag(v, source, dragInfo, dragAction, null);
163a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka    }
164a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
165a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka    /**
166a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka     * Starts a drag.
167a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka     *
168a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka     * @param v The view that is being dragged
169a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka     * @param source An object representing where the drag originated
170a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka     * @param dragInfo The data associated with the object that is being dragged
171a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka     * @param dragAction The drag action: either {@link #DRAG_ACTION_MOVE} or
172a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka     *        {@link #DRAG_ACTION_COPY}
173a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka     * @param dragRegion Coordinates within the bitmap b for the position of item being dragged.
174a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka     *          Makes dragging feel more precise, e.g. you can clip out a transparent border
175a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka     */
176a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka    public void startDrag(View v, DragSource source, Object dragInfo, int dragAction,
177a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            Rect dragRegion) {
1785162ea9b1f41dbebe00fd9ec4d1e15a697971439Joe Onorato        Bitmap b = getViewBitmap(v);
1795162ea9b1f41dbebe00fd9ec4d1e15a697971439Joe Onorato
1803f8175a86e24b3568d1f5b12e1d3d5efcc57d691Daniel Sandler        if (b == null) {
1813f8175a86e24b3568d1f5b12e1d3d5efcc57d691Daniel Sandler            // out of memory?
1823f8175a86e24b3568d1f5b12e1d3d5efcc57d691Daniel Sandler            return;
1833f8175a86e24b3568d1f5b12e1d3d5efcc57d691Daniel Sandler        }
1843f8175a86e24b3568d1f5b12e1d3d5efcc57d691Daniel Sandler
1855162ea9b1f41dbebe00fd9ec4d1e15a697971439Joe Onorato        int[] loc = mCoordinatesTemp;
1865162ea9b1f41dbebe00fd9ec4d1e15a697971439Joe Onorato        v.getLocationOnScreen(loc);
1875162ea9b1f41dbebe00fd9ec4d1e15a697971439Joe Onorato        int screenX = loc[0];
1885162ea9b1f41dbebe00fd9ec4d1e15a697971439Joe Onorato        int screenY = loc[1];
1895162ea9b1f41dbebe00fd9ec4d1e15a697971439Joe Onorato
1905f445425606b2c27276a79e9e871cf7f67b1b719Patrick Dubroy        startDrag(b, screenX, screenY, source, dragInfo, dragAction, dragRegion);
1915162ea9b1f41dbebe00fd9ec4d1e15a697971439Joe Onorato        b.recycle();
1925162ea9b1f41dbebe00fd9ec4d1e15a697971439Joe Onorato
1935162ea9b1f41dbebe00fd9ec4d1e15a697971439Joe Onorato        if (dragAction == DRAG_ACTION_MOVE) {
1945162ea9b1f41dbebe00fd9ec4d1e15a697971439Joe Onorato            v.setVisibility(View.GONE);
1955162ea9b1f41dbebe00fd9ec4d1e15a697971439Joe Onorato        }
1965162ea9b1f41dbebe00fd9ec4d1e15a697971439Joe Onorato    }
1975162ea9b1f41dbebe00fd9ec4d1e15a697971439Joe Onorato
1985162ea9b1f41dbebe00fd9ec4d1e15a697971439Joe Onorato    /**
1995162ea9b1f41dbebe00fd9ec4d1e15a697971439Joe Onorato     * Starts a drag.
200a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka     *
201e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung     * @param v The view that is being dragged
202e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung     * @param bmp The bitmap that represents the view being dragged
203e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung     * @param source An object representing where the drag originated
204e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung     * @param dragInfo The data associated with the object that is being dragged
205e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung     * @param dragAction The drag action: either {@link #DRAG_ACTION_MOVE} or
206e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung     *        {@link #DRAG_ACTION_COPY}
207e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung     * @param dragRegion Coordinates within the bitmap b for the position of item being dragged.
208e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung     *          Makes dragging feel more precise, e.g. you can clip out a transparent border
209e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung     */
210e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung    public void startDrag(View v, Bitmap bmp, DragSource source, Object dragInfo, int dragAction,
211e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung            Rect dragRegion) {
212e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung        int[] loc = mCoordinatesTemp;
213e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung        v.getLocationOnScreen(loc);
214e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung        int screenX = loc[0];
215e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung        int screenY = loc[1];
216e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung
2175f445425606b2c27276a79e9e871cf7f67b1b719Patrick Dubroy        startDrag(bmp, screenX, screenY, source, dragInfo, dragAction, dragRegion);
218e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung
219e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung        if (dragAction == DRAG_ACTION_MOVE) {
220e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung            v.setVisibility(View.GONE);
221e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung        }
222e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung    }
223e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung
224e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung    /**
225e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung     * Starts a drag.
226e3193b93ad7bf33e2e45319084a99b9fc986622bWinson Chung     *
2275162ea9b1f41dbebe00fd9ec4d1e15a697971439Joe Onorato     * @param b The bitmap to display as the drag image.  It will be re-scaled to the
2285162ea9b1f41dbebe00fd9ec4d1e15a697971439Joe Onorato     *          enlarged size.
2295162ea9b1f41dbebe00fd9ec4d1e15a697971439Joe Onorato     * @param screenX The x position on screen of the left-top of the bitmap.
2305162ea9b1f41dbebe00fd9ec4d1e15a697971439Joe Onorato     * @param screenY The y position on screen of the left-top of the bitmap.
2315162ea9b1f41dbebe00fd9ec4d1e15a697971439Joe Onorato     * @param source An object representing where the drag originated
232ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy     * @param dragInfo The data associated with the object that is being dragged
2335162ea9b1f41dbebe00fd9ec4d1e15a697971439Joe Onorato     * @param dragAction The drag action: either {@link #DRAG_ACTION_MOVE} or
2345162ea9b1f41dbebe00fd9ec4d1e15a697971439Joe Onorato     *        {@link #DRAG_ACTION_COPY}
2355162ea9b1f41dbebe00fd9ec4d1e15a697971439Joe Onorato     */
2365162ea9b1f41dbebe00fd9ec4d1e15a697971439Joe Onorato    public void startDrag(Bitmap b, int screenX, int screenY,
2375162ea9b1f41dbebe00fd9ec4d1e15a697971439Joe Onorato            DragSource source, Object dragInfo, int dragAction) {
2385f445425606b2c27276a79e9e871cf7f67b1b719Patrick Dubroy        startDrag(b, screenX, screenY, source, dragInfo, dragAction, null);
239a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka    }
240a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
241a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka    /**
242a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka     * Starts a drag.
243a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka     *
244a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka     * @param b The bitmap to display as the drag image.  It will be re-scaled to the
245a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka     *          enlarged size.
246a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka     * @param screenX The x position on screen of the left-top of the bitmap.
247a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka     * @param screenY The y position on screen of the left-top of the bitmap.
248a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka     * @param source An object representing where the drag originated
249a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka     * @param dragInfo The data associated with the object that is being dragged
250a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka     * @param dragAction The drag action: either {@link #DRAG_ACTION_MOVE} or
251a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka     *        {@link #DRAG_ACTION_COPY}
252a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka     * @param dragRegion Coordinates within the bitmap b for the position of item being dragged.
253a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka     *          Makes dragging feel more precise, e.g. you can clip out a transparent border
254a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka     */
255a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka    public void startDrag(Bitmap b, int screenX, int screenY,
256a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka            DragSource source, Object dragInfo, int dragAction, Rect dragRegion) {
25700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        if (PROFILE_DRAWING_DURING_DRAG) {
25800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            android.os.Debug.startMethodTracing("Launcher");
25900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        }
26000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
26100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        // Hide soft keyboard, if visible
26200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        if (mInputMethodManager == null) {
26300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            mInputMethodManager = (InputMethodManager)
26400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                    mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
26500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        }
26600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        mInputMethodManager.hideSoftInputFromWindow(mWindowToken, 0);
26700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
2684ed6278e518cc6894cb150b606382e8e6a012599Patrick Dubroy        for (DragListener listener : mListeners) {
2694ed6278e518cc6894cb150b606382e8e6a012599Patrick Dubroy            listener.onDragStart(source, dragInfo, dragAction);
27000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        }
27100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
272e3e27a854f3eca363d3c5ce353d19de475272d87Adam Cohen        final int registrationX = ((int)mMotionDownX) - screenX;
273e3e27a854f3eca363d3c5ce353d19de475272d87Adam Cohen        final int registrationY = ((int)mMotionDownY) - screenY;
27400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
275a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        final int dragRegionLeft = dragRegion == null ? 0 : dragRegion.left;
276a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        final int dragRegionTop = dragRegion == null ? 0 : dragRegion.top;
277e3e27a854f3eca363d3c5ce353d19de475272d87Adam Cohen
27800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        mDragging = true;
279cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen
280bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen        mDragObject.dragComplete = false;
281cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen        mDragObject.xOffset = mMotionDownX - (screenX + dragRegionLeft);
282cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen        mDragObject.yOffset = mMotionDownY - (screenY + dragRegionTop);
283cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen        mDragObject.dragSource = source;
284cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen        mDragObject.dragInfo = dragInfo;
28500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
28600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        mVibrator.vibrate(VIBRATE_DURATION);
28700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
288cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen        final DragView dragView = mDragObject.dragView = new DragView(mContext, b, registrationX,
289cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen                registrationY, 0, 0, b.getWidth(), b.getHeight());
290a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
291a669d79d0dcf034651ce305a8cd334272bec3374Patrick Dubroy        final DragSource dragSource = source;
292a669d79d0dcf034651ce305a8cd334272bec3374Patrick Dubroy        dragView.setOnDrawRunnable(new Runnable() {
293a669d79d0dcf034651ce305a8cd334272bec3374Patrick Dubroy            public void run() {
294a669d79d0dcf034651ce305a8cd334272bec3374Patrick Dubroy                dragSource.onDragViewVisible();
295a669d79d0dcf034651ce305a8cd334272bec3374Patrick Dubroy            };
296a669d79d0dcf034651ce305a8cd334272bec3374Patrick Dubroy        });
297a669d79d0dcf034651ce305a8cd334272bec3374Patrick Dubroy
298a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        if (dragRegion != null) {
299e3e27a854f3eca363d3c5ce353d19de475272d87Adam Cohen            dragView.setDragRegion(new Rect(dragRegion));
300a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka        }
301a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
30200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        dragView.show(mWindowToken, (int)mMotionDownX, (int)mMotionDownY);
303de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy
304de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy        handleMoveEvent((int) mMotionDownX, (int) mMotionDownY);
30500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    }
30600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
30700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    /**
30800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     * Draw the view into a bitmap.
30900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     */
310120980bd00f5eecec5717f49a3d7db96571025a9Adam Cohen    Bitmap getViewBitmap(View v) {
31100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        v.clearFocus();
31200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        v.setPressed(false);
31300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
31400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        boolean willNotCache = v.willNotCacheDrawing();
31500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        v.setWillNotCacheDrawing(false);
31600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
31700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        // Reset the drawing cache background color to fully transparent
31800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        // for the duration of this operation
31900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        int color = v.getDrawingCacheBackgroundColor();
32000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        v.setDrawingCacheBackgroundColor(0);
321120980bd00f5eecec5717f49a3d7db96571025a9Adam Cohen        float alpha = v.getAlpha();
322120980bd00f5eecec5717f49a3d7db96571025a9Adam Cohen        v.setAlpha(1.0f);
32300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
32400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        if (color != 0) {
32500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            v.destroyDrawingCache();
32600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        }
32700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        v.buildDrawingCache();
32800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        Bitmap cacheBitmap = v.getDrawingCache();
3293f8175a86e24b3568d1f5b12e1d3d5efcc57d691Daniel Sandler        if (cacheBitmap == null) {
3303f8175a86e24b3568d1f5b12e1d3d5efcc57d691Daniel Sandler            Log.e(TAG, "failed getViewBitmap(" + v + ")", new RuntimeException());
3313f8175a86e24b3568d1f5b12e1d3d5efcc57d691Daniel Sandler            return null;
3323f8175a86e24b3568d1f5b12e1d3d5efcc57d691Daniel Sandler        }
33300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
33400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        Bitmap bitmap = Bitmap.createBitmap(cacheBitmap);
33500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
33600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        // Restore the view
33700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        v.destroyDrawingCache();
338120980bd00f5eecec5717f49a3d7db96571025a9Adam Cohen        v.setAlpha(alpha);
33900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        v.setWillNotCacheDrawing(willNotCache);
34000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        v.setDrawingCacheBackgroundColor(color);
34100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
34200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        return bitmap;
34300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    }
34400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
34500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    /**
34600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     * Call this from a drag source view like this:
34700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     *
34800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     * <pre>
34900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     *  @Override
35000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     *  public boolean dispatchKeyEvent(KeyEvent event) {
35100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     *      return mDragController.dispatchKeyEvent(this, event)
35200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     *              || super.dispatchKeyEvent(event);
35300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     * </pre>
35400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     */
355ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy    @SuppressWarnings({"UnusedDeclaration"})
35600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    public boolean dispatchKeyEvent(KeyEvent event) {
35700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        return mDragging;
35800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    }
35900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
360304dcde0e301c2f1a0b2bdc80ea8617930691b6eWinson Chung    public boolean isDragging() {
361304dcde0e301c2f1a0b2bdc80ea8617930691b6eWinson Chung        return mDragging;
362304dcde0e301c2f1a0b2bdc80ea8617930691b6eWinson Chung    }
363304dcde0e301c2f1a0b2bdc80ea8617930691b6eWinson Chung
36424b6fd854f75f21700a330c2f0d11938e5dfeab6Joe Onorato    /**
36524b6fd854f75f21700a330c2f0d11938e5dfeab6Joe Onorato     * Stop dragging without dropping.
36624b6fd854f75f21700a330c2f0d11938e5dfeab6Joe Onorato     */
36724b6fd854f75f21700a330c2f0d11938e5dfeab6Joe Onorato    public void cancelDrag() {
368621e6406fadba27d6cff1c38b31d5cdf99c0f97aWinson Chung        if (mDragging) {
369c07918d0053fc7d2a19d7b013565a5d2e7d4af51Winson Chung            if (mLastDropTarget != null) {
370c07918d0053fc7d2a19d7b013565a5d2e7d4af51Winson Chung                mLastDropTarget.onDragExit(mDragObject);
371c07918d0053fc7d2a19d7b013565a5d2e7d4af51Winson Chung            }
372bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen            mDragObject.dragComplete = true;
373c0dcf597084d00e4c23a7fea5fd0738f6c095a6bAdam Cohen            mDragObject.dragSource.onDropCompleted(null, mDragObject, false);
374621e6406fadba27d6cff1c38b31d5cdf99c0f97aWinson Chung        }
37524b6fd854f75f21700a330c2f0d11938e5dfeab6Joe Onorato        endDrag();
37624b6fd854f75f21700a330c2f0d11938e5dfeab6Joe Onorato    }
37724b6fd854f75f21700a330c2f0d11938e5dfeab6Joe Onorato
37800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    private void endDrag() {
37900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        if (mDragging) {
38000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            mDragging = false;
3814ed6278e518cc6894cb150b606382e8e6a012599Patrick Dubroy            for (DragListener listener : mListeners) {
3824ed6278e518cc6894cb150b606382e8e6a012599Patrick Dubroy                listener.onDragEnd();
38300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            }
384cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen            if (mDragObject.dragView != null) {
385cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen                mDragObject.dragView.remove();
386cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen                mDragObject.dragView = null;
38700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            }
38800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        }
38900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    }
39000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
39100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    /**
39200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     * Call this from a drag source view.
39300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     */
39400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    public boolean onInterceptTouchEvent(MotionEvent ev) {
3959c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato        if (false) {
396a30ce8e6b25e41f392a41fd4d0d3e0a424a84dadJoe Onorato            Log.d(Launcher.TAG, "DragController.onInterceptTouchEvent " + ev + " mDragging="
3979c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato                    + mDragging);
3989c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato        }
39900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        final int action = ev.getAction();
40000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
40187467d3a2168180e8d6437d07d22b4dd0ef59845Joe Onorato        if (action == MotionEvent.ACTION_DOWN) {
40287467d3a2168180e8d6437d07d22b4dd0ef59845Joe Onorato            recordScreenSize();
40387467d3a2168180e8d6437d07d22b4dd0ef59845Joe Onorato        }
40487467d3a2168180e8d6437d07d22b4dd0ef59845Joe Onorato
405e048e8a8eff51e8c2c271d16c864367dac438ca2Joe Onorato        final int screenX = clamp((int)ev.getRawX(), 0, mDisplayMetrics.widthPixels);
406e048e8a8eff51e8c2c271d16c864367dac438ca2Joe Onorato        final int screenY = clamp((int)ev.getRawY(), 0, mDisplayMetrics.heightPixels);
40700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
40800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        switch (action) {
40900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            case MotionEvent.ACTION_MOVE:
41000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                break;
41100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            case MotionEvent.ACTION_DOWN:
41200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                // Remember location of down touch
41300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                mMotionDownX = screenX;
41400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                mMotionDownY = screenY;
41500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                mLastDropTarget = null;
41600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                break;
41700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            case MotionEvent.ACTION_UP:
41800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                if (mDragging) {
41900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                    drop(screenX, screenY);
42000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                }
42100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                endDrag();
42200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                break;
423621e6406fadba27d6cff1c38b31d5cdf99c0f97aWinson Chung            case MotionEvent.ACTION_CANCEL:
424621e6406fadba27d6cff1c38b31d5cdf99c0f97aWinson Chung                cancelDrag();
425621e6406fadba27d6cff1c38b31d5cdf99c0f97aWinson Chung                break;
42600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        }
42700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
42800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        return mDragging;
42900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    }
43000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
43100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    /**
432ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy     * Sets the view that should handle move events.
433ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy     */
434ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy    void setMoveTarget(View view) {
435ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy        mMoveTarget = view;
436ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy    }
437ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy
438ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy    public boolean dispatchUnhandledMove(View focused, int direction) {
439ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy        return mMoveTarget != null && mMoveTarget.dispatchUnhandledMove(focused, direction);
440ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy    }
441ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy
442de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy    private void handleMoveEvent(int x, int y) {
443cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen        mDragObject.dragView.move(x, y);
444de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy
445de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy        // Drop on someone?
446de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy        final int[] coordinates = mCoordinatesTemp;
447de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy        DropTarget dropTarget = findDropTarget(x, y, coordinates);
448cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen        mDragObject.x = coordinates[0];
449cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen        mDragObject.y = coordinates[1];
450de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy        if (dropTarget != null) {
451cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen            DropTarget delegate = dropTarget.getDropTargetDelegate(mDragObject);
452de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy            if (delegate != null) {
453de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy                dropTarget = delegate;
454de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy            }
455de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy
456de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy            if (mLastDropTarget != dropTarget) {
457de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy                if (mLastDropTarget != null) {
458cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen                    mLastDropTarget.onDragExit(mDragObject);
459de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy                }
460cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen                dropTarget.onDragEnter(mDragObject);
461de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy            }
462cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen            dropTarget.onDragOver(mDragObject);
463de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy        } else {
464de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy            if (mLastDropTarget != null) {
465cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen                mLastDropTarget.onDragExit(mDragObject);
466de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy            }
467de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy        }
468de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy        mLastDropTarget = dropTarget;
469de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy
470de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy        // Scroll, maybe, but not if we're in the delete region.
471de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy        boolean inDeleteRegion = false;
472de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy        if (mDeleteRegion != null) {
473de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy            inDeleteRegion = mDeleteRegion.contains(x, y);
474de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy        }
475a16fd5a6bd5371d40a5679261d416f06f8efa022Patrick Dubroy
476a16fd5a6bd5371d40a5679261d416f06f8efa022Patrick Dubroy        // After a scroll, the touch point will still be in the scroll region.
477a16fd5a6bd5371d40a5679261d416f06f8efa022Patrick Dubroy        // Rather than scrolling immediately, require a bit of twiddling to scroll again
478a16fd5a6bd5371d40a5679261d416f06f8efa022Patrick Dubroy        final int slop = ViewConfiguration.get(mContext).getScaledWindowTouchSlop();
479a16fd5a6bd5371d40a5679261d416f06f8efa022Patrick Dubroy        mDistanceSinceScroll +=
480a16fd5a6bd5371d40a5679261d416f06f8efa022Patrick Dubroy            Math.sqrt(Math.pow(mLastTouch[0] - x, 2) + Math.pow(mLastTouch[1] - y, 2));
481a16fd5a6bd5371d40a5679261d416f06f8efa022Patrick Dubroy        mLastTouch[0] = x;
482a16fd5a6bd5371d40a5679261d416f06f8efa022Patrick Dubroy        mLastTouch[1] = y;
483a16fd5a6bd5371d40a5679261d416f06f8efa022Patrick Dubroy
484658db74c24817892f1a379b16620744f38f60e40Joe Onorato        if (!inDeleteRegion && x < mScrollZone) {
485a16fd5a6bd5371d40a5679261d416f06f8efa022Patrick Dubroy            if (mScrollState == SCROLL_OUTSIDE_ZONE && mDistanceSinceScroll > slop) {
486de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy                mScrollState = SCROLL_WAITING_IN_ZONE;
487de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy                mScrollRunnable.setDirection(SCROLL_LEFT);
488de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy                mHandler.postDelayed(mScrollRunnable, SCROLL_DELAY);
4891262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy                mDragScroller.onEnterScrollArea(SCROLL_LEFT);
490de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy            }
491658db74c24817892f1a379b16620744f38f60e40Joe Onorato        } else if (!inDeleteRegion && x > mScrollView.getWidth() - mScrollZone) {
492a16fd5a6bd5371d40a5679261d416f06f8efa022Patrick Dubroy            if (mScrollState == SCROLL_OUTSIDE_ZONE && mDistanceSinceScroll > slop) {
493de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy                mScrollState = SCROLL_WAITING_IN_ZONE;
494de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy                mScrollRunnable.setDirection(SCROLL_RIGHT);
495de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy                mHandler.postDelayed(mScrollRunnable, SCROLL_DELAY);
4961262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy                mDragScroller.onEnterScrollArea(SCROLL_RIGHT);
497de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy            }
498de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy        } else {
499de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy            if (mScrollState == SCROLL_WAITING_IN_ZONE) {
500de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy                mScrollState = SCROLL_OUTSIDE_ZONE;
501de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy                mScrollRunnable.setDirection(SCROLL_RIGHT);
502de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy                mHandler.removeCallbacks(mScrollRunnable);
5031262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy                mDragScroller.onExitScrollArea();
504de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy            }
505de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy        }
506de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy    }
507de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy
508ea3763c2672f77539538af8cdd395ad97058eaabRomain Guy    /**
50900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     * Call this from a drag source view.
51000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     */
51100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    public boolean onTouchEvent(MotionEvent ev) {
51200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        if (!mDragging) {
51300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            return false;
51400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        }
51500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
51600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        final int action = ev.getAction();
517e048e8a8eff51e8c2c271d16c864367dac438ca2Joe Onorato        final int screenX = clamp((int)ev.getRawX(), 0, mDisplayMetrics.widthPixels);
518e048e8a8eff51e8c2c271d16c864367dac438ca2Joe Onorato        final int screenY = clamp((int)ev.getRawY(), 0, mDisplayMetrics.heightPixels);
51900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
52000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        switch (action) {
52100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        case MotionEvent.ACTION_DOWN:
52200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            // Remember where the motion event started
523e048e8a8eff51e8c2c271d16c864367dac438ca2Joe Onorato            mMotionDownX = screenX;
524e048e8a8eff51e8c2c271d16c864367dac438ca2Joe Onorato            mMotionDownY = screenY;
52500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
526658db74c24817892f1a379b16620744f38f60e40Joe Onorato            if ((screenX < mScrollZone) || (screenX > mScrollView.getWidth() - mScrollZone)) {
52700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                mScrollState = SCROLL_WAITING_IN_ZONE;
52800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                mHandler.postDelayed(mScrollRunnable, SCROLL_DELAY);
52900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            } else {
53000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                mScrollState = SCROLL_OUTSIDE_ZONE;
53100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            }
53200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            break;
53300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        case MotionEvent.ACTION_MOVE:
534de7658b5e02ae10010e44fcf8d9c5814f54d9eb0Patrick Dubroy            handleMoveEvent(screenX, screenY);
53500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            break;
53600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        case MotionEvent.ACTION_UP:
537b0a6bbeeab0960419dcd1f695c209ca0ec36ab8aPatrick Dubroy            // Ensure that we've processed a move event at the current pointer location.
538b0a6bbeeab0960419dcd1f695c209ca0ec36ab8aPatrick Dubroy            handleMoveEvent(screenX, screenY);
539b0a6bbeeab0960419dcd1f695c209ca0ec36ab8aPatrick Dubroy
54000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            mHandler.removeCallbacks(mScrollRunnable);
54100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            if (mDragging) {
542e048e8a8eff51e8c2c271d16c864367dac438ca2Joe Onorato                drop(screenX, screenY);
54300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            }
54400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            endDrag();
54500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            break;
54600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        case MotionEvent.ACTION_CANCEL:
54724b6fd854f75f21700a330c2f0d11938e5dfeab6Joe Onorato            cancelDrag();
548621e6406fadba27d6cff1c38b31d5cdf99c0f97aWinson Chung            break;
54900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        }
55000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
55100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        return true;
55200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    }
55300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
554b0a6bbeeab0960419dcd1f695c209ca0ec36ab8aPatrick Dubroy    private void drop(float x, float y) {
55500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        final int[] coordinates = mCoordinatesTemp;
556b0a6bbeeab0960419dcd1f695c209ca0ec36ab8aPatrick Dubroy        final DropTarget dropTarget = findDropTarget((int) x, (int) y, coordinates);
55700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
558cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen        mDragObject.x = coordinates[0];
559cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen        mDragObject.y = coordinates[1];
560b0a6bbeeab0960419dcd1f695c209ca0ec36ab8aPatrick Dubroy        boolean accepted = false;
56100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        if (dropTarget != null) {
562bfbfd26c627a18f8e1e3e6d0e53e78feab360203Adam Cohen            mDragObject.dragComplete = true;
563cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen            dropTarget.onDragExit(mDragObject);
564cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen            if (dropTarget.acceptDrop(mDragObject)) {
565cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen                dropTarget.onDrop(mDragObject);
566b0a6bbeeab0960419dcd1f695c209ca0ec36ab8aPatrick Dubroy                accepted = true;
56700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            }
56800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        }
569c0dcf597084d00e4c23a7fea5fd0738f6c095a6bAdam Cohen        mDragObject.dragSource.onDropCompleted((View) dropTarget, mDragObject, accepted);
57000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    }
57100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
57200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    private DropTarget findDropTarget(int x, int y, int[] dropCoordinates) {
57300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        final Rect r = mRectTemp;
57400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
57500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        final ArrayList<DropTarget> dropTargets = mDropTargets;
57600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        final int count = dropTargets.size();
57700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        for (int i=count-1; i>=0; i--) {
578440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            DropTarget target = dropTargets.get(i);
5790280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka            if (!target.isDropEnabled())
5800280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka                continue;
5810280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka
58200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            target.getHitRect(r);
583440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy
584440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy            // Convert the hit rect to screen coordinates
58500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            target.getLocationOnScreen(dropCoordinates);
58600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            r.offset(dropCoordinates[0] - target.getLeft(), dropCoordinates[1] - target.getTop());
587440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy
588cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen            mDragObject.x = x;
589cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen            mDragObject.y = y;
59000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            if (r.contains(x, y)) {
591cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen                DropTarget delegate = target.getDropTargetDelegate(mDragObject);
592440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy                if (delegate != null) {
593440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy                    target = delegate;
594440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy                    target.getLocationOnScreen(dropCoordinates);
595440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy                }
596440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy
597440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy                // Make dropCoordinates relative to the DropTarget
59800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                dropCoordinates[0] = x - dropCoordinates[0];
59900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                dropCoordinates[1] = y - dropCoordinates[1];
600440c360bc395c43683fa9ca226e59f9e35f9e926Patrick Dubroy
60100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                return target;
60200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            }
60300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        }
60400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        return null;
60500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    }
60600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
607e048e8a8eff51e8c2c271d16c864367dac438ca2Joe Onorato    /**
608e048e8a8eff51e8c2c271d16c864367dac438ca2Joe Onorato     * Get the screen size so we can clamp events to the screen size so even if
609e048e8a8eff51e8c2c271d16c864367dac438ca2Joe Onorato     * you drag off the edge of the screen, we find something.
610e048e8a8eff51e8c2c271d16c864367dac438ca2Joe Onorato     */
611e048e8a8eff51e8c2c271d16c864367dac438ca2Joe Onorato    private void recordScreenSize() {
612e048e8a8eff51e8c2c271d16c864367dac438ca2Joe Onorato        ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE))
613e048e8a8eff51e8c2c271d16c864367dac438ca2Joe Onorato                .getDefaultDisplay().getMetrics(mDisplayMetrics);
614e048e8a8eff51e8c2c271d16c864367dac438ca2Joe Onorato    }
615e048e8a8eff51e8c2c271d16c864367dac438ca2Joe Onorato
616e048e8a8eff51e8c2c271d16c864367dac438ca2Joe Onorato    /**
617e048e8a8eff51e8c2c271d16c864367dac438ca2Joe Onorato     * Clamp val to be &gt;= min and &lt; max.
618e048e8a8eff51e8c2c271d16c864367dac438ca2Joe Onorato     */
619e048e8a8eff51e8c2c271d16c864367dac438ca2Joe Onorato    private static int clamp(int val, int min, int max) {
620e048e8a8eff51e8c2c271d16c864367dac438ca2Joe Onorato        if (val < min) {
621e048e8a8eff51e8c2c271d16c864367dac438ca2Joe Onorato            return min;
622e048e8a8eff51e8c2c271d16c864367dac438ca2Joe Onorato        } else if (val >= max) {
623e048e8a8eff51e8c2c271d16c864367dac438ca2Joe Onorato            return max - 1;
624e048e8a8eff51e8c2c271d16c864367dac438ca2Joe Onorato        } else {
625e048e8a8eff51e8c2c271d16c864367dac438ca2Joe Onorato            return val;
626e048e8a8eff51e8c2c271d16c864367dac438ca2Joe Onorato        }
627e048e8a8eff51e8c2c271d16c864367dac438ca2Joe Onorato    }
628e048e8a8eff51e8c2c271d16c864367dac438ca2Joe Onorato
62900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    public void setDragScoller(DragScroller scroller) {
63000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        mDragScroller = scroller;
63100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    }
63200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
63300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    public void setWindowToken(IBinder token) {
63400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        mWindowToken = token;
63500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    }
63600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
63731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
63831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Sets the drag listner which will be notified when a drag starts or ends.
63931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
6404ed6278e518cc6894cb150b606382e8e6a012599Patrick Dubroy    public void addDragListener(DragListener l) {
6414ed6278e518cc6894cb150b606382e8e6a012599Patrick Dubroy        mListeners.add(l);
64200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    }
64300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
64431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
64531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     * Remove a previously installed drag listener.
64631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
64700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    public void removeDragListener(DragListener l) {
6484ed6278e518cc6894cb150b606382e8e6a012599Patrick Dubroy        mListeners.remove(l);
64900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    }
65000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
65100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    /**
65200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     * Add a DropTarget to the list of potential places to receive drop events.
65300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     */
65400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    public void addDropTarget(DropTarget target) {
65500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        mDropTargets.add(target);
65600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    }
65700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
65800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    /**
65900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     * Don't send drop events to <em>target</em> any more.
66000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     */
66100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    public void removeDropTarget(DropTarget target) {
66200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        mDropTargets.remove(target);
66300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    }
66400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
66500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    /**
66600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     * Set which view scrolls for touch events near the edge of the screen.
66700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     */
66800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    public void setScrollView(View v) {
66900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        mScrollView = v;
67000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    }
67100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
67200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    /**
67300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     * Specifies the delete region.  We won't scroll on touch events over the delete region.
67400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     *
67500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     * @param region The rectangle in screen coordinates of the delete region.
67600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato     */
67700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    void setDeleteRegion(RectF region) {
67800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        mDeleteRegion = region;
67900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    }
68000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
6815f445425606b2c27276a79e9e871cf7f67b1b719Patrick Dubroy    DragView getDragView() {
682cb3382b1bfe1a534b1b44f5c4def9b2db605ac90Adam Cohen        return mDragObject.dragView;
6835f445425606b2c27276a79e9e871cf7f67b1b719Patrick Dubroy    }
6845f445425606b2c27276a79e9e871cf7f67b1b719Patrick Dubroy
68500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    private class ScrollRunnable implements Runnable {
68600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        private int mDirection;
68700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
68800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        ScrollRunnable() {
68900acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        }
69000acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
69100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        public void run() {
69200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            if (mDragScroller != null) {
69300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                if (mDirection == SCROLL_LEFT) {
69400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                    mDragScroller.scrollLeft();
69500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                } else {
69600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                    mDragScroller.scrollRight();
69700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                }
69800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato                mScrollState = SCROLL_OUTSIDE_ZONE;
699a16fd5a6bd5371d40a5679261d416f06f8efa022Patrick Dubroy                mDistanceSinceScroll = 0;
700a16fd5a6bd5371d40a5679261d416f06f8efa022Patrick Dubroy                mDragScroller.onExitScrollArea();
70100acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            }
70200acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        }
70300acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato
70400acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        void setDirection(int direction) {
70500acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato            mDirection = direction;
70600acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato        }
70700acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato    }
70831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project}
709