Blame client/Android/Studio/freeRDPCore/src/main/java/com/freerdp/freerdpcore/utils/GestureDetector.java

Packit 1fb8d4
/*
Packit 1fb8d4
 * Copyright (C) 2008 The Android Open Source Project
Packit 1fb8d4
 *
Packit 1fb8d4
 * Licensed under the Apache License, Version 2.0 (the "License");
Packit 1fb8d4
 * you may not use this file except in compliance with the License.
Packit 1fb8d4
 * You may obtain a copy of the License at
Packit 1fb8d4
 *
Packit 1fb8d4
 *      http://www.apache.org/licenses/LICENSE-2.0
Packit 1fb8d4
 *
Packit 1fb8d4
 * Unless required by applicable law or agreed to in writing, software
Packit 1fb8d4
 * distributed under the License is distributed on an "AS IS" BASIS,
Packit 1fb8d4
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Packit 1fb8d4
 * See the License for the specific language governing permissions and
Packit 1fb8d4
 * limitations under the License.
Packit Service 5a9772
 *
Packit 1fb8d4
 * Modified for aFreeRDP by Martin Fleisz (martin.fleisz@thincast.com)
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
package com.freerdp.freerdpcore.utils;
Packit 1fb8d4
Packit 1fb8d4
import android.content.Context;
Packit 1fb8d4
import android.os.Build;
Packit 1fb8d4
import android.os.Handler;
Packit 1fb8d4
import android.os.Message;
Packit 1fb8d4
import android.util.DisplayMetrics;
Packit 1fb8d4
import android.view.MotionEvent;
Packit 1fb8d4
import android.view.ViewConfiguration;
Packit 1fb8d4
Packit Service 5a9772
public class GestureDetector
Packit Service 5a9772
{
Packit Service 5a9772
Packit Service 5a9772
	private static final int TAP_TIMEOUT = 100;
Packit Service 5a9772
	private static final int DOUBLE_TAP_TIMEOUT = 200;
Packit Service 5a9772
	// Distance a touch can wander before we think the user is the first touch in a sequence of
Packit Service 5a9772
	// double tap
Packit Service 5a9772
	private static final int LARGE_TOUCH_SLOP = 18;
Packit Service 5a9772
	// Distance between the first touch and second touch to still be considered a double tap
Packit Service 5a9772
	private static final int DOUBLE_TAP_SLOP = 100;
Packit Service 5a9772
	// constants for Message.what used by GestureHandler below
Packit Service 5a9772
	private static final int SHOW_PRESS = 1;
Packit Service 5a9772
	private static final int LONG_PRESS = 2;
Packit Service 5a9772
	private static final int TAP = 3;
Packit Service 5a9772
	private final Handler mHandler;
Packit Service 5a9772
	private final OnGestureListener mListener;
Packit Service 5a9772
	private int mTouchSlopSquare;
Packit Service 5a9772
	private int mLargeTouchSlopSquare;
Packit Service 5a9772
	private int mDoubleTapSlopSquare;
Packit Service 5a9772
	private int mLongpressTimeout = 100;
Packit Service 5a9772
	private OnDoubleTapListener mDoubleTapListener;
Packit Service 5a9772
	private boolean mStillDown;
Packit Service 5a9772
	private boolean mInLongPress;
Packit Service 5a9772
	private boolean mAlwaysInTapRegion;
Packit Service 5a9772
	private boolean mAlwaysInBiggerTapRegion;
Packit Service 5a9772
	private MotionEvent mCurrentDownEvent;
Packit Service 5a9772
	private MotionEvent mPreviousUpEvent;
Packit Service 5a9772
	/**
Packit Service 5a9772
	 * True when the user is still touching for the second tap (down, move, and
Packit Service 5a9772
	 * up events). Can only be true if there is a double tap listener attached.
Packit Service 5a9772
	 */
Packit Service 5a9772
	private boolean mIsDoubleTapping;
Packit Service 5a9772
	private float mLastMotionY;
Packit Service 5a9772
	private float mLastMotionX;
Packit Service 5a9772
	private boolean mIsLongpressEnabled;
Packit Service 5a9772
	/**
Packit Service 5a9772
	 * True if we are at a target API level of >= Froyo or the developer can
Packit Service 5a9772
	 * explicitly set it. If true, input events with > 1 pointer will be ignored
Packit Service 5a9772
	 * so we can work side by side with multitouch gesture detectors.
Packit Service 5a9772
	 */
Packit Service 5a9772
	private boolean mIgnoreMultitouch;
