From 8dd1afedc5899c7539978b706fb165fba8d1e2f2 Mon Sep 17 00:00:00 2001 From: George Mount Date: Wed, 14 Aug 2013 16:19:43 -0700 Subject: [PATCH] Give CropActivity minimal touchpad support. Bug 9265629 Change-Id: If42442b763fbeff639122ab2f5aeb8b43e43457b --- .../gallery3d/filtershow/crop/CropActivity.java | 149 +++++++++++++++++++-- 1 file changed, 138 insertions(+), 11 deletions(-) diff --git a/src/com/android/gallery3d/filtershow/crop/CropActivity.java b/src/com/android/gallery3d/filtershow/crop/CropActivity.java index 0a0c36703..9c0130854 100644 --- a/src/com/android/gallery3d/filtershow/crop/CropActivity.java +++ b/src/com/android/gallery3d/filtershow/crop/CropActivity.java @@ -37,6 +37,10 @@ import android.os.Bundle; import android.provider.MediaStore; import android.util.DisplayMetrics; import android.util.Log; +import android.view.InputDevice; +import android.view.InputDevice.MotionRange; +import android.view.KeyEvent; +import android.view.MotionEvent; import android.view.View; import android.view.View.OnClickListener; import android.view.WindowManager; @@ -46,6 +50,8 @@ import com.android.gallery3d.R; import com.android.gallery3d.common.Utils; import com.android.gallery3d.filtershow.cache.ImageLoader; import com.android.gallery3d.filtershow.tools.SaveImage; +import com.google.android.pano.util.TouchNavGestureDetector; +import com.google.android.pano.util.TouchNavGestureDetector.OnGestureListener; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; @@ -57,9 +63,10 @@ import java.io.OutputStream; /** * Activity for cropping an image. */ -public class CropActivity extends Activity { +public class CropActivity extends Activity implements OnGestureListener { private static final String LOGTAG = "CropActivity"; public static final String CROP_ACTION = "com.android.camera.action.CROP"; + private static final int MIN_SCROLL_LENGTH = 5; private CropExtras mCropExtras = null; private LoadBitmapTask mLoadBitmapTask = null; @@ -92,9 +99,25 @@ public class CropActivity extends Activity { private static final int FLAG_CHECK = DO_SET_WALLPAPER | DO_RETURN_DATA | DO_EXTRA_OUTPUT; + private TouchNavGestureDetector mGestureDetector; + private float mTouchPadToViewRatioX; + private float mTouchPadToViewRatioY; + private float mResolutionX; + private float mResolutionY; + + /** + * Used for click filtering. Any scroll less than MIN_SCROLL_LENGTH will not + * be registered. This will make clicking motions not trigger a scroll. Once + * you get past MIN_SCROLL_LENGTH, you can go below it again and register + * scrolls. This is to allow for starting a scroll and then moving back to + * the origin of the scroll. + */ + private boolean mDidStartDrag; + @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + mGestureDetector = new TouchNavGestureDetector(this, this); Intent intent = getIntent(); setResult(RESULT_CANCELED, new Intent()); mCropExtras = getExtrasFromIntent(intent); @@ -106,16 +129,18 @@ public class CropActivity extends Activity { mCropView = (CropView) findViewById(R.id.cropView); ActionBar actionBar = getActionBar(); - actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM); - actionBar.setCustomView(R.layout.filtershow_actionbar); - - View mSaveButton = actionBar.getCustomView(); - mSaveButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View view) { - startFinishOutput(); - } - }); + if (actionBar != null) { + actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM); + actionBar.setCustomView(R.layout.filtershow_actionbar); + + mSaveButton = actionBar.getCustomView(); + mSaveButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View view) { + startFinishOutput(); + } + }); + } if (intent.getData() != null) { mSourceUri = intent.getData(); @@ -694,4 +719,106 @@ public class CropActivity extends Activity { RectF scaledCrop = CropMath.getScaledCropBounds(crop, photo, imageBounds); return scaledCrop; } + + @Override + public boolean onGenericMotionEvent(MotionEvent event) { + boolean handled = super.onGenericMotionEvent(event); + if (!handled) { + handled = mGestureDetector.onGenericMotionEvent(event); + if (!handled + && (event.getSource() & TouchNavGestureDetector.SOURCE_TOUCH_NAVIGATION) + == TouchNavGestureDetector.SOURCE_TOUCH_NAVIGATION) { + int action = event.getActionMasked(); + switch (action) { + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_CANCEL: + sendScaledMotionEvent(event); + handled = true; + break; + } + } + } + return handled; + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + boolean handled = super.onKeyDown(keyCode, event); + if (!handled) { + if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER || keyCode == KeyEvent.KEYCODE_ENTER) { + startFinishOutput(); + handled = true; + } + } + return handled; + } + + /** + * Returns whether a scroll happened. + */ + @Override + public boolean onScroll(MotionEvent downEvent, MotionEvent currentEvent, float deltaX, + float deltaY) { + // If <5mm from the start, consider it a click. Used for smoother + // clicks. + if (!mDidStartDrag) { + float distanceX = Math.abs((currentEvent.getX() - downEvent.getX()) / mResolutionX); + float distanceY = Math.abs((currentEvent.getY() - downEvent.getY()) / mResolutionY); + if (distanceX < MIN_SCROLL_LENGTH && distanceY < MIN_SCROLL_LENGTH) { + // Not moved enough to scroll. + return false; + } + } + // Moved enough to scroll. + mDidStartDrag = true; + sendScaledMotionEvent(currentEvent); + return true; + } + + @Override + public boolean onFling(MotionEvent downEvent, MotionEvent currentEvent, float velX, + float velY) { + sendScaledMotionEvent(currentEvent); + return true; + } + + @Override + public boolean onDown(MotionEvent downEvent) { + mDidStartDrag = false; + InputDevice device = downEvent.getDevice(); + MotionRange motionRangeX = device.getMotionRange(MotionEvent.AXIS_X); + MotionRange motionRangeY = device.getMotionRange(MotionEvent.AXIS_Y); + + if (motionRangeX == null || motionRangeY == null) { + return false; + } + + mResolutionX = motionRangeX.getResolution(); + mResolutionY = motionRangeY.getResolution(); + + if (mResolutionX == 0) { + mResolutionX = TouchNavGestureDetector.DEFAULT_TOUCH_RESOLUTION; + } + if (mResolutionY == 0) { + mResolutionY = TouchNavGestureDetector.DEFAULT_TOUCH_RESOLUTION; + } + + // This is the conversion between a drag on the device vs. a drag on + // the screen. + mTouchPadToViewRatioX = mCropView.getWidth() / motionRangeX.getRange(); + mTouchPadToViewRatioY = mCropView.getHeight() / motionRangeY.getRange(); + + sendScaledMotionEvent(downEvent); + return true; + } + + private void sendScaledMotionEvent(MotionEvent event) { + final int scaledX = (int) (mTouchPadToViewRatioX * event.getX()); + final int scaledY = (int) (mTouchPadToViewRatioY * event.getY()); + final MotionEvent ev = MotionEvent.obtain(event.getEventTime(), event.getEventTime(), + event.getActionMasked(), scaledX, scaledY, 0); + mCropView.onTouchEvent(ev); + ev.recycle(); + } + } -- 2.11.0