package com.wistron.WiViewer;
import Utilities.CSStaticData;
import android.R.integer;
import android.content.Context;
import android.graphics.Matrix;
import android.os.Build;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
public abstract class VersionedGestureDetector {
private static final String TAG = "VersionedGestureDetector";
OnGestureListener mListener;
boolean canRotate=false;
boolean isRotatable=false;
float rotateAngle=0;
float preAngle=0;
// Matrix matrix_Rotate=new Matrix();
/**
* 实例化多点识别器
*/
public static VersionedGestureDetector newInstance(Context context,
OnGestureListener listener) {
final int sdkVersion = Integer.parseInt(Build.VERSION.SDK);
VersionedGestureDetector detector = null;
if (sdkVersion < Build.VERSION_CODES.ECLAIR) {
detector = new CupcakeDetector();
} else if (sdkVersion < Build.VERSION_CODES.FROYO) {
detector = new EclairDetector();
} else {
detector = new FroyoDetector(context);
}
Log.d(TAG, "Created new " + detector.getClass());
detector.mListener = listener;
return detector;
}
public abstract boolean onTouchEvent(MotionEvent ev);
/**
* 手势监听器,监听缩放和拖動
*/
public interface OnGestureListener {
public void onDrag(float dx, float dy);
public void onScale(float scaleFactor,float x,float y,ScaleGestureDetector de);
public void onRotate(float angle,float totalangle,boolean isEnd);
}
public float getRestAngle(float srcAngle)
{
float angle=0;
while(srcAngle>=360)
{
srcAngle-=360;
}
while(srcAngle<=-360)
{
srcAngle+=360;
}
if(srcAngle>0)
{
if(srcAngle<45)
{
angle=-srcAngle;
}
else if(srcAngle<90)
{
angle=90-srcAngle;
}
else if( srcAngle<135)
{
angle=(90-srcAngle);
}
else if (srcAngle<180)
{
angle=180-srcAngle;
}
else if (srcAngle <225)
{
angle=(180-srcAngle);
}
else if (srcAngle<270)
{
angle=270-srcAngle;
}
else if (srcAngle<315)
{
angle=(270-srcAngle);
}
else if( srcAngle<360)
{
angle=360-srcAngle;
}
}
else
{
if(srcAngle>-45)
{
angle=-srcAngle;
}
else if(srcAngle>-90)
{
angle=-(90+srcAngle);
}
else if( srcAngle>-135)
{
angle=(-90-srcAngle);
}
else if (srcAngle>-180)
{
angle=-180-srcAngle;
}
else if (srcAngle >-225)
{
angle=-180-srcAngle;
}
else if (srcAngle>-270)
{
angle=-270-srcAngle;
}
else if (srcAngle>-315)
{
angle=-270-srcAngle;
}
else if( srcAngle>-360)
{
angle=-360-srcAngle;
}
}
return angle;
}
public float getRotateAngle(float x,float y,float x_,float y_)
{
if(x_==x)
{
if(y_>y)
return 90;
else {
return 270;
}
}
if( y==y_)
{
if(x_<x)
return 180;
else {
return 0;
}
}
float angle=(float)Math.toDegrees(Math.atan((y_-y)/(x_-x)));
if( x_<x)
{
angle+=180;
}
else {
if(y_<y)
{
angle+=360;
}
}
//Log.e(TAG, "angle="+angle);
return angle ;
}
private static class CupcakeDetector extends VersionedGestureDetector {
float mLastTouchX;
float mLastTouchY;
float getActiveX(MotionEvent ev) {
return ev.getX();
}
float getActiveY(MotionEvent ev) {
return ev.getY();
}
boolean shouldDrag() {
return true;
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN: {
mLastTouchX = getActiveX(ev);
mLastTouchY = getActiveY(ev);
break;
}
case MotionEvent.ACTION_MOVE: {
final float x = getActiveX(ev);
final float y = getActiveY(ev);
if (shouldDrag()) {
mListener.onDrag(x - mLastTouchX, y - mLastTouchY);
}
mLastTouchX = x;
mLastTouchY = y;
break;
}
}
return true;
}
}
private static class EclairDetector extends CupcakeDetector {
private static final int INVALID_POINTER_ID = -1;
private int mActivePointerId = INVALID_POINTER_ID;
private int mActivePointerIndex = 0;
@Override
float getActiveX(MotionEvent ev) {
float mf=0;
try
{
mf= ev.getX(mActivePointerIndex);
} catch (Exception e)
{
// TODO: handle exception
e.printStackTrace();
}
return mf;
}
@Override
float getActiveY(MotionEvent ev) {
float mf=0;
try
{
mf= ev.getY(mActivePointerIndex);;
} catch (Exception e)
{
// TODO: handle exception
e.printStackTrace();
}
return mf;
}
@Override
public boolean onTouchEvent(MotionEvent ev)
{
final int action = ev.getAction();
switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
mActivePointerId = ev.getPointerId(0);
break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
mActivePointerId = INVALID_POINTER_ID;
break;
case MotionEvent.ACTION_POINTER_UP:
final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK)
>> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
final int pointerId = ev.getPointerId(pointerIndex);
if (pointerId == mActivePointerId) {
// This was our active pointer going up. Choose a new
// active pointer and adjust accordingly.
final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
mActivePointerId = ev.getPointerId(newPointerIndex);
mLastTouchX = ev.getX(newPointerIndex);
mLastTouchY = ev.getY(newPointerIndex);
}
break;
}
mActivePointerIndex = ev.findPointerIndex(mActivePointerId);
return super.onTouchEvent(ev);
}
}
private static class FroyoDetector extends EclairDetector {
private ScaleGestureDetector mDetector;
public FroyoDetector(Context context) {
if(CSStaticData.DEBUG)
Log.e(TAG, "FroyoDetector");
mDetector = new ScaleGestureDetector(context,
new ScaleGestureDetector.SimpleOnScaleGestureListener()
{
@Override
public boolean onScale(ScaleGestureDetector detector) {
mListener.onScale(detector.getScaleFactor(),detector.getFocusX(),detector.getFocusY(),detector);
return true;
}
});
}
@Override
boolean shouldDrag() {
return !mDetector.isInProgress();
// return true;
}
@Override
public boolean onTouchEvent(MotionEvent ev)
{
switch (ev.getAction())
{
case MotionEvent.ACTION_MOVE:
if(canRotate)
{
float curangle=getRotateAngle(ev.getX(0),ev.getY(0), ev.getX(1), ev.getY(1));
float temp= curangle-preAngle;
float tempfortotal=temp;
if(temp>300)
{
tempfortotal=temp-360;
}
else if( temp<-300)
{
tempfortotal=360+temp;
}
rotateAngle+=tempfortotal;
// Log.e(TAG, "rotateAngle="+rotateAngle);
if(!isRotatable)
{
int angleTrigger=Math.abs((int)rotateAngle)%90;
if(angleTrigger>30)
{
//Log.e(TAG, "isRotatable");
isRotatable=true;
rotateAngle=tempfortotal;
}
}
if(isRotatable)
{
mListener.onRotate(temp,rotateAngle,false);
}
preAngle=curangle;
}
break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
//Log.e(TAG, "ACTION_UP");
canRotate=false;
if(isRotatable)
{
isRotatable=false;
float resetAngle=getRestAngle(rotateAngle);
rotateAngle=rotateAngle+resetAngle;
mListener.onRotate(resetAngle,rotateAngle,true);
// Log.e(TAG, "resetAngle"+resetAngle);
// Log.e(TAG, "rotateAngle"+rotateAngle);
}
rotateAngle=0;
break;
case MotionEvent.ACTION_POINTER_UP:
case MotionEvent.ACTION_POINTER_2_UP:
// Log.e(TAG, "ACTION_POINTER_UP");
canRotate=false;
// isRotatable=false;
//rotateAngle=0;
break;
case MotionEvent.ACTION_POINTER_2_DOWN:
canRotate=true;
preAngle=getRotateAngle(ev.getX(0),ev.getY(0), ev.getX(1), ev.getY(1));
break;
}
mDetector.onTouchEvent(ev);
return super.onTouchEvent(ev);
}
}
}