Packit Service 5a9772
	/**
Packit Service 5a9772
	 * Creates a GestureDetector with the supplied listener.
Packit Service 5a9772
	 * You may only use this constructor from a UI thread (this is the usual situation).
Packit Service 5a9772
	 *
Packit Service 5a9772
	 * @param context  the application's context
Packit Service 5a9772
	 * @param listener the listener invoked for all the callbacks, this must
Packit Service 5a9772
	 *                 not be null.
Packit Service 5a9772
	 * @throws NullPointerException if {@code listener} is null.
Packit Service 5a9772
	 * @see android.os.Handler#Handler()
Packit Service 5a9772
	 */
Packit Service 5a9772
	public GestureDetector(Context context, OnGestureListener listener)
Packit Service 5a9772
	{
Packit Service 5a9772
		this(context, listener, null);
Packit Service 5a9772
	}
Packit Service 5a9772
Packit Service 5a9772
	/**
Packit Service 5a9772
	 * Creates a GestureDetector with the supplied listener.
Packit Service 5a9772
	 * You may only use this constructor from a UI thread (this is the usual situation).
Packit Service 5a9772
	 *
Packit Service 5a9772
	 * @param context  the application's context
Packit Service 5a9772
	 * @param listener the listener invoked for all the callbacks, this must
Packit Service 5a9772
	 *                 not be null.
Packit Service 5a9772
	 * @param handler  the handler to use
Packit Service 5a9772
	 * @throws NullPointerException if {@code listener} is null.
Packit Service 5a9772
	 * @see android.os.Handler#Handler()
Packit Service 5a9772
	 */
Packit Service 5a9772
	public GestureDetector(Context context, OnGestureListener listener, Handler handler)
Packit Service 5a9772
	{
Packit Service 5a9772
		this(context, listener, handler,
Packit Service 5a9772
		     context != null &&
Packit Service 5a9772
		         context.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.FROYO);
Packit Service 5a9772
	}
Packit Service 5a9772
Packit Service 5a9772
	/**
Packit Service 5a9772
	 * Creates a GestureDetector with the supplied listener.
Packit Service 5a9772
	 * You may only use this constructor from a UI thread (this is the usual situation).
Packit Service 5a9772
	 *
Packit Service 5a9772
	 * @param context          the application's context
Packit Service 5a9772
	 * @param listener         the listener invoked for all the callbacks, this must
Packit Service 5a9772
	 *                         not be null.
Packit Service 5a9772
	 * @param handler          the handler to use
Packit Service 5a9772
	 * @param ignoreMultitouch whether events involving more than one pointer should
Packit Service 5a9772
	 *                         be ignored.
Packit Service 5a9772
	 * @throws NullPointerException if {@code listener} is null.
Packit Service 5a9772
	 * @see android.os.Handler#Handler()
Packit Service 5a9772
	 */
Packit Service 5a9772
	public GestureDetector(Context context, OnGestureListener listener, Handler handler,
Packit Service 5a9772
	                       boolean ignoreMultitouch)
Packit Service 5a9772
	{
Packit Service 5a9772
		if (handler != null)
Packit Service 5a9772
		{
Packit Service 5a9772
			mHandler = new GestureHandler(handler);
Packit Service 5a9772
		}
Packit Service 5a9772
		else
Packit Service 5a9772
		{
Packit Service 5a9772
			mHandler = new GestureHandler();
Packit Service 5a9772
		}
Packit Service 5a9772
		mListener = listener;
Packit Service 5a9772
		if (listener instanceof OnDoubleTapListener)
Packit Service 5a9772
		{
Packit Service 5a9772
			setOnDoubleTapListener((OnDoubleTapListener)listener);
Packit Service 5a9772
		}
Packit Service 5a9772
		init(context, ignoreMultitouch);
Packit Service 5a9772
	}
Packit Service 5a9772
Packit Service 5a9772
	private void init(Context context, boolean ignoreMultitouch)
