1135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren/*
2135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren * Copyright (C) 2012 The Android Open Source Project
3135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren *
4135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren * Licensed under the Apache License, Version 2.0 (the "License");
5135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren * you may not use this file except in compliance with the License.
6135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren * You may obtain a copy of the License at
7135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren *
8135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren *      http://www.apache.org/licenses/LICENSE-2.0
9135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren *
10135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren * Unless required by applicable law or agreed to in writing, software
11135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren * distributed under the License is distributed on an "AS IS" BASIS,
12135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren * See the License for the specific language governing permissions and
14135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren * limitations under the License.
15135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren */
16135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wrenpackage com.android.dreams.phototable;
17135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren
18135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wrenimport android.content.Context;
19135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wrenimport android.content.res.Resources;
20135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wrenimport android.util.Log;
21135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wrenimport android.view.MotionEvent;
22135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wrenimport android.view.View;
23135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wrenimport android.view.ViewConfiguration;
24135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren
25135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren/**
26135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren * Touch listener that implements phototable interactions.
27135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren */
28135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wrenpublic class PhotoTouchListener implements View.OnTouchListener {
29135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren    private static final String TAG = "PhotoTouchListener";
30c1501041b64faa6c205a93baf403c4c87a0c1acfChris Wren    private static final boolean DEBUG = false;
31135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren    private static final int INVALID_POINTER = -1;
32135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren    private static final int MAX_POINTER_COUNT = 10;
33135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren    private final int mTouchSlop;
34135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren    private final int mTapTimeout;
35d85f53c69dead1f1f6c0290b8104422143bc5166Chris Wren    private final PhotoTable mTable;
36135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren    private final float mBeta;
37135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren    private final boolean mEnableFling;
38135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren    private final boolean mManualImageRotation;
39135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren    private long mLastEventTime;
40135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren    private float mLastTouchX;
41135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren    private float mLastTouchY;
42135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren    private float mInitialTouchX;
43135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren    private float mInitialTouchY;
44135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren    private float mInitialTouchA;
45135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren    private long mInitialTouchTime;
46135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren    private float mInitialTargetX;
47135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren    private float mInitialTargetY;
48135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren    private float mInitialTargetA;
49135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren    private float mDX;
50135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren    private float mDY;
51135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren    private int mA = INVALID_POINTER;
52135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren    private int mB = INVALID_POINTER;
53135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren    private float[] pts = new float[MAX_POINTER_COUNT];
54135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren
55d85f53c69dead1f1f6c0290b8104422143bc5166Chris Wren    public PhotoTouchListener(Context context, PhotoTable table) {
56135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren        mTable = table;
57135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren        final ViewConfiguration configuration = ViewConfiguration.get(context);
58135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren        mTouchSlop = configuration.getScaledTouchSlop();
5988d80f4471c900628e2cb6eef23029b99af48e09Chris Wren        mTapTimeout = ViewConfiguration.getTapTimeout();
60135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren        final Resources resources = context.getResources();
61135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren        mBeta = resources.getInteger(R.integer.table_damping) / 1000000f;
62135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren        mEnableFling = resources.getBoolean(R.bool.enable_fling);
63135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren        mManualImageRotation = resources.getBoolean(R.bool.enable_manual_image_rotation);
64135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren    }
65135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren
66135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren    /** Get angle defined by first two touches, in degrees */
67135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren    private float getAngle(View target, MotionEvent ev) {
68135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren        float alpha = 0f;
69135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren        int a = ev.findPointerIndex(mA);
70135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren        int b = ev.findPointerIndex(mB);
71135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren        if (a >=0 && b >=0) {
72135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren            alpha = (float) (Math.atan2(pts[2*a + 1] - pts[2*b + 1],
73135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren                                        pts[2*a] - pts[2*b]) *
74135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren                             180f / Math.PI);
75135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren        }
76135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren        return alpha;
77135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren    }
78135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren
79135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren    private void resetTouch(View target) {
80135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren        mInitialTouchX = -1;
81135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren        mInitialTouchY = -1;
82135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren        mInitialTouchA = 0f;
83135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren        mInitialTargetX = (float) target.getX();
84135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren        mInitialTargetY = (float) target.getY();
85135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren        mInitialTargetA = (float) target.getRotation();
86135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren    }
87135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren
88135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren    public void onFling(View target, float dX, float dY) {
89135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren        if (!mEnableFling) {
90135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren            return;
91135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren        }
92f61019ceb816fed9e5035c3d9b8451f6e4ee1da9Chris Wren        log("fling " + dX + ", " + dY);
93135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren
94135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren        // convert to pixel per frame
95135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren        dX /= 60f;
96135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren        dY /= 60f;
97135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren
98135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren        // starting position compionents in global corrdinate frame
99135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren        final float x0 = pts[0];
100135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren        final float y0 = pts[1];
101135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren
102135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren        // velocity
103135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren        final float v = (float) Math.hypot(dX, dY);
104135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren
105135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren        if (v == 0f) {
106135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren            return;
107135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren        }
108135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren
109135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren        // number of steps to come to a stop
110135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren        final float n = (float) Math.max(1.0, (- Math.log(v) / Math.log(mBeta)));
111135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren        // distance travelled before stopping
112135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren        final float s = (float) Math.max(0.0, (v * (1f - Math.pow(mBeta, n)) / (1f - mBeta)));
113135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren
114135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren        // ending posiiton after stopping
115135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren        final float x1 = x0 + s * dX / v;
116135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren        final float y1 = y0 + s * dY / v;
117135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren
1181dc94b55d59f5c4dbf86788d0c32b7ac4449909aChris Wren        mTable.fling(target, x1 - x0, y1 - y0, (int) (1000f * n / 60f), false);
119135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren    }
120135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren
121135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren    @Override
122135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren    public boolean onTouch(View target, MotionEvent ev) {
123135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren        final int action = ev.getActionMasked();
124135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren
125135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren        // compute raw coordinates
126135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren        for(int i = 0; i < 10 && i < ev.getPointerCount(); i++) {
127135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren            pts[i*2] = ev.getX(i);
128135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren            pts[i*2 + 1] = ev.getY(i);
129135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren        }
130135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren        target.getMatrix().mapPoints(pts);
131135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren
132135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren        switch (action) {
133135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren        case MotionEvent.ACTION_DOWN:
134eb70217554d14807d73cae033b4f756c9b80fe3bChris Wren            mTable.moveToTopOfPile(target);
135135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren            mInitialTouchTime = ev.getEventTime();
136135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren            mA = ev.getPointerId(ev.getActionIndex());
137135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren            resetTouch(target);
138135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren            break;
139135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren
140135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren        case MotionEvent.ACTION_POINTER_DOWN:
141135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren            if (mB == INVALID_POINTER) {
142135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren                mB = ev.getPointerId(ev.getActionIndex());
143135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren                mInitialTouchA = getAngle(target, ev);
144135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren            }
145135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren            break;
146135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren
147135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren        case MotionEvent.ACTION_POINTER_UP:
148135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren            if (mB == ev.getPointerId(ev.getActionIndex())) {
149135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren                mB = INVALID_POINTER;
150135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren                mInitialTargetA = (float) target.getRotation();
151135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren            }
152135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren            if (mA == ev.getPointerId(ev.getActionIndex())) {
153f61019ceb816fed9e5035c3d9b8451f6e4ee1da9Chris Wren                log("primary went up!");
154135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren                mA = mB;
155135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren                resetTouch(target);
156135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren                mB = INVALID_POINTER;
157135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren            }
158135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren            break;
159135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren
160135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren        case MotionEvent.ACTION_MOVE: {
161135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren                if (mA != INVALID_POINTER) {
162135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren                    int idx = ev.findPointerIndex(mA);
163135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren                    float x = pts[2 * idx];
164135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren                    float y = pts[2 * idx + 1];
165135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren                    if (mInitialTouchX == -1 && mInitialTouchY == -1) {
166135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren                        mInitialTouchX = x;
167135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren                        mInitialTouchY = y;
168135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren                    } else {
169135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren                        float dt = (float) (ev.getEventTime() - mLastEventTime) / 1000f;
170f61019ceb816fed9e5035c3d9b8451f6e4ee1da9Chris Wren                        float tmpDX = (x - mLastTouchX) / dt;
171f61019ceb816fed9e5035c3d9b8451f6e4ee1da9Chris Wren                        float tmpDY = (y - mLastTouchY) / dt;
172f61019ceb816fed9e5035c3d9b8451f6e4ee1da9Chris Wren                        if (dt > 0f && (Math.abs(tmpDX) > 5f || Math.abs(tmpDY) > 5f)) {
173f61019ceb816fed9e5035c3d9b8451f6e4ee1da9Chris Wren                            // work around odd bug with multi-finger flings
174f61019ceb816fed9e5035c3d9b8451f6e4ee1da9Chris Wren                            mDX = tmpDX;
175f61019ceb816fed9e5035c3d9b8451f6e4ee1da9Chris Wren                            mDY = tmpDY;
176f61019ceb816fed9e5035c3d9b8451f6e4ee1da9Chris Wren                        }
177f61019ceb816fed9e5035c3d9b8451f6e4ee1da9Chris Wren                        log("move " + mDX + ", " + mDY);
178f61019ceb816fed9e5035c3d9b8451f6e4ee1da9Chris Wren
179135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren                        mLastEventTime = ev.getEventTime();
180135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren                        mLastTouchX = x;
181135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren                        mLastTouchY = y;
182135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren                    }
183135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren
18488d80f4471c900628e2cb6eef23029b99af48e09Chris Wren                    if (!mTable.hasSelection()) {
18588d80f4471c900628e2cb6eef23029b99af48e09Chris Wren                        float rotation = target.getRotation();
186135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren                        if (mManualImageRotation && mB != INVALID_POINTER) {
187135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren                            float a = getAngle(target, ev);
18888d80f4471c900628e2cb6eef23029b99af48e09Chris Wren                            rotation = mInitialTargetA + a - mInitialTouchA;
189135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren                        }
19088d80f4471c900628e2cb6eef23029b99af48e09Chris Wren                        mTable.move(target,
19188d80f4471c900628e2cb6eef23029b99af48e09Chris Wren                                    mInitialTargetX + x - mInitialTouchX,
19288d80f4471c900628e2cb6eef23029b99af48e09Chris Wren                                    mInitialTargetY + y - mInitialTouchY,
19388d80f4471c900628e2cb6eef23029b99af48e09Chris Wren                                    rotation);
194135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren                    }
195135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren                }
196135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren            }
197135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren            break;
198135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren
199135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren        case MotionEvent.ACTION_UP: {
200135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren                if (mA != INVALID_POINTER) {
201135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren                    int idx = ev.findPointerIndex(mA);
202135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren                    float x0 = pts[2 * idx];
203135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren                    float y0 = pts[2 * idx + 1];
204135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren                    if (mInitialTouchX == -1 && mInitialTouchY == -1) {
205135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren                        mInitialTouchX = x0;
206135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren                        mInitialTouchY = y0;
207135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren                    }
208135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren                    double distance = Math.hypot(x0 - mInitialTouchX,
209135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren                                                 y0 - mInitialTouchY);
21088d80f4471c900628e2cb6eef23029b99af48e09Chris Wren                    if (mTable.hasSelection()) {
21188d80f4471c900628e2cb6eef23029b99af48e09Chris Wren                        if (distance < mTouchSlop) {
21288d80f4471c900628e2cb6eef23029b99af48e09Chris Wren                          mTable.clearSelection();
21388d80f4471c900628e2cb6eef23029b99af48e09Chris Wren                        } else {
21488d80f4471c900628e2cb6eef23029b99af48e09Chris Wren                          if ((x0 - mInitialTouchX) > 0f) {
21588d80f4471c900628e2cb6eef23029b99af48e09Chris Wren                            mTable.selectPrevious();
21688d80f4471c900628e2cb6eef23029b99af48e09Chris Wren                          } else {
21788d80f4471c900628e2cb6eef23029b99af48e09Chris Wren                            mTable.selectNext();
21888d80f4471c900628e2cb6eef23029b99af48e09Chris Wren                          }
21988d80f4471c900628e2cb6eef23029b99af48e09Chris Wren                        }
220135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren                    } else if ((ev.getEventTime() - mInitialTouchTime) < mTapTimeout &&
221135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren                               distance < mTouchSlop) {
222135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren                        // tap
223135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren                        mTable.setSelection(target);
224135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren                    } else {
225135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren                        onFling(target, mDX, mDY);
226135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren                    }
227135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren                    mA = INVALID_POINTER;
228135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren                    mB = INVALID_POINTER;
229135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren                }
230135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren            }
231135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren            break;
232135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren
233135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren        case MotionEvent.ACTION_CANCEL:
234f61019ceb816fed9e5035c3d9b8451f6e4ee1da9Chris Wren            log("action cancel!");
235135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren            break;
236135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren        }
237135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren
238135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren        return true;
239135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren    }
240135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren
241135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren    private static void log(String message) {
242135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren        if (DEBUG) {
243135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren            Log.i(TAG, message);
244135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren        }
245135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren    }
246135f525b62eb20c31c593e09f8bdb92215d538a4Chris Wren}
247