149b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong/*
249b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong * Copyright (C) 2013 The Android Open Source Project
349b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong *
449b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong * Licensed under the Apache License, Version 2.0 (the "License");
549b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong * you may not use this file except in compliance with the License.
649b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong * You may obtain a copy of the License at
749b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong *
849b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong *      http://www.apache.org/licenses/LICENSE-2.0
949b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong *
1049b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong * Unless required by applicable law or agreed to in writing, software
1149b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong * distributed under the License is distributed on an "AS IS" BASIS,
1249b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1349b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong * See the License for the specific language governing permissions and
1449b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong * limitations under the License.
1549b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong */
1649b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong
1749b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kongpackage com.android.camera.ui;
1849b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong
1949b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kongimport android.content.Context;
2049b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kongimport android.view.GestureDetector;
2149b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kongimport android.view.MotionEvent;
2249b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kongimport android.view.ScaleGestureDetector;
2349b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong
242bca210e5fc8a77685775ffb403096167b017dceAngus Kongimport com.android.camera.debug.Log;
252bca210e5fc8a77685775ffb403096167b017dceAngus Kong
26121022cb590955e37f1264f77190ce4711159976Doris Liu// This class aggregates two gesture detectors: GestureDetector,
2749b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong// ScaleGestureDetector.
28166e36fb6e04d40a1bef0459ee6b96c9c736039bAngus Kongpublic class FilmstripGestureRecognizer {
2949b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong    @SuppressWarnings("unused")
302bca210e5fc8a77685775ffb403096167b017dceAngus Kong    private static final Log.Tag TAG = new Log.Tag("FStripGestureRecog");
3149b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong
3249b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong    public interface Listener {
3349b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong        boolean onSingleTapUp(float x, float y);
3449b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong        boolean onDoubleTap(float x, float y);
3549b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong        boolean onScroll(float x, float y, float dx, float dy);
3649b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong        boolean onFling(float velocityX, float velocityY);
3749b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong        boolean onScaleBegin(float focusX, float focusY);
3849b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong        boolean onScale(float focusX, float focusY, float scale);
3949b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong        boolean onDown(float x, float y);
4087f9a62f473a3c57505e2877b0a46ab3cb5e62acAngus Kong        boolean onUp(float x, float y);
4126795a9258c0815ca2a92d2c660438066f001022Angus Kong        void onLongPress(float x, float y);
4249b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong        void onScaleEnd();
4349b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong    }
4449b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong
4549b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong    private final GestureDetector mGestureDetector;
4649b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong    private final ScaleGestureDetector mScaleDetector;
4749b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong    private final Listener mListener;
4849b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong
49166e36fb6e04d40a1bef0459ee6b96c9c736039bAngus Kong    public FilmstripGestureRecognizer(Context context, Listener listener) {
5049b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong        mListener = listener;
5149b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong        mGestureDetector = new GestureDetector(context, new MyGestureListener(),
5249b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong                null, true /* ignoreMultitouch */);
53121022cb590955e37f1264f77190ce4711159976Doris Liu        mGestureDetector.setOnDoubleTapListener(new MyDoubleTapListener());
5449b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong        mScaleDetector = new ScaleGestureDetector(
5549b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong                context, new MyScaleListener());
5649b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong    }
5749b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong
58166e36fb6e04d40a1bef0459ee6b96c9c736039bAngus Kong    public boolean onTouchEvent(MotionEvent event) {
59166e36fb6e04d40a1bef0459ee6b96c9c736039bAngus Kong        final boolean gestureProcessed = mGestureDetector.onTouchEvent(event);
60166e36fb6e04d40a1bef0459ee6b96c9c736039bAngus Kong        final boolean scaleProcessed = mScaleDetector.onTouchEvent(event);
6187f9a62f473a3c57505e2877b0a46ab3cb5e62acAngus Kong        if (event.getAction() == MotionEvent.ACTION_UP) {
6287f9a62f473a3c57505e2877b0a46ab3cb5e62acAngus Kong            mListener.onUp(event.getX(), event.getY());
6387f9a62f473a3c57505e2877b0a46ab3cb5e62acAngus Kong        }
64166e36fb6e04d40a1bef0459ee6b96c9c736039bAngus Kong        return (gestureProcessed | scaleProcessed);
6549b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong    }
6649b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong
6749b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong    private class MyGestureListener
6849b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong                extends GestureDetector.SimpleOnGestureListener {
6949b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong        @Override
7026795a9258c0815ca2a92d2c660438066f001022Angus Kong        public void onLongPress(MotionEvent e) {
7126795a9258c0815ca2a92d2c660438066f001022Angus Kong            mListener.onLongPress(e.getX(), e.getY());
7226795a9258c0815ca2a92d2c660438066f001022Angus Kong        }
7326795a9258c0815ca2a92d2c660438066f001022Angus Kong
7426795a9258c0815ca2a92d2c660438066f001022Angus Kong        @Override
7549b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong        public boolean onScroll(
7649b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong                MotionEvent e1, MotionEvent e2, float dx, float dy) {
7749b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong            return mListener.onScroll(e2.getX(), e2.getY(), dx, dy);
7849b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong        }
7949b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong
8049b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong        @Override
8149b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
8249b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong                float velocityY) {
8349b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong            return mListener.onFling(velocityX, velocityY);
8449b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong        }
8549b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong
8649b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong        @Override
8749b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong        public boolean onDown(MotionEvent e) {
8849b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong            mListener.onDown(e.getX(), e.getY());
8949b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong            return super.onDown(e);
9049b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong        }
9149b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong    }
9249b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong
93121022cb590955e37f1264f77190ce4711159976Doris Liu    /**
94121022cb590955e37f1264f77190ce4711159976Doris Liu     * The listener that is used to notify when a double-tap or a confirmed
95121022cb590955e37f1264f77190ce4711159976Doris Liu     * single-tap occur.
96121022cb590955e37f1264f77190ce4711159976Doris Liu     */
97121022cb590955e37f1264f77190ce4711159976Doris Liu    private class MyDoubleTapListener implements GestureDetector.OnDoubleTapListener {
98121022cb590955e37f1264f77190ce4711159976Doris Liu
99121022cb590955e37f1264f77190ce4711159976Doris Liu        @Override
100121022cb590955e37f1264f77190ce4711159976Doris Liu        public boolean onSingleTapConfirmed(MotionEvent e) {
101121022cb590955e37f1264f77190ce4711159976Doris Liu            return mListener.onSingleTapUp(e.getX(), e.getY());
102121022cb590955e37f1264f77190ce4711159976Doris Liu        }
103121022cb590955e37f1264f77190ce4711159976Doris Liu
104121022cb590955e37f1264f77190ce4711159976Doris Liu        @Override
105121022cb590955e37f1264f77190ce4711159976Doris Liu        public boolean onDoubleTap(MotionEvent e) {
106121022cb590955e37f1264f77190ce4711159976Doris Liu            return mListener.onDoubleTap(e.getX(), e.getY());
107121022cb590955e37f1264f77190ce4711159976Doris Liu        }
108121022cb590955e37f1264f77190ce4711159976Doris Liu
109121022cb590955e37f1264f77190ce4711159976Doris Liu        @Override
110121022cb590955e37f1264f77190ce4711159976Doris Liu        public boolean onDoubleTapEvent(MotionEvent e) {
111121022cb590955e37f1264f77190ce4711159976Doris Liu            return true;
112121022cb590955e37f1264f77190ce4711159976Doris Liu        }
113121022cb590955e37f1264f77190ce4711159976Doris Liu    }
114121022cb590955e37f1264f77190ce4711159976Doris Liu
11549b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong    private class MyScaleListener
11649b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong            extends ScaleGestureDetector.SimpleOnScaleGestureListener {
11749b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong        @Override
11849b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong        public boolean onScaleBegin(ScaleGestureDetector detector) {
11949b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong            return mListener.onScaleBegin(
12049b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong                    detector.getFocusX(), detector.getFocusY());
12149b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong        }
12249b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong
12349b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong        @Override
12449b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong        public boolean onScale(ScaleGestureDetector detector) {
12549b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong            return mListener.onScale(detector.getFocusX(),
12649b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong                    detector.getFocusY(), detector.getScaleFactor());
12749b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong        }
12849b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong
12949b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong        @Override
13049b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong        public void onScaleEnd(ScaleGestureDetector detector) {
13149b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong            mListener.onScaleEnd();
13249b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong        }
13349b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong    }
13449b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong}
135