18f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate/*
28f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate * Copyright (C) 2010 The Android Open Source Project
38f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate *
48f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate * Licensed under the Apache License, Version 2.0 (the "License");
58f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate * you may not use this file except in compliance with the License.
68f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate * You may obtain a copy of the License at
78f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate *
88f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate *      http://www.apache.org/licenses/LICENSE-2.0
98f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate *
108f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate * Unless required by applicable law or agreed to in writing, software
118f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate * distributed under the License is distributed on an "AS IS" BASIS,
128f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate * See the License for the specific language governing permissions and
148f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate * limitations under the License.
158f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate */
168f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate
178f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tatepackage com.example.android.apis.view;
188f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate
198f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tateimport com.example.android.apis.R;
208f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate
218f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tateimport android.content.ClipData;
228f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tateimport android.content.Context;
238f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tateimport android.content.res.TypedArray;
248f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tateimport android.graphics.*;
258f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tateimport android.os.SystemClock;
268f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tateimport android.text.TextPaint;
278f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tateimport android.util.AttributeSet;
288f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tateimport android.util.Log;
298f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tateimport android.view.DragEvent;
308f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tateimport android.view.View;
318f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tateimport android.widget.TextView;
328f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate
338f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tatepublic class DraggableDot extends View {
348f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate    static final String TAG = "DraggableDot";
358f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate
368f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate    private boolean mDragInProgress;
378f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate    private boolean mHovering;
388f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate    private boolean mAcceptsDrag;
398f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate    TextView mReportView;
408f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate
418f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate    private Paint mPaint;
428f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate    private TextPaint mLegendPaint;
438f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate    private Paint mGlow;
448f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate    private static final int NUM_GLOW_STEPS = 10;
458f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate    private static final int GREEN_STEP = 0x0000FF00 / NUM_GLOW_STEPS;
468f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate    private static final int WHITE_STEP = 0x00FFFFFF / NUM_GLOW_STEPS;
478f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate    private static final int ALPHA_STEP = 0xFF000000 / NUM_GLOW_STEPS;
488f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate
498f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate    int mRadius;
508f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate    int mAnrType;
518f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate    CharSequence mLegend;
528f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate
538f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate    static final int ANR_NONE = 0;
547f68ce1a1913bb8ffa13cf518b0daaa1bcf5eb4dChristopher Tate    static final int ANR_SHADOW = 1;
558f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate    static final int ANR_DROP = 2;
568f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate
578f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate    void sleepSixSeconds() {
588f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate        // hang forever; good for producing ANRs
598f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate        long start = SystemClock.uptimeMillis();
608f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate        do {
618f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate            try { Thread.sleep(1000); } catch (InterruptedException e) {}
628f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate        } while (SystemClock.uptimeMillis() < start + 6000);
638f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate    }
648f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate
657f68ce1a1913bb8ffa13cf518b0daaa1bcf5eb4dChristopher Tate    // Shadow builder that can ANR if desired
667f68ce1a1913bb8ffa13cf518b0daaa1bcf5eb4dChristopher Tate    class ANRShadowBuilder extends DragShadowBuilder {
678f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate        boolean mDoAnr;
688f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate
697f68ce1a1913bb8ffa13cf518b0daaa1bcf5eb4dChristopher Tate        public ANRShadowBuilder(View view, boolean doAnr) {
708f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate            super(view);
718f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate            mDoAnr = doAnr;
728f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate        }
738f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate
748f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate        @Override
757f68ce1a1913bb8ffa13cf518b0daaa1bcf5eb4dChristopher Tate        public void onDrawShadow(Canvas canvas) {
768f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate            if (mDoAnr) {
778f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate                sleepSixSeconds();
788f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate            }
797f68ce1a1913bb8ffa13cf518b0daaa1bcf5eb4dChristopher Tate            super.onDrawShadow(canvas);
808f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate        }
818f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate    }
828f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate
838f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate    public DraggableDot(Context context, AttributeSet attrs) {
848f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate        super(context, attrs);
858f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate
868f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate        setFocusable(true);
878f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate        setClickable(true);
888f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate
898f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate        mLegend = "";
908f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate
918f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate        mPaint = new Paint();
928f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate        mPaint.setAntiAlias(true);
938f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate        mPaint.setStrokeWidth(6);
948f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate        mPaint.setColor(0xFFD00000);
958f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate
968f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate        mLegendPaint = new TextPaint();
978f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate        mLegendPaint.setAntiAlias(true);
988f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate        mLegendPaint.setTextAlign(Paint.Align.CENTER);
998f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate        mLegendPaint.setColor(0xFFF0F0FF);
1008f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate
1018f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate        mGlow = new Paint();
1028f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate        mGlow.setAntiAlias(true);
1038f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate        mGlow.setStrokeWidth(1);
1048f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate        mGlow.setStyle(Paint.Style.STROKE);
1058f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate
1068f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate        // look up any layout-defined attributes
1078f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate        TypedArray a = context.obtainStyledAttributes(attrs,
1088f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate                R.styleable.DraggableDot);
1098f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate
1108f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate        final int N = a.getIndexCount();
1118f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate        for (int i = 0; i < N; i++) {
1128f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate            int attr = a.getIndex(i);
1138f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate            switch (attr) {
1148f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate            case R.styleable.DraggableDot_radius: {
1158f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate                mRadius = a.getDimensionPixelSize(attr, 0);
1168f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate            } break;
1178f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate
1188f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate            case R.styleable.DraggableDot_legend: {
1198f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate                mLegend = a.getText(attr);
1208f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate            } break;
1218f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate
1228f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate            case R.styleable.DraggableDot_anr: {
1238f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate                mAnrType = a.getInt(attr, 0);
1248f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate            } break;
1258f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate            }
1268f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate        }
1278f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate
1288f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate        Log.i(TAG, "DraggableDot @ " + this + " : radius=" + mRadius + " legend='" + mLegend
129134fada434cae8dc5a00b91cb5ff0541de94ea64Christopher Tate                + "' anr=" + mAnrType);
1308f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate
1318f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate        setOnLongClickListener(new View.OnLongClickListener() {
1328f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate            public boolean onLongClick(View v) {
1330d11c9c34501a9a9dedee1092fd63af218dc28c8Dianne Hackborn                ClipData data = ClipData.newPlainText("dot", "Dot : " + v.toString());
1347f68ce1a1913bb8ffa13cf518b0daaa1bcf5eb4dChristopher Tate                v.startDrag(data, new ANRShadowBuilder(v, mAnrType == ANR_SHADOW),
135134fada434cae8dc5a00b91cb5ff0541de94ea64Christopher Tate                        (Object)v, 0);
1368f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate                return true;
1378f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate            }
1388f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate        });
1398f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate    }
1408f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate
1418f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate    void setReportView(TextView view) {
1428f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate        mReportView = view;
1438f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate    }
1448f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate
1458f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate    @Override
1468f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate    protected void onDraw(Canvas canvas) {
1478f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate        float wf = getWidth();
1488f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate        float hf = getHeight();
1498f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate        final float cx = wf/2;
1508f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate        final float cy = hf/2;
1518f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate        wf -= getPaddingLeft() + getPaddingRight();
1528f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate        hf -= getPaddingTop() + getPaddingBottom();
1538f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate        float rad = (wf < hf) ? wf/2 : hf/2;
1548f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate        canvas.drawCircle(cx, cy, rad, mPaint);
1558f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate
1568f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate        if (mLegend != null && mLegend.length() > 0) {
1578f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate            canvas.drawText(mLegend, 0, mLegend.length(),
1588f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate                    cx, cy + mLegendPaint.getFontSpacing()/2,
1598f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate                    mLegendPaint);
1608f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate        }
1618f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate
1628f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate        // if we're in the middle of a drag, light up as a potential target
1638f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate        if (mDragInProgress && mAcceptsDrag) {
1648f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate            for (int i = NUM_GLOW_STEPS; i > 0; i--) {
1658f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate                int color = (mHovering) ? WHITE_STEP : GREEN_STEP;
1668f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate                color = i*(color | ALPHA_STEP);
1678f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate                mGlow.setColor(color);
1688f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate                canvas.drawCircle(cx, cy, rad, mGlow);
1698f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate                rad -= 0.5f;
1708f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate                canvas.drawCircle(cx, cy, rad, mGlow);
1718f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate                rad -= 0.5f;
1728f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate            }
1738f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate        }
1748f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate    }
1758f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate
1768f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate    @Override
1778f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate    protected void onMeasure(int widthSpec, int heightSpec) {
1788f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate        int totalDiameter = 2*mRadius + getPaddingLeft() + getPaddingRight();
1798f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate        setMeasuredDimension(totalDiameter, totalDiameter);
1808f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate    }
1818f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate
1828f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate    /**
1838f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate     * Drag and drop
1848f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate     */
1858f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate    @Override
1868f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate    public boolean onDragEvent(DragEvent event) {
1878f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate        boolean result = false;
1888f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate        switch (event.getAction()) {
1898f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate        case DragEvent.ACTION_DRAG_STARTED: {
1908f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate            // claim to accept any dragged content
1918f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate            Log.i(TAG, "Drag started, event=" + event);
1928f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate            // cache whether we accept the drag to return for LOCATION events
1938f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate            mDragInProgress = true;
1948f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate            mAcceptsDrag = result = true;
1958f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate            // Redraw in the new visual state if we are a potential drop target
1968f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate            if (mAcceptsDrag) {
1978f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate                invalidate();
1988f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate            }
1998f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate        } break;
2008f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate
2018f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate        case DragEvent.ACTION_DRAG_ENDED: {
2028f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate            Log.i(TAG, "Drag ended.");
2038f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate            if (mAcceptsDrag) {
2048f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate                invalidate();
2058f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate            }
2068f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate            mDragInProgress = false;
2078f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate            mHovering = false;
2088f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate        } break;
2098f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate
2108f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate        case DragEvent.ACTION_DRAG_LOCATION: {
2118f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate            // we returned true to DRAG_STARTED, so return true here
2128f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate            Log.i(TAG, "... seeing drag locations ...");
2138f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate            result = mAcceptsDrag;
2148f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate        } break;
2158f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate
2168f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate        case DragEvent.ACTION_DROP: {
2178f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate            Log.i(TAG, "Got a drop! dot=" + this + " event=" + event);
2188f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate            if (mAnrType == ANR_DROP) {
2198f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate                sleepSixSeconds();
2208f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate            }
2218f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate            processDrop(event);
2228f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate            result = true;
2238f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate        } break;
2248f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate
2258f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate        case DragEvent.ACTION_DRAG_ENTERED: {
2268f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate            Log.i(TAG, "Entered dot @ " + this);
2278f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate            mHovering = true;
2288f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate            invalidate();
2298f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate        } break;
2308f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate
2318f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate        case DragEvent.ACTION_DRAG_EXITED: {
2328f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate            Log.i(TAG, "Exited dot @ " + this);
2338f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate            mHovering = false;
2348f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate            invalidate();
2358f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate        } break;
2368f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate
2378f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate        default:
2388f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate            Log.i(TAG, "other drag event: " + event);
2398f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate            result = mAcceptsDrag;
2408f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate            break;
2418f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate        }
2428f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate
2438f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate        return result;
2448f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate    }
2458f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate
2468f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate    private void processDrop(DragEvent event) {
2478f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate        final ClipData data = event.getClipData();
2488f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate        final int N = data.getItemCount();
2498f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate        for (int i = 0; i < N; i++) {
2500d11c9c34501a9a9dedee1092fd63af218dc28c8Dianne Hackborn            ClipData.Item item = data.getItemAt(i);
2518f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate            Log.i(TAG, "Dropped item " + i + " : " + item);
2528f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate            if (mReportView != null) {
2538f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate                String text = item.coerceToText(getContext()).toString();
2548f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate                if (event.getLocalState() == (Object) this) {
2558f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate                    text += " : Dropped on self!";
2568f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate                }
2578f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate                mReportView.setText(text);
2588f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate            }
2598f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate        }
2608f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate    }
2618f2e8f48b924ecc87086b8ab7af348031dd848c9Christopher Tate}