Packit Service 5a9772
	{
Packit Service 5a9772
		if (mListener == null)
Packit Service 5a9772
		{
Packit Service 5a9772
			throw new NullPointerException("OnGestureListener must not be null");
Packit Service 5a9772
		}
Packit Service 5a9772
		mIsLongpressEnabled = true;
Packit Service 5a9772
		mIgnoreMultitouch = ignoreMultitouch;
Packit Service 5a9772
Packit Service 5a9772
		// Fallback to support pre-donuts releases
Packit Service 5a9772
		int touchSlop, largeTouchSlop, doubleTapSlop;
Packit Service 5a9772
		if (context == null)
Packit Service 5a9772
		{
Packit Service 5a9772
			// noinspection deprecation
Packit Service 5a9772
			touchSlop = ViewConfiguration.getTouchSlop();
Packit Service 5a9772
			largeTouchSlop = touchSlop + 2;
Packit Service 5a9772
			doubleTapSlop = DOUBLE_TAP_SLOP;
Packit Service 5a9772
		}
Packit Service 5a9772
		else
Packit Service 5a9772
		{
Packit Service 5a9772
			final DisplayMetrics metrics = context.getResources().getDisplayMetrics();
Packit Service 5a9772
			final float density = metrics.density;
Packit Service 5a9772
			final ViewConfiguration configuration = ViewConfiguration.get(context);
Packit Service 5a9772
			touchSlop = configuration.getScaledTouchSlop();
Packit Service 5a9772
			largeTouchSlop = (int)(density * LARGE_TOUCH_SLOP + 0.5f);
Packit Service 5a9772
			doubleTapSlop = configuration.getScaledDoubleTapSlop();
Packit Service 5a9772
		}
Packit Service 5a9772
		mTouchSlopSquare = touchSlop * touchSlop;
Packit Service 5a9772
		mLargeTouchSlopSquare = largeTouchSlop * largeTouchSlop;
Packit Service 5a9772
		mDoubleTapSlopSquare = doubleTapSlop * doubleTapSlop;
Packit Service 5a9772
	}
Packit Service 5a9772
Packit Service 5a9772
	/**
Packit Service 5a9772
	 * Sets the listener which will be called for double-tap and related
Packit Service 5a9772
	 * gestures.
Packit Service 5a9772
	 *
Packit Service 5a9772
	 * @param onDoubleTapListener the listener invoked for all the callbacks, or
Packit Service 5a9772
	 *                            null to stop listening for double-tap gestures.
Packit Service 5a9772
	 */
Packit Service 5a9772
	public void setOnDoubleTapListener(OnDoubleTapListener onDoubleTapListener)
Packit Service 5a9772
	{
Packit Service 5a9772
		mDoubleTapListener = onDoubleTapListener;
Packit Service 5a9772
	}
Packit Service 5a9772
Packit Service 5a9772
	/**
Packit Service 5a9772
	 * Set whether longpress is enabled, if this is enabled when a user
Packit Service 5a9772
	 * presses and holds down you get a longpress event and nothing further.
Packit Service 5a9772
	 * If it's disabled the user can press and hold down and then later
Packit Service 5a9772
	 * moved their finger and you will get scroll events. By default
Packit Service 5a9772
	 * longpress is enabled.
Packit Service 5a9772
	 *
Packit Service 5a9772
	 * @param isLongpressEnabled whether longpress should be enabled.
Packit Service 5a9772
	 */
Packit Service 5a9772
	public void setIsLongpressEnabled(boolean isLongpressEnabled)
Packit Service 5a9772
	{
Packit Service 5a9772
		mIsLongpressEnabled = isLongpressEnabled;
Packit Service 5a9772
	}
Packit Service 5a9772
Packit Service 5a9772
	/**
Packit Service 5a9772
	 * @return true if longpress is enabled, else false.
Packit Service 5a9772
	 */
Packit Service 5a9772
	public boolean isLongpressEnabled()
Packit Service 5a9772
	{
Packit Service 5a9772
		return mIsLongpressEnabled;
Packit Service 5a9772
	}
Packit Service 5a9772
Packit Service 5a9772
	public void setLongPressTimeout(int timeout)
Packit Service 5a9772
	{
Packit Service 5a9772
		mLongpressTimeout = timeout;
Packit Service 5a9772
	}
Packit Service 5a9772
Packit Service 5a9772
	/**
Packit Service 5a9772
	 * Analyzes the given motion event and if applicable triggers the
Packit Service 5a9772
	 * appropriate callbacks on the {@link OnGestureListener} supplied.
Packit Service 5a9772
	 *
Packit Service 5a9772
	 * @param ev The current motion event.
Packit Service 5a9772
	 * @return true if the {@link OnGestureListener} consumed the event,
Packit Service 5a9772
	 * else false.
Packit Service 5a9772
	 */
Packit Service 5a9772
	public boolean onTouchEvent(MotionEvent ev)
