blob: 466172b7cda2fcce43b3b176ca1800abb6e9d4a3 [file] [log] [blame]
Michael Kolb8872c232013-01-29 10:33:22 -08001/*
Doris Liu6432cd62013-06-13 17:20:31 -07002 * Copyright (C) 2013 The Android Open Source Project
Michael Kolb8872c232013-01-29 10:33:22 -08003 *
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
17package com.android.camera;
18
Doris Liu6432cd62013-06-13 17:20:31 -070019import android.view.GestureDetector;
Michael Kolb8872c232013-01-29 10:33:22 -080020import android.view.MotionEvent;
21import android.view.ScaleGestureDetector;
22import android.view.View;
Michael Kolb8872c232013-01-29 10:33:22 -080023
24import com.android.camera.ui.PieRenderer;
25import com.android.camera.ui.RenderOverlay;
26import com.android.camera.ui.ZoomRenderer;
Michael Kolb8872c232013-01-29 10:33:22 -080027
Doris Liu6432cd62013-06-13 17:20:31 -070028/* PreviewGestures disambiguates touch events received on RenderOverlay
29 * and dispatch them to the proper recipient (i.e. zoom renderer or pie renderer).
30 * Touch events on CameraControls will be handled by framework.
31 * */
Michael Kolb8872c232013-01-29 10:33:22 -080032public class PreviewGestures
33 implements ScaleGestureDetector.OnScaleGestureListener {
34
35 private static final String TAG = "CAM_gestures";
36
Michael Kolb8872c232013-01-29 10:33:22 -080037 private static final int MODE_NONE = 0;
Michael Kolb8872c232013-01-29 10:33:22 -080038 private static final int MODE_ZOOM = 2;
Michael Kolb3bc96b22013-03-12 10:24:42 -070039
40 public static final int DIR_UP = 0;
41 public static final int DIR_DOWN = 1;
42 public static final int DIR_LEFT = 2;
43 public static final int DIR_RIGHT = 3;
Michael Kolb8872c232013-01-29 10:33:22 -080044
Michael Kolbd6954f32013-03-08 20:43:01 -080045 private SingleTapListener mTapListener;
Michael Kolb8872c232013-01-29 10:33:22 -080046 private RenderOverlay mOverlay;
47 private PieRenderer mPie;
48 private ZoomRenderer mZoom;
49 private MotionEvent mDown;
50 private MotionEvent mCurrent;
51 private ScaleGestureDetector mScale;
Michael Kolb8872c232013-01-29 10:33:22 -080052 private int mMode;
Doris Liu6432cd62013-06-13 17:20:31 -070053 private boolean mZoomEnabled;
Michael Kolb8872c232013-01-29 10:33:22 -080054 private boolean mEnabled;
55 private boolean mZoomOnly;
Doris Liu6432cd62013-06-13 17:20:31 -070056 private GestureDetector mGestureDetector;
57
58 private GestureDetector.SimpleOnGestureListener mGestureListener = new GestureDetector.SimpleOnGestureListener() {
59 @Override
60 public void onLongPress (MotionEvent e) {
61 // Open pie
Michael Kolba77d6e02013-06-26 14:27:56 -070062 if (!mZoomOnly && mPie != null && !mPie.showsItems()) {
Doris Liu6432cd62013-06-13 17:20:31 -070063 openPie();
64 }
65 }
66
67 @Override
68 public boolean onSingleTapUp (MotionEvent e) {
69 // Tap to focus when pie is not open
70 if (mPie == null || !mPie.showsItems()) {
71 mTapListener.onSingleTapUp(null, (int) e.getX(), (int) e.getY());
72 return true;
73 }
74 return false;
75 }
76
77 @Override
78 public boolean onScroll (MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
Michael Kolba77d6e02013-06-26 14:27:56 -070079 if (mZoomOnly || mMode == MODE_ZOOM) return false;
Doris Liu6432cd62013-06-13 17:20:31 -070080 int deltaX = (int) (e1.getX() - e2.getX());
81 int deltaY = (int) (e1.getY() - e2.getY());
82 if (deltaY > 2 * deltaX && deltaY > -2 * deltaX) {
83 // Open pie on swipe up
84 if (mPie != null && !mPie.showsItems()) {
85 openPie();
86 return true;
87 }
88 }
89 return false;
90 }
91 };
Michael Kolb8872c232013-01-29 10:33:22 -080092
Michael Kolbd6954f32013-03-08 20:43:01 -080093 public interface SingleTapListener {
94 public void onSingleTapUp(View v, int x, int y);
95 }
96
97 public PreviewGestures(CameraActivity ctx, SingleTapListener tapListener,
Doris Liu6432cd62013-06-13 17:20:31 -070098 ZoomRenderer zoom, PieRenderer pie) {
Michael Kolbd6954f32013-03-08 20:43:01 -080099 mTapListener = tapListener;
Michael Kolb8872c232013-01-29 10:33:22 -0800100 mPie = pie;
101 mZoom = zoom;
Michael Kolba77d6e02013-06-26 14:27:56 -0700102 mMode = MODE_NONE;
Michael Kolb8872c232013-01-29 10:33:22 -0800103 mScale = new ScaleGestureDetector(ctx, this);
Michael Kolb8872c232013-01-29 10:33:22 -0800104 mEnabled = true;
Doris Liu6432cd62013-06-13 17:20:31 -0700105 mGestureDetector = new GestureDetector(mGestureListener);
Michael Kolb8872c232013-01-29 10:33:22 -0800106 }
107
108 public void setRenderOverlay(RenderOverlay overlay) {
109 mOverlay = overlay;
110 }
111
Michael Kolb8872c232013-01-29 10:33:22 -0800112 public void setEnabled(boolean enabled) {
113 mEnabled = enabled;
Doris Liu6432cd62013-06-13 17:20:31 -0700114 }
115
116 public void setZoomEnabled(boolean enable) {
117 mZoomEnabled = enable;
Michael Kolb8872c232013-01-29 10:33:22 -0800118 }
119
120 public void setZoomOnly(boolean zoom) {
121 mZoomOnly = zoom;
122 }
123
Doris Liu6432cd62013-06-13 17:20:31 -0700124 public boolean isEnabled() {
125 return mEnabled;
Doris Liu9cdfe002013-04-16 09:50:56 -0700126 }
127
Michael Kolb8872c232013-01-29 10:33:22 -0800128 public boolean dispatchTouch(MotionEvent m) {
129 if (!mEnabled) {
Doris Liu6432cd62013-06-13 17:20:31 -0700130 return false;
Michael Kolb8872c232013-01-29 10:33:22 -0800131 }
132 mCurrent = m;
133 if (MotionEvent.ACTION_DOWN == m.getActionMasked()) {
Doris Liu6432cd62013-06-13 17:20:31 -0700134 mMode = MODE_NONE;
135 mDown = MotionEvent.obtain(m);
Michael Kolb8872c232013-01-29 10:33:22 -0800136 }
Michael Kolb8872c232013-01-29 10:33:22 -0800137
Doris Liu6432cd62013-06-13 17:20:31 -0700138 // If pie is open, redirects all the touch events to pie.
139 if (mPie != null && mPie.isOpen()) {
140 return sendToPie(m);
141 }
142
143 // If pie is not open, send touch events to gesture detector and scale
144 // listener to recognize the gesture.
145 mGestureDetector.onTouchEvent(m);
146 if (mZoom != null) {
147 mScale.onTouchEvent(m);
148 if (MotionEvent.ACTION_POINTER_DOWN == m.getActionMasked()) {
149 mMode = MODE_ZOOM;
150 if (mZoomEnabled) {
151 // Start showing zoom UI as soon as there is a second finger down
152 mZoom.onScaleBegin(mScale);
Michael Kolb8872c232013-01-29 10:33:22 -0800153 }
Doris Liu6432cd62013-06-13 17:20:31 -0700154 } else if (MotionEvent.ACTION_POINTER_UP == m.getActionMasked()) {
155 mZoom.onScaleEnd(mScale);
Michael Kolb8872c232013-01-29 10:33:22 -0800156 }
157 }
Doris Liu6432cd62013-06-13 17:20:31 -0700158 return true;
Michael Kolb8872c232013-01-29 10:33:22 -0800159 }
160
Michael Kolb8872c232013-01-29 10:33:22 -0800161 private MotionEvent makeCancelEvent(MotionEvent m) {
162 MotionEvent c = MotionEvent.obtain(m);
163 c.setAction(MotionEvent.ACTION_CANCEL);
164 return c;
165 }
166
167 private void openPie() {
Doris Liu6432cd62013-06-13 17:20:31 -0700168 mGestureDetector.onTouchEvent(makeCancelEvent(mDown));
169 mScale.onTouchEvent(makeCancelEvent(mDown));
Michael Kolb8872c232013-01-29 10:33:22 -0800170 mOverlay.directDispatchTouch(mDown, mPie);
171 }
172
Michael Kolb8872c232013-01-29 10:33:22 -0800173 private boolean sendToPie(MotionEvent m) {
Michael Kolb8872c232013-01-29 10:33:22 -0800174 return mOverlay.directDispatchTouch(m, mPie);
175 }
176
Doris Liu6432cd62013-06-13 17:20:31 -0700177 // OnScaleGestureListener implementation
Michael Kolb8872c232013-01-29 10:33:22 -0800178 @Override
179 public boolean onScale(ScaleGestureDetector detector) {
180 return mZoom.onScale(detector);
181 }
182
183 @Override
184 public boolean onScaleBegin(ScaleGestureDetector detector) {
Doris Liu6432cd62013-06-13 17:20:31 -0700185 if (mPie == null || !mPie.isOpen()) {
Michael Kolb8872c232013-01-29 10:33:22 -0800186 mMode = MODE_ZOOM;
Doris Liu6432cd62013-06-13 17:20:31 -0700187 mGestureDetector.onTouchEvent(makeCancelEvent(mCurrent));
188 if (!mZoomEnabled) return false;
Michael Kolb8872c232013-01-29 10:33:22 -0800189 return mZoom.onScaleBegin(detector);
Michael Kolb8872c232013-01-29 10:33:22 -0800190 }
Doris Liu6432cd62013-06-13 17:20:31 -0700191 return false;
Michael Kolb8872c232013-01-29 10:33:22 -0800192 }
193
194 @Override
195 public void onScaleEnd(ScaleGestureDetector detector) {
Doris Liu6432cd62013-06-13 17:20:31 -0700196 mZoom.onScaleEnd(detector);
Michael Kolb8872c232013-01-29 10:33:22 -0800197 }
198}
Doris Liu6432cd62013-06-13 17:20:31 -0700199