/*
* Flingbox - An OpenSource physics sandbox for Google's Android
* Copyright (C) 2009 Jon Ander Peñalba & Endika Gutiérrez
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package edu.eside.flingbox.input;
import android.content.Context;
import android.util.Log;
import android.view.MotionEvent;
import android.view.GestureDetector;
/**
* Custom gesture detection class
*
* Listener should implement {@link OnInputListener}.
*/
public class SceneGestureDetector extends GestureDetector {
public interface OnInputListener extends OnGestureListener {
/**
* Called when user stops scrolling
* @param ev
* @return
*/
public boolean onUp(MotionEvent ev);
public boolean onPinch(MotionEvent ev1, MotionEvent ev2, float scale,
float dX, float dY);
}
/** Handler of processed gesture events */
private final OnInputListener mListener;
private MotionEvent mLastMotionEvent;
/**
* @param context
* @param listener
*/
public SceneGestureDetector(Context context, OnInputListener listener) {
super(context, listener);
mListener = listener;
}
/**
* Should be called on touch event
*/
public boolean onTouchEvent(MotionEvent ev) {
boolean handled = false;
// Check for an Up event
if (ev.getAction() == MotionEvent.ACTION_UP)
handled |= mListener.onUp(ev);
// Check for multitouch event
if (ev.getPointerCount() > 1) {
handled |= this.onMultitouchEvent(ev);
// Cancel last event
super.onTouchEvent(MotionEvent.obtain(0, 0, MotionEvent.ACTION_CANCEL, 0f, 0f, 0));
}
mLastMotionEvent = ev;
return handled ? true : super.onTouchEvent(ev);
}
public boolean onMultitouchEvent(MotionEvent ev) {
if (ev.getPointerCount() < 2)
return false;
switch (ev.getAction()) {
case MotionEvent.ACTION_MOVE:
if (mLastMotionEvent == null || mLastMotionEvent.getPointerCount() < 2)
break;
final float lastX0 = ev.getHistoricalX(0, 1), lastX1 = ev.getHistoricalX(1, 1),
lastY0 = ev.getHistoricalY(0, 1), lastY1 = ev.getHistoricalY(1, 1);
final float x0 = ev.getX(0), x1 = ev.getX(1),
y0 = ev.getY(0), y1 = ev.getY(1);
if (lastX0 == 0 || lastX1 == 0 || lastY0 == 0 || lastY1 == 0
|| x0 == 0 || x1 == 0 || y0 == 0 || y1 == 0)
return false;
final float dx = -((x0 - lastX0) + (x1 - lastX1)) / 2;
final float dy = -((y0 - lastY0) + (y1 - lastY1)) / 2;
final float scale = (float) Math.sqrt(
((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0))
/ ((lastX1 - lastX0) * (lastX1 - lastX0) + (lastY1 - lastY0) * (lastY1 - lastY0))
);
if ((scale < 1.25 && scale > 0.8)
&& (dx > -40 && dx < 40 && dy > -40 && dy < 40))
mListener.onPinch(mLastMotionEvent, ev, scale, dx, dy);
return true;
}
return false;
}
}