Packit Service 5a9772
	{
Packit Service 5a9772
		final int action = ev.getAction();
Packit Service 5a9772
		final float y = ev.getY();
Packit Service 5a9772
		final float x = ev.getX();
Packit Service 5a9772
Packit Service 5a9772
		boolean handled = false;
Packit Service 5a9772
Packit Service 5a9772
		switch (action & MotionEvent.ACTION_MASK)
Packit Service 5a9772
		{
Packit Service 5a9772
			case MotionEvent.ACTION_POINTER_DOWN:
Packit Service 5a9772
				if (mIgnoreMultitouch)
Packit Service 5a9772
				{
Packit Service 5a9772
					// Multitouch event - abort.
Packit Service 5a9772
					cancel();
Packit Service 5a9772
				}
Packit Service 5a9772
				break;
Packit Service 5a9772
Packit Service 5a9772
			case MotionEvent.ACTION_POINTER_UP:
Packit Service 5a9772
				// Ending a multitouch gesture and going back to 1 finger
Packit Service 5a9772
				if (mIgnoreMultitouch && ev.getPointerCount() == 2)
Packit Service 5a9772
				{
Packit Service 5a9772
					int index = (((action & MotionEvent.ACTION_POINTER_INDEX_MASK) >>
Packit Service 5a9772
					              MotionEvent.ACTION_POINTER_INDEX_SHIFT) == 0)
Packit Service 5a9772
					                ? 1
Packit Service 5a9772
					                : 0;
Packit Service 5a9772
					mLastMotionX = ev.getX(index);
Packit Service 5a9772
					mLastMotionY = ev.getY(index);
Packit Service 5a9772
				}
Packit Service 5a9772
				break;
Packit Service 5a9772
Packit Service 5a9772
			case MotionEvent.ACTION_DOWN:
Packit Service 5a9772
				if (mDoubleTapListener != null)
Packit Service 5a9772
				{
Packit Service 5a9772
					boolean hadTapMessage = mHandler.hasMessages(TAP);
Packit Service 5a9772
					if (hadTapMessage)
Packit Service 5a9772
						mHandler.removeMessages(TAP);
Packit Service 5a9772
					if ((mCurrentDownEvent != null) && (mPreviousUpEvent != null) &&
Packit Service 5a9772
					    hadTapMessage &&
Packit Service 5a9772
					    isConsideredDoubleTap(mCurrentDownEvent, mPreviousUpEvent, ev))
Packit Service 5a9772
					{
Packit Service 5a9772
						// This is a second tap
Packit Service 5a9772
						mIsDoubleTapping = true;
Packit Service 5a9772
						// Give a callback with the first tap of the double-tap
Packit Service 5a9772
						handled |= mDoubleTapListener.onDoubleTap(mCurrentDownEvent);
Packit Service 5a9772
						// Give a callback with down event of the double-tap
Packit Service 5a9772
						handled |= mDoubleTapListener.onDoubleTapEvent(ev);
Packit Service 5a9772
					}
Packit Service 5a9772
					else
Packit Service 5a9772
					{
Packit Service 5a9772
						// This is a first tap
Packit Service 5a9772
						mHandler.sendEmptyMessageDelayed(TAP, DOUBLE_TAP_TIMEOUT);
Packit Service 5a9772
					}
Packit Service 5a9772
				}
Packit Service 5a9772
Packit Service 5a9772
				mLastMotionX = x;
Packit Service 5a9772
				mLastMotionY = y;
Packit Service 5a9772
				if (mCurrentDownEvent != null)
Packit Service 5a9772
				{
Packit Service 5a9772
					mCurrentDownEvent.recycle();
Packit Service 5a9772
				}
Packit Service 5a9772
				mCurrentDownEvent = MotionEvent.obtain(ev);
Packit Service 5a9772
				mAlwaysInTapRegion = true;
Packit Service 5a9772
				mAlwaysInBiggerTapRegion = true;
Packit Service 5a9772
				mStillDown = true;
Packit Service 5a9772
				mInLongPress = false;
Packit Service 5a9772
Packit Service 5a9772
				if (mIsLongpressEnabled)
Packit Service 5a9772
				{
Packit Service 5a9772
					mHandler.removeMessages(LONG_PRESS);
Packit Service 5a9772
					mHandler.sendEmptyMessageAtTime(LONG_PRESS, mCurrentDownEvent.getDownTime() +
Packit Service 5a9772
					                                                TAP_TIMEOUT +
Packit Service 5a9772
					                                                mLongpressTimeout);
Packit Service 5a9772
				}
Packit Service 5a9772
				mHandler.sendEmptyMessageAtTime(SHOW_PRESS,
Packit Service 5a9772
				                                mCurrentDownEvent.getDownTime() + TAP_TIMEOUT);
Packit Service 5a9772
				handled |= mListener.onDown(ev);
Packit Service 5a9772
				break;
Packit Service 5a9772
Packit Service 5a9772
			case MotionEvent.ACTION_MOVE:
Packit Service 5a9772
				if (mIgnoreMultitouch && ev.getPointerCount() > 1)
Packit Service 5a9772
				{
Packit Service 5a9772
					break;
Packit Service 5a9772
				}
Packit Service 5a9772
				final float scrollX = mLastMotionX - x;
Packit Service 5a9772
				final float scrollY = mLastMotionY - y;
Packit Service 5a9772
				if (mIsDoubleTapping)
Packit Service 5a9772
				{
Packit Service 5a9772
					// Give the move events of the double-tap
Packit Service 5a9772
					handled |= mDoubleTapListener.onDoubleTapEvent(ev);
Packit Service 5a9772
				}
Packit Service 5a9772
				else if (mAlwaysInTapRegion)
Packit Service 5a9772
				{
Packit Service 5a9772
					final int deltaX = (int)(x - mCurrentDownEvent.getX());
Packit Service 5a9772
					final int deltaY = (int)(y - mCurrentDownEvent.getY());
Packit Service 5a9772
					int distance = (deltaX * deltaX) + (deltaY * deltaY);
Packit Service 5a9772
					if (distance > mTouchSlopSquare)
Packit Service 5a9772
					{
Packit Service 5a9772
						mLastMotionX = x;
Packit Service 5a9772
						mLastMotionY = y;
Packit Service 5a9772
						mAlwaysInTapRegion = false;
Packit Service 5a9772
						mHandler.removeMessages(TAP);
Packit Service 5a9772
						mHandler.removeMessages(SHOW_PRESS);
Packit Service 5a9772
						mHandler.removeMessages(LONG_PRESS);
Packit Service 5a9772
					}
Packit Service 5a9772
					if (distance > mLargeTouchSlopSquare)
Packit Service 5a9772
					{
Packit Service 5a9772
						mAlwaysInBiggerTapRegion = false;
Packit Service 5a9772
					}
Packit Service 5a9772
					handled = mListener.onScroll(mCurrentDownEvent, ev, scrollX, scrollY);
Packit Service 5a9772
				}
Packit Service 5a9772
				else if ((Math.abs(scrollX) >= 1) || (Math.abs(scrollY) >= 1))
Packit Service 5a9772
				{
Packit Service 5a9772
					handled = mListener.onScroll(mCurrentDownEvent, ev, scrollX, scrollY);
Packit Service 5a9772
					mLastMotionX = x;
Packit Service 5a9772
					mLastMotionY = y;
Packit Service 5a9772
				}
Packit Service 5a9772
				break;
Packit Service 5a9772
Packit Service 5a9772
			case MotionEvent.ACTION_UP:
Packit Service 5a9772
				mStillDown = false;
Packit Service 5a9772
				MotionEvent currentUpEvent = MotionEvent.obtain(ev);
Packit Service 5a9772
				if (mIsDoubleTapping)
Packit Service 5a9772
				{
Packit Service 5a9772
					// Finally, give the up event of the double-tap
Packit Service 5a9772
					handled |= mDoubleTapListener.onDoubleTapEvent(ev);
Packit Service 5a9772
				}
Packit Service 5a9772
				else if (mInLongPress)
Packit Service 5a9772
				{
Packit Service 5a9772
					mHandler.removeMessages(TAP);
Packit Service 5a9772
					mListener.onLongPressUp(ev);
Packit Service 5a9772
					mInLongPress = false;
Packit Service 5a9772
				}
Packit Service 5a9772
				else if (mAlwaysInTapRegion)
Packit Service 5a9772
				{
Packit Service 5a9772
					handled = mListener.onSingleTapUp(mCurrentDownEvent);
Packit Service 5a9772
				}
Packit Service 5a9772
				else
Packit Service 5a9772
				{
Packit Service 5a9772
					// A fling must travel the minimum tap distance
Packit Service 5a9772
				}
Packit Service 5a9772
				if (mPreviousUpEvent != null)
Packit Service 5a9772
				{
Packit Service 5a9772
					mPreviousUpEvent.recycle();
Packit Service 5a9772
				}
Packit Service 5a9772
				// Hold the event we obtained above - listeners may have changed the original.
Packit Service 5a9772
				mPreviousUpEvent = currentUpEvent;
Packit Service 5a9772
				mIsDoubleTapping = false;
Packit Service 5a9772
				mHandler.removeMessages(SHOW_PRESS);
Packit Service 5a9772
				mHandler.removeMessages(LONG_PRESS);
Packit Service 5a9772
				handled |= mListener.onUp(ev);
Packit Service 5a9772
				break;
Packit Service 5a9772
			case MotionEvent.ACTION_CANCEL:
Packit Service 5a9772
				cancel();
Packit Service 5a9772
				break;
Packit Service 5a9772
		}
Packit Service 5a9772
		return handled;
Packit Service 5a9772
	}
