OSDN Git Service

am aa52b3d2: Prevent crash for when newData cannot be found.
[android-x86/packages-apps-Camera2.git] / src / com / android / camera / PreviewGestures.java
1 /*
2  * Copyright (C) 2013 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package com.android.camera;
18
19 import android.view.GestureDetector;
20 import android.view.MotionEvent;
21 import android.view.ScaleGestureDetector;
22 import android.view.View;
23
24 import com.android.camera.debug.Log;
25 import com.android.camera.ui.PieRenderer;
26 import com.android.camera.ui.RenderOverlay;
27 import com.android.camera.ui.ZoomRenderer;
28
29 /* PreviewGestures disambiguates touch events received on RenderOverlay
30  * and dispatch them to the proper recipient (i.e. zoom renderer or pie renderer).
31  * Touch events on CameraControls will be handled by framework.
32  * */
33 public class PreviewGestures
34         implements ScaleGestureDetector.OnScaleGestureListener {
35
36     private static final Log.Tag TAG = new Log.Tag("PreviewGestures");
37
38     private static final int MODE_NONE = 0;
39     private static final int MODE_ZOOM = 2;
40
41     public static final int DIR_UP = 0;
42     public static final int DIR_DOWN = 1;
43     public static final int DIR_LEFT = 2;
44     public static final int DIR_RIGHT = 3;
45
46     private final SingleTapListener mTapListener;
47     private RenderOverlay mOverlay;
48     private final PieRenderer mPie;
49     private final ZoomRenderer mZoom;
50     private MotionEvent mDown;
51     private MotionEvent mCurrent;
52     private final ScaleGestureDetector mScale;
53     private int mMode;
54     private boolean mZoomEnabled;
55     private boolean mEnabled;
56     private boolean mZoomOnly;
57     private final GestureDetector mGestureDetector;
58
59     private final GestureDetector.SimpleOnGestureListener mGestureListener = new GestureDetector.SimpleOnGestureListener() {
60         @Override
61         public void onLongPress (MotionEvent e) {
62             // Open pie
63             if (!mZoomOnly && mPie != null && !mPie.showsItems()) {
64                 openPie();
65             }
66         }
67
68         @Override
69         public boolean onSingleTapUp (MotionEvent e) {
70             // Tap to focus when pie is not open
71             if (mPie == null || !mPie.showsItems()) {
72                 mTapListener.onSingleTapUp(null, (int) e.getX(), (int) e.getY());
73                 return true;
74             }
75             return false;
76         }
77
78         @Override
79         public boolean onScroll (MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
80             if (e1 == null) {
81                 // e1 can be null if for some cases.
82                 return false;
83             }
84             if (mZoomOnly || mMode == MODE_ZOOM) return false;
85             int deltaX = (int) (e1.getX() - e2.getX());
86             int deltaY = (int) (e1.getY() - e2.getY());
87             if (deltaY > 2 * deltaX && deltaY > -2 * deltaX) {
88                 // Open pie on swipe up
89                 if (mPie != null && !mPie.showsItems()) {
90                     openPie();
91                     return true;
92                 }
93             }
94             return false;
95         }
96     };
97
98     public interface SingleTapListener {
99         public void onSingleTapUp(View v, int x, int y);
100     }
101
102     public PreviewGestures(CameraActivity ctx, SingleTapListener tapListener,
103             ZoomRenderer zoom, PieRenderer pie) {
104         mTapListener = tapListener;
105         mPie = pie;
106         mZoom = zoom;
107         mMode = MODE_NONE;
108         mScale = new ScaleGestureDetector(ctx, this);
109         mEnabled = true;
110         mGestureDetector = new GestureDetector(mGestureListener);
111     }
112
113     public void setRenderOverlay(RenderOverlay overlay) {
114         mOverlay = overlay;
115     }
116
117     public void setEnabled(boolean enabled) {
118         mEnabled = enabled;
119     }
120
121     public void setZoomEnabled(boolean enable) {
122         mZoomEnabled = enable;
123     }
124
125     public void setZoomOnly(boolean zoom) {
126         mZoomOnly = zoom;
127     }
128
129     public boolean isEnabled() {
130         return mEnabled;
131     }
132
133     public boolean dispatchTouch(MotionEvent m) {
134         if (!mEnabled) {
135             return false;
136         }
137         mCurrent = m;
138         if (MotionEvent.ACTION_DOWN == m.getActionMasked()) {
139             mMode = MODE_NONE;
140             mDown = MotionEvent.obtain(m);
141         }
142
143         // If pie is open, redirects all the touch events to pie.
144         if (mPie != null && mPie.isOpen()) {
145             return sendToPie(m);
146         }
147
148         // If pie is not open, send touch events to gesture detector and scale
149         // listener to recognize the gesture.
150         mGestureDetector.onTouchEvent(m);
151         if (mZoom != null) {
152             mScale.onTouchEvent(m);
153             if (MotionEvent.ACTION_POINTER_DOWN == m.getActionMasked()) {
154                 mMode = MODE_ZOOM;
155                 if (mZoomEnabled) {
156                     // Start showing zoom UI as soon as there is a second finger down
157                     mZoom.onScaleBegin(mScale);
158                 }
159             } else if (MotionEvent.ACTION_POINTER_UP == m.getActionMasked()) {
160                 mZoom.onScaleEnd(mScale);
161             }
162         }
163         return true;
164     }
165
166     private MotionEvent makeCancelEvent(MotionEvent m) {
167         MotionEvent c = MotionEvent.obtain(m);
168         c.setAction(MotionEvent.ACTION_CANCEL);
169         return c;
170     }
171
172     private void openPie() {
173         mGestureDetector.onTouchEvent(makeCancelEvent(mDown));
174         mScale.onTouchEvent(makeCancelEvent(mDown));
175         mOverlay.directDispatchTouch(mDown, mPie);
176     }
177
178     private boolean sendToPie(MotionEvent m) {
179         return mOverlay.directDispatchTouch(m, mPie);
180     }
181
182     // OnScaleGestureListener implementation
183     @Override
184     public boolean onScale(ScaleGestureDetector detector) {
185         return mZoom.onScale(detector);
186     }
187
188     @Override
189     public boolean onScaleBegin(ScaleGestureDetector detector) {
190         if (mPie == null || !mPie.isOpen()) {
191             mMode = MODE_ZOOM;
192             mGestureDetector.onTouchEvent(makeCancelEvent(mCurrent));
193             if (!mZoomEnabled) return false;
194             return mZoom.onScaleBegin(detector);
195         }
196         return false;
197     }
198
199     @Override
200     public void onScaleEnd(ScaleGestureDetector detector) {
201         mZoom.onScaleEnd(detector);
202     }
203 }
204