1/*
2 * Copyright (C) 2012 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
17package com.android.gallery3d.ui;
18
19import android.content.Context;
20import android.os.SystemClock;
21import android.view.GestureDetector;
22import android.view.MotionEvent;
23import android.view.ScaleGestureDetector;
24
25// This class aggregates three gesture detectors: GestureDetector,
26// ScaleGestureDetector, and DownUpDetector.
27public class GestureRecognizer {
28    @SuppressWarnings("unused")
29    private static final String TAG = "GestureRecognizer";
30
31    public interface Listener {
32        boolean onSingleTapUp(float x, float y);
33        boolean onDoubleTap(float x, float y);
34        boolean onScroll(float dx, float dy, float totalX, float totalY);
35        boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY);
36        boolean onScaleBegin(float focusX, float focusY);
37        boolean onScale(float focusX, float focusY, float scale);
38        void onScaleEnd();
39        void onDown(float x, float y);
40        void onUp();
41    }
42
43    private final GestureDetector mGestureDetector;
44    private final ScaleGestureDetector mScaleDetector;
45    private final DownUpDetector mDownUpDetector;
46    private final Listener mListener;
47
48    public GestureRecognizer(Context context, Listener listener) {
49        mListener = listener;
50        mGestureDetector = new GestureDetector(context, new MyGestureListener(),
51                null, true /* ignoreMultitouch */);
52        mScaleDetector = new ScaleGestureDetector(
53                context, new MyScaleListener());
54        mDownUpDetector = new DownUpDetector(new MyDownUpListener());
55    }
56
57    public void onTouchEvent(MotionEvent event) {
58        mGestureDetector.onTouchEvent(event);
59        mScaleDetector.onTouchEvent(event);
60        mDownUpDetector.onTouchEvent(event);
61    }
62
63    public boolean isDown() {
64        return mDownUpDetector.isDown();
65    }
66
67    public void cancelScale() {
68        long now = SystemClock.uptimeMillis();
69        MotionEvent cancelEvent = MotionEvent.obtain(
70                now, now, MotionEvent.ACTION_CANCEL, 0, 0, 0);
71        mScaleDetector.onTouchEvent(cancelEvent);
72        cancelEvent.recycle();
73    }
74
75    private class MyGestureListener
76                extends GestureDetector.SimpleOnGestureListener {
77        @Override
78        public boolean onSingleTapUp(MotionEvent e) {
79            return mListener.onSingleTapUp(e.getX(), e.getY());
80        }
81
82        @Override
83        public boolean onDoubleTap(MotionEvent e) {
84            return mListener.onDoubleTap(e.getX(), e.getY());
85        }
86
87        @Override
88        public boolean onScroll(
89                MotionEvent e1, MotionEvent e2, float dx, float dy) {
90            return mListener.onScroll(
91                    dx, dy, e2.getX() - e1.getX(), e2.getY() - e1.getY());
92        }
93
94        @Override
95        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
96                float velocityY) {
97            return mListener.onFling(e1, e2, velocityX, velocityY);
98        }
99    }
100
101    private class MyScaleListener
102            extends ScaleGestureDetector.SimpleOnScaleGestureListener {
103        @Override
104        public boolean onScaleBegin(ScaleGestureDetector detector) {
105            return mListener.onScaleBegin(
106                    detector.getFocusX(), detector.getFocusY());
107        }
108
109        @Override
110        public boolean onScale(ScaleGestureDetector detector) {
111            return mListener.onScale(detector.getFocusX(),
112                    detector.getFocusY(), detector.getScaleFactor());
113        }
114
115        @Override
116        public void onScaleEnd(ScaleGestureDetector detector) {
117            mListener.onScaleEnd();
118        }
119    }
120
121    private class MyDownUpListener implements DownUpDetector.DownUpListener {
122        @Override
123        public void onDown(MotionEvent e) {
124            mListener.onDown(e.getX(), e.getY());
125        }
126
127        @Override
128        public void onUp(MotionEvent e) {
129            mListener.onUp();
130        }
131    }
132}
133