Packit Service 5a9772
Packit Service 5a9772
	private void cancel()
Packit Service 5a9772
	{
Packit Service 5a9772
		mHandler.removeMessages(SHOW_PRESS);
Packit Service 5a9772
		mHandler.removeMessages(LONG_PRESS);
Packit Service 5a9772
		mHandler.removeMessages(TAP);
Packit Service 5a9772
		mAlwaysInTapRegion = false; // ensures that we won't receive an OnSingleTap notification
Packit Service 5a9772
		                            // when a 2-Finger tap is performed
Packit Service 5a9772
		mIsDoubleTapping = false;
Packit Service 5a9772
		mStillDown = false;
Packit Service 5a9772
		if (mInLongPress)
Packit Service 5a9772
		{
Packit Service 5a9772
			mInLongPress = false;
Packit Service 5a9772
		}
Packit Service 5a9772
	}
Packit Service 5a9772
Packit Service 5a9772
	private boolean isConsideredDoubleTap(MotionEvent firstDown, MotionEvent firstUp,
Packit Service 5a9772
	                                      MotionEvent secondDown)
Packit Service 5a9772
	{
Packit Service 5a9772
		if (!mAlwaysInBiggerTapRegion)
Packit Service 5a9772
		{
Packit Service 5a9772
			return false;
Packit Service 5a9772
		}
Packit Service 5a9772
Packit Service 5a9772
		if (secondDown.getEventTime() - firstUp.getEventTime() > DOUBLE_TAP_TIMEOUT)
Packit Service 5a9772
		{
Packit Service 5a9772
			return false;
Packit Service 5a9772
		}
Packit Service 5a9772
Packit Service 5a9772
		int deltaX = (int)firstDown.getX() - (int)secondDown.getX();
Packit Service 5a9772
		int deltaY = (int)firstDown.getY() - (int)secondDown.getY();
Packit Service 5a9772
		return (deltaX * deltaX + deltaY * deltaY < mDoubleTapSlopSquare);
Packit Service 5a9772
	}
