1/*
2 * Copyright (C) 2014 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.camera;
18
19import android.graphics.Bitmap;
20import android.graphics.Matrix;
21import android.graphics.RectF;
22import android.graphics.SurfaceTexture;
23import android.view.GestureDetector;
24import android.view.MotionEvent;
25import android.view.TextureView;
26import android.view.View;
27import android.view.ViewGroup;
28
29import com.android.camera.debug.Log;
30import com.android.camera.ui.CountDownView;
31import com.android.camera.ui.PreviewOverlay;
32import com.android.camera.ui.PreviewOverlay.OnZoomChangedListener;
33import com.android.camera.ui.PreviewStatusListener;
34import com.android.camera.ui.ProgressOverlay;
35import com.android.camera2.R;
36
37/**
38 * Contains the UI for the CaptureModule.
39 */
40public class CaptureModuleUI implements
41        PreviewStatusListener {
42
43    private static final Log.Tag TAG = new Log.Tag("CaptureModuleUI");
44
45    private final CameraActivity mActivity;
46    private final CaptureModule mModule;
47    private final View mRootView;
48
49    private final PreviewOverlay mPreviewOverlay;
50    private final ProgressOverlay mProgressOverlay;
51    private final View.OnLayoutChangeListener mLayoutListener;
52    private final TextureView mPreviewView;
53
54    private final GestureDetector.OnGestureListener mPreviewGestureListener = new GestureDetector.SimpleOnGestureListener() {
55        @Override
56        public boolean onSingleTapUp(MotionEvent ev) {
57            mModule.onSingleTapUp(null, (int) ev.getX(), (int) ev.getY());
58            return true;
59        }
60    };
61    private final FocusOverlayManager.FocusUI mFocusUI;
62    private final CountDownView mCountdownView;
63
64    private int mPreviewAreaWidth;
65    private int mPreviewAreaHeight;
66
67    /** Maximum zoom; intialize to 1.0 (disabled) */
68    private float mMaxZoom = 1f;
69
70    /** Set up listener to receive zoom changes from View and send to module. */
71    private final OnZoomChangedListener mZoomChancedListener  = new OnZoomChangedListener() {
72        @Override
73        public void onZoomValueChanged(float ratio) {
74            mModule.setZoom(ratio);
75        }
76
77        @Override
78        public void onZoomStart() {
79        }
80
81        @Override
82        public void onZoomEnd() {
83        }
84    };
85
86    public void onPreviewAreaChanged(RectF previewArea) {
87        // TODO: mFaceView.onPreviewAreaChanged(previewArea);
88        mCountdownView.onPreviewAreaChanged(previewArea);
89    }
90
91    @Override
92    public void onPreviewLayoutChanged(View v, int left, int top, int right,
93            int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
94        if (mLayoutListener != null) {
95            mLayoutListener.onLayoutChange(v, left, top, right, bottom, oldLeft, oldTop, oldRight,
96                    oldBottom);
97        }
98    }
99
100    @Override
101    public boolean shouldAutoAdjustTransformMatrixOnLayout() {
102        return false;
103    }
104
105    @Override
106    public boolean shouldAutoAdjustBottomBar() {
107        return true;
108    }
109
110    @Override
111    public void onPreviewFlipped() {
112        // Do nothing because when preview is flipped, TextureView will lay
113        // itself out again, which will then trigger a transform matrix update.
114    }
115
116    @Override
117    public GestureDetector.OnGestureListener getGestureListener() {
118        return mPreviewGestureListener;
119    }
120
121    @Override
122    public View.OnTouchListener getTouchListener() {
123        return null;
124    }
125
126    public CaptureModuleUI(CameraActivity activity, CaptureModule module, View parent,
127            View.OnLayoutChangeListener layoutListener) {
128        mActivity = activity;
129        mModule = module;
130        mRootView = parent;
131        mLayoutListener = layoutListener;
132
133        ViewGroup moduleRoot = (ViewGroup) mRootView.findViewById(R.id.module_layout);
134        mActivity.getLayoutInflater().inflate(R.layout.capture_module,
135                moduleRoot, true);
136
137        mPreviewView = (TextureView) mRootView.findViewById(R.id.preview_content);
138
139        mPreviewOverlay = (PreviewOverlay) mRootView.findViewById(R.id.preview_overlay);
140        mProgressOverlay = (ProgressOverlay) mRootView.findViewById(R.id.progress_overlay);
141
142        mFocusUI = (FocusOverlayManager.FocusUI) mRootView.findViewById(R.id.focus_overlay);
143        mCountdownView = (CountDownView) mRootView.findViewById(R.id.count_down_view);
144    }
145
146    @Override
147    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
148        mModule.onSurfaceTextureAvailable(surface, width, height);
149    }
150
151    @Override
152    public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
153        return mModule.onSurfaceTextureDestroyed(surface);
154    }
155
156    @Override
157    public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
158        mModule.onSurfaceTextureSizeChanged(surface, width, height);
159    }
160
161    @Override
162    public void onSurfaceTextureUpdated(SurfaceTexture surface) {
163        mModule.onSurfaceTextureUpdated(surface);
164    }
165
166    public void positionProgressOverlay(RectF area) {
167        mProgressOverlay.setBounds(area);
168    }
169
170    /**
171     * Getter for the width of the visible area of the preview.
172     */
173    public int getPreviewAreaWidth() {
174        return mPreviewAreaWidth;
175    }
176
177    /**
178     * Getter for the height of the visible area of the preview.
179     */
180    public int getPreviewAreaHeight() {
181        return mPreviewAreaHeight;
182    }
183
184    public Matrix getPreviewTransform(Matrix m) {
185        return mPreviewView.getTransform(m);
186    }
187
188    public void showAutoFocusInProgress() {
189        mFocusUI.onFocusStarted();
190    }
191
192    public void showAutoFocusSuccess() {
193        mFocusUI.onFocusSucceeded();
194    }
195
196    public void showAutoFocusFailure() {
197        mFocusUI.onFocusFailed();
198    }
199
200    public void setPassiveFocusSuccess(boolean success) {
201        mFocusUI.setPassiveFocusSuccess(success);
202    }
203
204    public void showDebugMessage(String message) {
205        mFocusUI.showDebugMessage(message);
206    }
207
208    public void setAutoFocusTarget(int x, int y, boolean isPassiveScan, int afSize, int aeSize) {
209        mFocusUI.setFocusPosition(x, y, isPassiveScan, afSize, aeSize);
210    }
211
212    public void clearAutoFocusIndicator() {
213        mFocusUI.clearFocus();
214    }
215
216    public void clearAutoFocusIndicator(boolean waitUntilProgressIsHidden) {
217    }
218
219    /**
220     * Starts the countdown timer.
221     *
222     * @param sec seconds to countdown
223     */
224    public void startCountdown(int sec) {
225        mCountdownView.startCountDown(sec);
226    }
227
228    /**
229     * Sets a listener that gets notified when the countdown is finished.
230     */
231    public void setCountdownFinishedListener(CountDownView.OnCountDownStatusListener listener) {
232        mCountdownView.setCountDownStatusListener(listener);
233    }
234
235    /**
236     * Returns whether the countdown is on-going.
237     */
238    public boolean isCountingDown() {
239        return mCountdownView.isCountingDown();
240    }
241
242    /**
243     * Cancels the on-going countdown, if any.
244     */
245    public void cancelCountDown() {
246        mCountdownView.cancelCountDown();
247    }
248
249    /**
250     * Sets the progress of the gcam picture taking.
251     *
252     * @param percent amount of process done in percent 0-100.
253     */
254    public void setPictureTakingProgress(int percent) {
255        mProgressOverlay.setProgress(percent);
256    }
257
258    public Bitmap getBitMapFromPreview() {
259        Matrix m = new Matrix();
260        m = getPreviewTransform(m);
261        Bitmap src = mPreviewView.getBitmap();
262        return Bitmap.createBitmap(src, 0, 0, src.getWidth(), src.getHeight(), m, true);
263    }
264
265    /**
266     * Enables zoom UI, setting maximum zoom.
267     * Called from Module when camera is available.
268     *
269     * @param maxZoom maximum zoom value.
270     */
271    public void initializeZoom(float maxZoom) {
272        mMaxZoom = maxZoom;
273        mPreviewOverlay.setupZoom(mMaxZoom, 0, mZoomChancedListener);
274    }
275}
276