DragEvent.java revision 2c095f367779ef32130c72849936a2e3013c8492
1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.view;
18
19import android.content.ClipData;
20import android.content.ClipDescription;
21import android.os.Parcel;
22import android.os.Parcelable;
23
24/** !!! TODO: real docs */
25public class DragEvent implements Parcelable {
26    private static final boolean TRACK_RECYCLED_LOCATION = false;
27
28    int mAction;
29    float mX, mY;
30    ClipDescription mClipDescription;
31    ClipData mClipData;
32
33    private DragEvent mNext;
34    private RuntimeException mRecycledLocation;
35    private boolean mRecycled;
36
37    private static final int MAX_RECYCLED = 10;
38    private static final Object gRecyclerLock = new Object();
39    private static int gRecyclerUsed = 0;
40    private static DragEvent gRecyclerTop = null;
41
42    /**
43     * action constants for DragEvent dispatch
44     */
45    public static final int ACTION_DRAG_STARTED = 1;
46    public static final int ACTION_DRAG_LOCATION = 2;
47    public static final int ACTION_DROP = 3;
48    public static final int ACTION_DRAG_ENDED = 4;
49    public static final int ACTION_DRAG_ENTERED = 5;
50    public static final int ACTION_DRAG_EXITED = 6;
51
52    /* hide the constructor behind package scope */
53    private DragEvent() {
54    }
55
56    static DragEvent obtain() {
57        return DragEvent.obtain(0, 0f, 0f, null, null);
58    }
59
60    public static DragEvent obtain(int action, float x, float y,
61            ClipDescription description, ClipData data) {
62        final DragEvent ev;
63        synchronized (gRecyclerLock) {
64            if (gRecyclerTop == null) {
65                return new DragEvent();
66            }
67            ev = gRecyclerTop;
68            gRecyclerTop = ev.mNext;
69            gRecyclerUsed -= 1;
70        }
71        ev.mRecycledLocation = null;
72        ev.mRecycled = false;
73        ev.mNext = null;
74
75        ev.mAction = action;
76        ev.mX = x;
77        ev.mY = y;
78        ev.mClipDescription = description;
79        ev.mClipData = data;
80
81        return ev;
82    }
83
84    public static DragEvent obtain(DragEvent source) {
85        return obtain(source.mAction, source.mX, source.mY,
86                source.mClipDescription, source.mClipData);
87    }
88
89    public int getAction() {
90        return mAction;
91    }
92
93    public float getX() {
94        return mX;
95    }
96
97    public float getY() {
98        return mY;
99    }
100
101    public ClipData getClipData() {
102        return mClipData;
103    }
104
105    public ClipDescription getClipDescription() {
106        return mClipDescription;
107    }
108
109    /**
110     * Recycle the DragEvent, to be re-used by a later caller.  After calling
111     * this function you must never touch the event again.
112     */
113    public final void recycle() {
114        // Ensure recycle is only called once!
115        if (TRACK_RECYCLED_LOCATION) {
116            if (mRecycledLocation != null) {
117                throw new RuntimeException(toString() + " recycled twice!", mRecycledLocation);
118            }
119            mRecycledLocation = new RuntimeException("Last recycled here");
120        } else {
121            if (mRecycled) {
122                throw new RuntimeException(toString() + " recycled twice!");
123            }
124            mRecycled = true;
125        }
126
127        mClipData = null;
128        mClipDescription = null;
129
130        synchronized (gRecyclerLock) {
131            if (gRecyclerUsed < MAX_RECYCLED) {
132                gRecyclerUsed++;
133                mNext = gRecyclerTop;
134                gRecyclerTop = this;
135            }
136        }
137    }
138
139    @Override
140    public String toString() {
141        return "DragEvent{" + Integer.toHexString(System.identityHashCode(this))
142        + " action=" + mAction + " @ (" + mX + ", " + mY + ") desc=" + mClipDescription
143        + " data=" + mClipData
144        + "}";
145    }
146
147    /* Parcelable interface */
148
149    public int describeContents() {
150        return 0;
151    }
152
153    public void writeToParcel(Parcel dest, int flags) {
154        dest.writeInt(mAction);
155        dest.writeFloat(mX);
156        dest.writeFloat(mY);
157        if (mClipData == null) {
158            dest.writeInt(0);
159        } else {
160            dest.writeInt(1);
161            mClipData.writeToParcel(dest, flags);
162        }
163        if (mClipDescription == null) {
164            dest.writeInt(0);
165        } else {
166            dest.writeInt(1);
167            mClipDescription.writeToParcel(dest, flags);
168        }
169    }
170
171    public static final Parcelable.Creator<DragEvent> CREATOR =
172        new Parcelable.Creator<DragEvent>() {
173        public DragEvent createFromParcel(Parcel in) {
174            DragEvent event = DragEvent.obtain();
175            event.mAction = in.readInt();
176            event.mX = in.readFloat();
177            event.mY = in.readFloat();
178            if (in.readInt() != 0) {
179                event.mClipData = ClipData.CREATOR.createFromParcel(in);
180            }
181            if (in.readInt() != 0) {
182                event.mClipDescription = ClipDescription.CREATOR.createFromParcel(in);
183            }
184            return event;
185        }
186
187        public DragEvent[] newArray(int size) {
188            return new DragEvent[size];
189        }
190    };
191}
192