Packit Service 5a9772
Packit Service 5a9772
	private void dispatchLongPress()
Packit Service 5a9772
	{
Packit Service 5a9772
		mHandler.removeMessages(TAP);
Packit Service 5a9772
		mInLongPress = true;
Packit Service 5a9772
		mListener.onLongPress(mCurrentDownEvent);
Packit Service 5a9772
	}
Packit Service 5a9772
Packit Service 5a9772
	/**
Packit Service 5a9772
	 * The listener that is used to notify when gestures occur.
Packit Service 5a9772
	 * If you want to listen for all the different gestures then implement
Packit Service 5a9772
	 * this interface. If you only want to listen for a subset it might
Packit Service 5a9772
	 * be easier to extend {@link SimpleOnGestureListener}.
Packit Service 5a9772
	 */
Packit Service 5a9772
	public interface OnGestureListener {
Packit Service 5a9772
Packit Service 5a9772
		/**
Packit Service 5a9772
		 * Notified when a tap occurs with the down {@link MotionEvent}
Packit Service 5a9772
		 * that triggered it. This will be triggered immediately for
Packit Service 5a9772
		 * every down event. All other events should be preceded by this.
Packit Service 5a9772
		 *
Packit Service 5a9772
		 * @param e The down motion event.
Packit Service 5a9772
		 */
Packit Service 5a9772
		boolean onDown(MotionEvent e);
Packit Service 5a9772
Packit Service 5a9772
		/**
Packit Service 5a9772
		 * Notified when a tap finishes with the up {@link MotionEvent}
Packit Service 5a9772
		 * that triggered it. This will be triggered immediately for
Packit Service 5a9772
		 * every up event. All other events should be preceded by this.
Packit Service 5a9772
		 *
Packit Service 5a9772
		 * @param e The up motion event.
Packit Service 5a9772
		 */
Packit Service 5a9772
		boolean onUp(MotionEvent e);
Packit Service 5a9772
Packit Service 5a9772
		/**
Packit Service 5a9772
		 * The user has performed a down {@link MotionEvent} and not performed
Packit Service 5a9772
		 * a move or up yet. This event is commonly used to provide visual
Packit Service 5a9772
		 * feedback to the user to let them know that their action has been
Packit Service 5a9772
		 * recognized i.e. highlight an element.
Packit Service 5a9772
		 *
Packit Service 5a9772
		 * @param e The down motion event
Packit Service 5a9772
		 */
Packit Service 5a9772
		void onShowPress(MotionEvent e);
Packit Service 5a9772
Packit Service 5a9772
		/**
Packit Service 5a9772
		 * Notified when a tap occurs with the up {@link MotionEvent}
Packit Service 5a9772
		 * that triggered it.
Packit Service 5a9772
		 *
Packit Service 5a9772
		 * @param e The up motion event that completed the first tap
Packit Service 5a9772
		 * @return true if the event is consumed, else false
Packit Service 5a9772
		 */
Packit Service 5a9772
		boolean onSingleTapUp(MotionEvent e);
Packit Service 5a9772
Packit Service 5a9772
		/**
Packit Service 5a9772
		 * Notified when a scroll occurs with the initial on down {@link MotionEvent} and the
Packit Service 5a9772
		 * current move {@link MotionEvent}. The distance in x and y is also supplied for
Packit Service 5a9772
		 * convenience.
Packit Service 5a9772
		 *
Packit Service 5a9772
		 * @param e1        The first down motion event that started the scrolling.
Packit Service 5a9772
		 * @param e2        The move motion event that triggered the current onScroll.
Packit Service 5a9772
		 * @param distanceX The distance along the X axis that has been scrolled since the last
Packit Service 5a9772
		 *                  call to onScroll. This is NOT the distance between {@code e1}
Packit Service 5a9772
		 *                  and {@code e2}.
Packit Service 5a9772
		 * @param distanceY The distance along the Y axis that has been scrolled since the last
Packit Service 5a9772
		 *                  call to onScroll. This is NOT the distance between {@code e1}
Packit Service 5a9772
		 *                  and {@code e2}.
Packit Service 5a9772
		 * @return true if the event is consumed, else false
Packit Service 5a9772
		 */
Packit Service 5a9772
		boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY);
