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
24121022cb590955e37f1264f77190ce4711159976Doris Liu// This class aggregates two gesture detectors: GestureDetector,
2549b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong// ScaleGestureDetector.
2649b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kongpublic class FilmStripGestureRecognizer {
2749b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong    @SuppressWarnings("unused")
2849b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong    private static final String TAG = "FilmStripGestureRecognizer";
2949b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong
3049b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong    public interface Listener {
3149b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong        boolean onSingleTapUp(float x, float y);
3249b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong        boolean onDoubleTap(float x, float y);
3349b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong        boolean onScroll(float x, float y, float dx, float dy);
3449b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong        boolean onFling(float velocityX, float velocityY);
3549b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong        boolean onScaleBegin(float focusX, float focusY);
3649b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong        boolean onScale(float focusX, float focusY, float scale);
3749b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong        boolean onDown(float x, float y);
3887f9a62f473a3c57505e2877b0a46ab3cb5e62acAngus Kong        boolean onUp(float x, float y);
3949b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong        void onScaleEnd();
4049b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong    }
4149b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong
4249b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong    private final GestureDetector mGestureDetector;
4349b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong    private final ScaleGestureDetector mScaleDetector;
4449b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong    private final Listener mListener;
4549b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong
4649b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong    public FilmStripGestureRecognizer(Context context, Listener listener) {
4749b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong        mListener = listener;
4849b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong        mGestureDetector = new GestureDetector(context, new MyGestureListener(),
4949b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong                null, true /* ignoreMultitouch */);
50121022cb590955e37f1264f77190ce4711159976Doris Liu        mGestureDetector.setOnDoubleTapListener(new MyDoubleTapListener());
5149b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong        mScaleDetector = new ScaleGestureDetector(
5249b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong                context, new MyScaleListener());
5349b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong    }
5449b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong
557234f4d6ff4fdcd47eb428405d2b31a5711d20ceDoris Liu    public void onTouchEvent(MotionEvent event) {
567234f4d6ff4fdcd47eb428405d2b31a5711d20ceDoris Liu        mGestureDetector.onTouchEvent(event);
577234f4d6ff4fdcd47eb428405d2b31a5711d20ceDoris Liu        mScaleDetector.onTouchEvent(event);
5887f9a62f473a3c57505e2877b0a46ab3cb5e62acAngus Kong        if (event.getAction() == MotionEvent.ACTION_UP) {
5987f9a62f473a3c57505e2877b0a46ab3cb5e62acAngus Kong            mListener.onUp(event.getX(), event.getY());
6087f9a62f473a3c57505e2877b0a46ab3cb5e62acAngus Kong        }
6149b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong    }
6249b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong
6349b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong    private class MyGestureListener
6449b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong                extends GestureDetector.SimpleOnGestureListener {
6549b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong        @Override
6649b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong        public boolean onScroll(
6749b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong                MotionEvent e1, MotionEvent e2, float dx, float dy) {
6849b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong            return mListener.onScroll(e2.getX(), e2.getY(), dx, dy);
6949b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong        }
7049b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong
7149b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong        @Override
7249b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
7349b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong                float velocityY) {
7449b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong            return mListener.onFling(velocityX, velocityY);
7549b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong        }
7649b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong
7749b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong        @Override
7849b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong        public boolean onDown(MotionEvent e) {
7949b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong            mListener.onDown(e.getX(), e.getY());
8049b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong            return super.onDown(e);
8149b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong        }
8249b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong    }
8349b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong
84121022cb590955e37f1264f77190ce4711159976Doris Liu    /**
85121022cb590955e37f1264f77190ce4711159976Doris Liu     * The listener that is used to notify when a double-tap or a confirmed
86121022cb590955e37f1264f77190ce4711159976Doris Liu     * single-tap occur.
87121022cb590955e37f1264f77190ce4711159976Doris Liu     */
88121022cb590955e37f1264f77190ce4711159976Doris Liu    private class MyDoubleTapListener implements GestureDetector.OnDoubleTapListener {
89121022cb590955e37f1264f77190ce4711159976Doris Liu
90121022cb590955e37f1264f77190ce4711159976Doris Liu        @Override
91121022cb590955e37f1264f77190ce4711159976Doris Liu        public boolean onSingleTapConfirmed(MotionEvent e) {
92121022cb590955e37f1264f77190ce4711159976Doris Liu            return mListener.onSingleTapUp(e.getX(), e.getY());
93121022cb590955e37f1264f77190ce4711159976Doris Liu        }
94121022cb590955e37f1264f77190ce4711159976Doris Liu
95121022cb590955e37f1264f77190ce4711159976Doris Liu        @Override
96121022cb590955e37f1264f77190ce4711159976Doris Liu        public boolean onDoubleTap(MotionEvent e) {
97121022cb590955e37f1264f77190ce4711159976Doris Liu            return mListener.onDoubleTap(e.getX(), e.getY());
98121022cb590955e37f1264f77190ce4711159976Doris Liu        }
99121022cb590955e37f1264f77190ce4711159976Doris Liu
100121022cb590955e37f1264f77190ce4711159976Doris Liu        @Override
101121022cb590955e37f1264f77190ce4711159976Doris Liu        public boolean onDoubleTapEvent(MotionEvent e) {
102121022cb590955e37f1264f77190ce4711159976Doris Liu            return true;
103121022cb590955e37f1264f77190ce4711159976Doris Liu        }
104121022cb590955e37f1264f77190ce4711159976Doris Liu    }
105121022cb590955e37f1264f77190ce4711159976Doris Liu
10649b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong    private class MyScaleListener
10749b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong            extends ScaleGestureDetector.SimpleOnScaleGestureListener {
10849b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong        @Override
10949b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong        public boolean onScaleBegin(ScaleGestureDetector detector) {
11049b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong            return mListener.onScaleBegin(
11149b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong                    detector.getFocusX(), detector.getFocusY());
11249b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong        }
11349b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong
11449b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong        @Override
11549b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong        public boolean onScale(ScaleGestureDetector detector) {
11649b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong            return mListener.onScale(detector.getFocusX(),
11749b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong                    detector.getFocusY(), detector.getScaleFactor());
11849b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong        }
11949b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong
12049b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong        @Override
12149b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong        public void onScaleEnd(ScaleGestureDetector detector) {
12249b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong            mListener.onScaleEnd();
12349b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong        }
12449b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong    }
12549b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong}
126