OSDN Git Service

Add more metrics to Editor
[android-x86/packages-apps-Camera2.git] / src / com / android / camera / NewPreviewGestures.java
1 package com.android.camera;
2
3 /*
4  * Copyright (C) 2013 The Android Open Source Project
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18
19 import android.os.Handler;
20 import android.os.Message;
21 import android.util.Log;
22 import android.view.GestureDetector;
23 import android.view.MotionEvent;
24 import android.view.ScaleGestureDetector;
25 import android.view.View;
26 import android.view.ViewConfiguration;
27
28 import com.android.camera.PreviewGestures.SingleTapListener;
29 import com.android.camera.PreviewGestures.SwipeListener;
30 import com.android.camera.ui.PieRenderer;
31 import com.android.camera.ui.RenderOverlay;
32 import com.android.camera.ui.ZoomRenderer;
33 import com.android.gallery3d.R;
34
35 import java.util.ArrayList;
36 import java.util.List;
37
38 /* NewPreviewGestures disambiguates touch events received on RenderOverlay
39  * and dispatch them to the proper recipient (i.e. zoom renderer or pie renderer).
40  * Touch events on CameraControls will be handled by framework.
41  * */
42 public class NewPreviewGestures
43         implements ScaleGestureDetector.OnScaleGestureListener {
44
45     private static final String TAG = "CAM_gestures";
46
47     private static final long TIMEOUT_PIE = 200;
48     private static final int MSG_PIE = 1;
49     private static final int MODE_NONE = 0;
50     private static final int MODE_PIE = 1;
51     private static final int MODE_ZOOM = 2;
52     private static final int MODE_MODULE = 3;
53     private static final int MODE_ALL = 4;
54     private static final int MODE_SWIPE = 5;
55
56     public static final int DIR_UP = 0;
57     public static final int DIR_DOWN = 1;
58     public static final int DIR_LEFT = 2;
59     public static final int DIR_RIGHT = 3;
60
61     private NewCameraActivity mActivity;
62     private SingleTapListener mTapListener;
63     private RenderOverlay mOverlay;
64     private PieRenderer mPie;
65     private ZoomRenderer mZoom;
66     private MotionEvent mDown;
67     private MotionEvent mCurrent;
68     private ScaleGestureDetector mScale;
69     private int mMode;
70     private int mSlop;
71     private int mTapTimeout;
72     private boolean mZoomEnabled;
73     private boolean mEnabled;
74     private boolean mZoomOnly;
75     private int mOrientation;
76     private GestureDetector mGestureDetector;
77
78     private GestureDetector.SimpleOnGestureListener mGestureListener = new GestureDetector.SimpleOnGestureListener() {
79         @Override
80         public void onLongPress (MotionEvent e) {
81             // Open pie
82             if (mPie != null && !mPie.showsItems()) {
83                 openPie();
84             }
85         }
86
87         @Override
88         public boolean onSingleTapUp (MotionEvent e) {
89             // Tap to focus when pie is not open
90             if (mPie == null || !mPie.showsItems()) {
91                 mTapListener.onSingleTapUp(null, (int) e.getX(), (int) e.getY());
92                 return true;
93             }
94             return false;
95         }
96
97         @Override
98         public boolean onScroll (MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
99             if (mMode == MODE_ZOOM) return false;
100             int deltaX = (int) (e1.getX() - e2.getX());
101             int deltaY = (int) (e1.getY() - e2.getY());
102             if (deltaY > 2 * deltaX && deltaY > -2 * deltaX) {
103                 // Open pie on swipe up
104                 if (mPie != null && !mPie.showsItems()) {
105                     openPie();
106                     return true;
107                 }
108             }
109             return false;
110         }
111     };
112
113     private Handler mHandler = new Handler() {
114         public void handleMessage(Message msg) {
115             if (msg.what == MSG_PIE) {
116                 mMode = MODE_PIE;
117                 openPie();
118             }
119         }
120     };
121
122     public interface SingleTapListener {
123         public void onSingleTapUp(View v, int x, int y);
124     }
125
126     public NewPreviewGestures(NewCameraActivity ctx, SingleTapListener tapListener,
127             ZoomRenderer zoom, PieRenderer pie) {
128         mActivity = ctx;
129         mTapListener = tapListener;
130         mPie = pie;
131         mZoom = zoom;
132         mMode = MODE_ALL;
133         mScale = new ScaleGestureDetector(ctx, this);
134         mSlop = (int) ctx.getResources().getDimension(R.dimen.pie_touch_slop);
135         mTapTimeout = ViewConfiguration.getTapTimeout();
136         mEnabled = true;
137         mGestureDetector = new GestureDetector(mGestureListener);
138     }
139
140     public void setRenderOverlay(RenderOverlay overlay) {
141         mOverlay = overlay;
142     }
143
144     public void setOrientation(int orientation) {
145         mOrientation = orientation;
146     }
147
148     public void setEnabled(boolean enabled) {
149         mEnabled = enabled;
150     }
151
152     public void setZoomEnabled(boolean enable) {
153         mZoomEnabled = enable;
154     }
155
156     public void setZoomOnly(boolean zoom) {
157         mZoomOnly = zoom;
158     }
159
160     public boolean isEnabled() {
161         return mEnabled;
162     }
163
164     public boolean dispatchTouch(MotionEvent m) {
165         if (!mEnabled) {
166             return false;
167         }
168         mCurrent = m;
169         if (MotionEvent.ACTION_DOWN == m.getActionMasked()) {
170             mMode = MODE_NONE;
171             mDown = MotionEvent.obtain(m);
172         }
173
174         // If pie is open, redirects all the touch events to pie.
175         if (mPie != null && mPie.isOpen()) {
176             return sendToPie(m);
177         }
178
179         // If pie is not open, send touch events to gesture detector and scale
180         // listener to recognize the gesture.
181         mGestureDetector.onTouchEvent(m);
182         if (mZoom != null) {
183             mScale.onTouchEvent(m);
184             if (MotionEvent.ACTION_POINTER_DOWN == m.getActionMasked()) {
185                 mMode = MODE_ZOOM;
186                 if (mZoomEnabled) {
187                     // Start showing zoom UI as soon as there is a second finger down
188                     mZoom.onScaleBegin(mScale);
189                 }
190             } else if (MotionEvent.ACTION_POINTER_UP == m.getActionMasked()) {
191                 mZoom.onScaleEnd(mScale);
192             }
193         }
194         return true;
195     }
196
197     // left tests for finger moving right to left
198     private int getSwipeDirection(MotionEvent m) {
199         float dx = 0;
200         float dy = 0;
201         switch (mOrientation) {
202         case 0:
203             dx = m.getX() - mDown.getX();
204             dy = m.getY() - mDown.getY();
205             break;
206         case 90:
207             dx = - (m.getY() - mDown.getY());
208             dy = m.getX() - mDown.getX();
209             break;
210         case 180:
211             dx = -(m.getX() - mDown.getX());
212             dy = m.getY() - mDown.getY();
213             break;
214         case 270:
215             dx = m.getY() - mDown.getY();
216             dy = m.getX() - mDown.getX();
217             break;
218         }
219         if (dx < 0 && (Math.abs(dy) / -dx < 2)) return DIR_LEFT;
220         if (dx > 0 && (Math.abs(dy) / dx < 2)) return DIR_RIGHT;
221         if (dy > 0) return DIR_DOWN;
222         return DIR_UP;
223     }
224
225     private MotionEvent makeCancelEvent(MotionEvent m) {
226         MotionEvent c = MotionEvent.obtain(m);
227         c.setAction(MotionEvent.ACTION_CANCEL);
228         return c;
229     }
230
231     private void openPie() {
232         mGestureDetector.onTouchEvent(makeCancelEvent(mDown));
233         mScale.onTouchEvent(makeCancelEvent(mDown));
234         mOverlay.directDispatchTouch(mDown, mPie);
235     }
236
237     private boolean sendToPie(MotionEvent m) {
238         return mOverlay.directDispatchTouch(m, mPie);
239     }
240
241     // OnScaleGestureListener implementation
242     @Override
243     public boolean onScale(ScaleGestureDetector detector) {
244         return mZoom.onScale(detector);
245     }
246
247     @Override
248     public boolean onScaleBegin(ScaleGestureDetector detector) {
249         if (mPie == null || !mPie.isOpen()) {
250             mMode = MODE_ZOOM;
251             mGestureDetector.onTouchEvent(makeCancelEvent(mCurrent));
252             if (!mZoomEnabled) return false;
253             return mZoom.onScaleBegin(detector);
254         }
255         return false;
256     }
257
258     @Override
259     public void onScaleEnd(ScaleGestureDetector detector) {
260         mZoom.onScaleEnd(detector);
261     }
262 }
263