Packit Service 5a9772
Packit Service 5a9772
		/**
Packit Service 5a9772
		 * Notified when a long press occurs with the initial on down {@link MotionEvent}
Packit Service 5a9772
		 * that trigged it.
Packit Service 5a9772
		 *
Packit Service 5a9772
		 * @param e The initial on down motion event that started the longpress.
Packit Service 5a9772
		 */
Packit Service 5a9772
		void onLongPress(MotionEvent e);
Packit Service 5a9772
Packit Service 5a9772
		/**
Packit Service 5a9772
		 * Notified when a long press ends with the final {@link MotionEvent}.
Packit Service 5a9772
		 *
Packit Service 5a9772
		 * @param e The up motion event that ended the longpress.
Packit Service 5a9772
		 */
Packit Service 5a9772
		void onLongPressUp(MotionEvent e);
Packit Service 5a9772
	}
Packit Service 5a9772
Packit Service 5a9772
	/**
Packit Service 5a9772
	 * The listener that is used to notify when a double-tap or a confirmed
Packit Service 5a9772
	 * single-tap occur.
Packit Service 5a9772
	 */
Packit Service 5a9772
	public interface OnDoubleTapListener {
Packit Service 5a9772
		/**
Packit Service 5a9772
		 * Notified when a single-tap occurs.
Packit Service 5a9772
		 * 

Packit Service 5a9772
		 * Unlike {@link OnGestureListener#onSingleTapUp(MotionEvent)}, this
Packit Service 5a9772
		 * will only be called after the detector is confident that the user's
Packit Service 5a9772
		 * first tap is not followed by a second tap leading to a double-tap
Packit Service 5a9772
		 * gesture.
Packit Service 5a9772
		 *
Packit Service 5a9772
		 * @param e The down motion event of the single-tap.
Packit Service 5a9772
		 * @return true if the event is consumed, else false
Packit Service 5a9772
		 */
Packit Service 5a9772
		boolean onSingleTapConfirmed(MotionEvent e);
Packit Service 5a9772
Packit Service 5a9772
		/**
Packit Service 5a9772
		 * Notified when a double-tap occurs.
Packit Service 5a9772
		 *
Packit Service 5a9772
		 * @param e The down motion event of the first tap of the double-tap.
Packit Service 5a9772
		 * @return true if the event is consumed, else false
Packit Service 5a9772
		 */
Packit Service 5a9772
		boolean onDoubleTap(MotionEvent e);
Packit Service 5a9772
Packit Service 5a9772
		/**
Packit Service 5a9772
		 * Notified when an event within a double-tap gesture occurs, including
Packit Service 5a9772
		 * the down, move, and up events.
Packit Service 5a9772
		 *
Packit Service 5a9772
		 * @param e The motion event that occurred during the double-tap gesture.
Packit Service 5a9772
		 * @return true if the event is consumed, else false
Packit Service 5a9772
		 */
Packit Service 5a9772
		boolean onDoubleTapEvent(MotionEvent e);
Packit Service 5a9772
	}
