OSDN Git Service

Give CropActivity minimal touchpad support.
authorGeorge Mount <mount@google.com>
Wed, 14 Aug 2013 23:19:43 +0000 (16:19 -0700)
committerGeorge Mount <mount@google.com>
Thu, 15 Aug 2013 14:08:23 +0000 (07:08 -0700)
Bug 9265629

Change-Id: If42442b763fbeff639122ab2f5aeb8b43e43457b

src/com/android/gallery3d/filtershow/crop/CropActivity.java

index 0a0c367..9c01308 100644 (file)
@@ -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();
+    }
+
 }