DragEvent.java revision c02c7af0ec88ec56089a11138d5fcfafcf891c58
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    private void init(int action, float x, float y, ClipDescription description, ClipData data) {
57        mAction = action;
58        mX = x;
59        mY = y;
60        mClipDescription = description;
61        mClipData = data;
62    }
63
64    static DragEvent obtain() {
65        return DragEvent.obtain(0, 0f, 0f, null, null);
66    }
67
68    public static DragEvent obtain(int action, float x, float y,
69            ClipDescription description, ClipData data) {
70        final DragEvent ev;
71        synchronized (gRecyclerLock) {
72            if (gRecyclerTop == null) {
73                ev = new DragEvent();
74                ev.init(action, x, y, description, data);
75                return ev;
76            }
77            ev = gRecyclerTop;
78            gRecyclerTop = ev.mNext;
79            gRecyclerUsed -= 1;
80        }
81        ev.mRecycledLocation = null;
82        ev.mRecycled = false;
83        ev.mNext = null;
84
85        ev.init(action, x, y, description, data);
86
87        return ev;
88    }
89
90    public static DragEvent obtain(DragEvent source) {
91        return obtain(source.mAction, source.mX, source.mY,
92                source.mClipDescription, source.mClipData);
93    }
94
95    public int getAction() {
96        return mAction;
97    }
98
99    public float getX() {
100        return mX;
101    }
102
103    public float getY() {
104        return mY;
105    }
106
107    public ClipData getClipData() {
108        return mClipData;
109    }
110
111    public ClipDescription getClipDescription() {
112        return mClipDescription;
113    }
114
115    /**
116     * Recycle the DragEvent, to be re-used by a later caller.  After calling
117     * this function you must never touch the event again.
118     */
119    public final void recycle() {
120        // Ensure recycle is only called once!
121        if (TRACK_RECYCLED_LOCATION) {
122            if (mRecycledLocation != null) {
123                throw new RuntimeException(toString() + " recycled twice!", mRecycledLocation);
124            }
125            mRecycledLocation = new RuntimeException("Last recycled here");
126        } else {
127            if (mRecycled) {
128                throw new RuntimeException(toString() + " recycled twice!");
129            }
130            mRecycled = true;
131        }
132
133        mClipData = null;
134        mClipDescription = null;
135
136        synchronized (gRecyclerLock) {
137            if (gRecyclerUsed < MAX_RECYCLED) {
138                gRecyclerUsed++;
139                mNext = gRecyclerTop;
140                gRecyclerTop = this;
141            }
142        }
143    }
144
145    @Override
146    public String toString() {
147        return "DragEvent{" + Integer.toHexString(System.identityHashCode(this))
148        + " action=" + mAction + " @ (" + mX + ", " + mY + ") desc=" + mClipDescription
149        + " data=" + mClipData
150        + "}";
151    }
152
153    /* Parcelable interface */
154
155    public int describeContents() {
156        return 0;
157    }
158
159    public void writeToParcel(Parcel dest, int flags) {
160        dest.writeInt(mAction);
161        dest.writeFloat(mX);
162        dest.writeFloat(mY);
163        if (mClipData == null) {
164            dest.writeInt(0);
165        } else {
166            dest.writeInt(1);
167            mClipData.writeToParcel(dest, flags);
168        }
169        if (mClipDescription == null) {
170            dest.writeInt(0);
171        } else {
172            dest.writeInt(1);
173            mClipDescription.writeToParcel(dest, flags);
174        }
175    }
176
177    public static final Parcelable.Creator<DragEvent> CREATOR =
178        new Parcelable.Creator<DragEvent>() {
179        public DragEvent createFromParcel(Parcel in) {
180            DragEvent event = DragEvent.obtain();
181            event.mAction = in.readInt();
182            event.mX = in.readFloat();
183            event.mY = in.readFloat();
184            if (in.readInt() != 0) {
185                event.mClipData = ClipData.CREATOR.createFromParcel(in);
186            }
187            if (in.readInt() != 0) {
188                event.mClipDescription = ClipDescription.CREATOR.createFromParcel(in);
189            }
190            return event;
191        }
192
193        public DragEvent[] newArray(int size) {
194            return new DragEvent[size];
195        }
196    };
197}
198