Packit Service 5a9772
Packit Service 5a9772
	/**
Packit Service 5a9772
	 * A convenience class to extend when you only want to listen for a subset
Packit Service 5a9772
	 * of all the gestures. This implements all methods in the
Packit Service 5a9772
	 * {@link OnGestureListener} and {@link OnDoubleTapListener} but does
Packit Service 5a9772
	 * nothing and return {@code false} for all applicable methods.
Packit Service 5a9772
	 */
Packit Service 5a9772
	public static class SimpleOnGestureListener implements OnGestureListener, OnDoubleTapListener
Packit Service 5a9772
	{
Packit Service 5a9772
		public boolean onSingleTapUp(MotionEvent e)
Packit Service 5a9772
		{
Packit Service 5a9772
			return false;
Packit Service 5a9772
		}
Packit Service 5a9772
Packit Service 5a9772
		public void onLongPress(MotionEvent e)
Packit Service 5a9772
		{
Packit Service 5a9772
		}
Packit Service 5a9772
Packit Service 5a9772
		public void onLongPressUp(MotionEvent e)
Packit Service 5a9772
		{
Packit Service 5a9772
		}
Packit Service 5a9772
Packit Service 5a9772
		public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY)
Packit Service 5a9772
		{
Packit Service 5a9772
			return false;
Packit Service 5a9772
		}
Packit Service 5a9772
Packit Service 5a9772
		public void onShowPress(MotionEvent e)
Packit Service 5a9772
		{
Packit Service 5a9772
		}
Packit Service 5a9772
Packit Service 5a9772
		public boolean onDown(MotionEvent e)
Packit Service 5a9772
		{
Packit Service 5a9772
			return false;
Packit Service 5a9772
		}
Packit Service 5a9772
Packit Service 5a9772
		public boolean onUp(MotionEvent e)
Packit Service 5a9772
		{
Packit Service 5a9772
			return false;
Packit Service 5a9772
		}
Packit Service 5a9772
Packit Service 5a9772
		public boolean onDoubleTap(MotionEvent e)
Packit Service 5a9772
		{
Packit Service 5a9772
			return false;
Packit Service 5a9772
		}
Packit Service 5a9772
Packit Service 5a9772
		public boolean onDoubleTapEvent(MotionEvent e)
Packit Service 5a9772
		{
Packit Service 5a9772
			return false;
Packit Service 5a9772
		}
Packit Service 5a9772
Packit Service 5a9772
		public boolean onSingleTapConfirmed(MotionEvent e)
Packit Service 5a9772
		{
Packit Service 5a9772
			return false;
Packit Service 5a9772
		}
Packit Service 5a9772
	}
Packit Service 5a9772
Packit Service 5a9772
	private class GestureHandler extends Handler
Packit Service 5a9772
	{
Packit Service 5a9772
		GestureHandler()
Packit Service 5a9772
		{
Packit Service 5a9772
			super();
Packit Service 5a9772
		}
Packit Service 5a9772
Packit Service 5a9772
		GestureHandler(Handler handler)
Packit Service 5a9772
		{
Packit Service 5a9772
			super(handler.getLooper());
Packit Service 5a9772
		}
Packit Service 5a9772
Packit Service 5a9772
		@Override public void handleMessage(Message msg)
Packit Service 5a9772
		{
Packit Service 5a9772
			switch (msg.what)
Packit Service 5a9772
			{
Packit Service 5a9772
				case SHOW_PRESS:
Packit Service 5a9772
					mListener.onShowPress(mCurrentDownEvent);
Packit Service 5a9772
					break;
Packit Service 5a9772
Packit Service 5a9772
				case LONG_PRESS:
Packit Service 5a9772
					dispatchLongPress();
Packit Service 5a9772
					break;
Packit Service 5a9772
Packit Service 5a9772
				case TAP:
Packit Service 5a9772
					// If the user's finger is still down, do not count it as a tap
Packit Service 5a9772
					if (mDoubleTapListener != null && !mStillDown)
Packit Service 5a9772
					{
Packit Service 5a9772
						mDoubleTapListener.onSingleTapConfirmed(mCurrentDownEvent);
Packit Service 5a9772
					}
Packit Service 5a9772
					break;
Packit Service 5a9772
Packit Service 5a9772
				default:
Packit Service 5a9772
					throw new RuntimeException("Unknown message " + msg); // never
Packit Service 5a9772
			}
Packit Service 5a9772
		}
Packit Service 5a9772
	}
Packit 1fb8d4
}