1/*
2 * Copyright (C) 2015 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.captureintent;
18
19import com.android.camera.app.CameraAppUI;
20import com.android.camera.async.MainThread;
21import com.android.camera.hardware.HardwareSpec;
22import com.android.camera.ui.CountDownView;
23import com.android.camera.ui.PreviewOverlay;
24import com.android.camera.ui.PreviewStatusListener;
25import com.android.camera.ui.ProgressOverlay;
26import com.android.camera.ui.focus.FocusRing;
27import com.android.camera.util.AndroidServices;
28import com.android.camera.util.Size;
29import com.android.camera2.R;
30
31import android.graphics.Bitmap;
32import android.graphics.Matrix;
33import android.graphics.RectF;
34import android.view.LayoutInflater;
35import android.view.View;
36import android.view.ViewGroup;
37import android.widget.FrameLayout;
38import android.widget.ImageView;
39
40/**
41 * Contains the UI for the ImageCaptureIntentModule.
42 */
43public class CaptureIntentModuleUI {
44    public interface Listener {
45        public void onZoomRatioChanged(float zoomRatio);
46    }
47    private final Listener mListener;
48
49    private final CameraAppUI mAppUI;
50    private final View mRootView;
51    private final PreviewOverlay mPreviewOverlay;
52    private final ProgressOverlay mProgressOverlay;
53    private final FocusRing mFocusRing;
54    private final CountDownView mCountdownView;
55
56    /** The image view to display the captured picture. */
57    private final ImageView mIntentReviewImageView;
58
59    /** The layout rect of the preview. */
60    private RectF mPreviewRect;
61
62    private final PreviewStatusListener.PreviewAreaChangedListener mPreviewAreaChangedListener =
63            new PreviewStatusListener.PreviewAreaChangedListener() {
64                @Override
65                public void onPreviewAreaChanged(RectF previewArea) {
66                    mPreviewRect = previewArea;
67                    mCountdownView.onPreviewAreaChanged(previewArea);
68                    mProgressOverlay.setBounds(previewArea);
69                    FrameLayout.LayoutParams params =
70                            (FrameLayout.LayoutParams) mIntentReviewImageView.getLayoutParams();
71
72                    /**
73                     * WAR for b/19676505: On Nexus 6 / 16:9 / portrait, for
74                     * some reasons the previewArea width is 1345.499999999....
75                     * Use Math.ceil here to make the width 1346.
76                     */
77                    params.width = (int) Math.ceil((double) previewArea.width());
78
79                    params.height = Math.round(previewArea.height());
80                    params.setMargins(
81                            Math.round(previewArea.left), Math.round(previewArea.top), 0, 0);
82                    mIntentReviewImageView.setLayoutParams(params);
83                }
84            };
85
86    public CaptureIntentModuleUI(
87            CameraAppUI appUI, View parent, Listener listener) {
88
89        mAppUI = appUI;
90        mListener = listener;
91        mRootView = parent;
92
93        mIntentReviewImageView = (ImageView) mRootView.findViewById(R.id.intent_review_imageview);
94
95        final LayoutInflater layoutInflater = AndroidServices.instance().provideLayoutInflater();
96
97        ViewGroup moduleRoot = (ViewGroup) mRootView.findViewById(R.id.module_layout);
98        layoutInflater.inflate(R.layout.capture_module, moduleRoot, true);
99
100        mPreviewOverlay = (PreviewOverlay) mRootView.findViewById(R.id.preview_overlay);
101        mProgressOverlay = (ProgressOverlay) mRootView.findViewById(R.id.progress_overlay);
102        mFocusRing = (FocusRing) mRootView.findViewById(R.id.focus_ring);
103        mCountdownView = (CountDownView) mRootView.findViewById(R.id.count_down_view);
104
105        mPreviewRect = new RectF(0, 0, 0, 0);
106    }
107
108    /**
109     * Obtains the current preview layout rect.
110     */
111    public RectF getPreviewRect() {
112        return mPreviewRect;
113    }
114
115    /**
116     * Obtains the current preview layout size.
117     */
118    public Size getPreviewSurfaceSize() {
119        return new Size(mAppUI.getSurfaceWidth(), mAppUI.getSurfaceHeight());
120    }
121
122    /**
123     * Configures the bottom bar UI.
124     *
125     * @param hardwareSpec The hardware spec.
126     * @param bottomBarSpec The bottom bar spec.
127     */
128    public void applyModuleSpecs(
129            HardwareSpec hardwareSpec,
130            CameraAppUI.BottomBarUISpec bottomBarSpec) {
131        MainThread.checkMainThread();
132        mAppUI.applyModuleSpecs(hardwareSpec, bottomBarSpec);
133    }
134
135    /**
136     * Called when the module got resumed.
137     */
138    public void onModuleResumed() {
139        MainThread.checkMainThread();
140        // Listen to preview layout change event. Adjust review image view
141        // layout to match preview layout.
142        //
143        // Doing this here rather than in ctor is because TextureViewHelper
144        // doesn't exist until the module got initialized.
145        mAppUI.addPreviewAreaChangedListener(mPreviewAreaChangedListener);
146    }
147
148    /**
149     * Called when the module got paused.
150     */
151    public void onModulePaused() {
152        MainThread.checkMainThread();
153        mAppUI.removePreviewAreaChangedListener(mPreviewAreaChangedListener);
154    }
155
156    /**
157     * Update preview transform matrix.
158     *
159     * @param matrix The preview transform matrix.
160     */
161    public void updatePreviewTransform(Matrix matrix) {
162        MainThread.checkMainThread();
163        mAppUI.updatePreviewTransform(matrix);
164    }
165
166    /**
167     * Update preview aspect ratio.
168     *
169     * This is useful only when TextureViewHelper auto transform is enabled.
170     *
171     * @param aspectRatio The preview aspect ratio.
172     */
173    public void updatePreviewAspectRatio(float aspectRatio) {
174        MainThread.checkMainThread();
175        mAppUI.updatePreviewAspectRatio(aspectRatio);
176    }
177
178    /**
179     * Called when the preview is started.
180     */
181    public void onPreviewStarted() {
182        MainThread.checkMainThread();
183        mAppUI.onPreviewStarted();
184    }
185
186    /**
187     * Enables zoom UI, setting maximum zoom.
188     * Called from Module when camera is available.
189     *
190     * @param maxZoom maximum zoom value.
191     */
192    public void initializeZoom(float maxZoom) {
193        MainThread.checkMainThread();
194        mPreviewOverlay.setupZoom(maxZoom, 0, mZoomChancedListener);
195    }
196
197    public FocusRing getFocusRing() {
198        return mFocusRing;
199    }
200
201    public void setShutterButtonEnabled(boolean enabled) {
202        MainThread.checkMainThread();
203        mAppUI.setShutterButtonEnabled(enabled);
204    }
205
206    public void startFlashAnimation(boolean shortFlash) {
207        MainThread.checkMainThread();
208        mAppUI.startFlashAnimation(shortFlash);
209    }
210
211    /**
212     * Starts the countdown timer.
213     *
214     * @param sec seconds to countdown
215     */
216    public void startCountdown(int sec) {
217        MainThread.checkMainThread();
218        mAppUI.transitionToCancel();
219        mCountdownView.startCountDown(sec);
220    }
221
222    /**
223     * Cancels the on-going countdown, if any.
224     */
225    public void cancelCountDown() {
226        mCountdownView.cancelCountDown();
227    }
228
229    /**
230     * Sets a listener that gets notified when the countdown is finished.
231     */
232    public void setCountdownFinishedListener(CountDownView.OnCountDownStatusListener listener) {
233        mCountdownView.setCountDownStatusListener(listener);
234    }
235
236    /**
237     * Transition to the UI where users can review the taken photo.
238     *
239     * @param reviewPictureBitmap The picture bitmap to be shown.
240     */
241    public void showPictureReviewUI(Bitmap reviewPictureBitmap) {
242        MainThread.checkMainThread();
243
244        mIntentReviewImageView.setImageBitmap(reviewPictureBitmap);
245        mIntentReviewImageView.setVisibility(View.VISIBLE);
246
247        mAppUI.transitionToIntentReviewLayout();
248        mAppUI.hideModeOptions();
249        mAppUI.disableModeOptions();
250        mAppUI.setShutterButtonEnabled(false);
251    }
252
253    /**
254     * Transition to the UI where users can take a photo.
255     */
256    public void showPictureCaptureUI() {
257        MainThread.checkMainThread();
258
259        mIntentReviewImageView.setVisibility(View.INVISIBLE);
260        mIntentReviewImageView.setImageBitmap(null);
261
262        mAppUI.transitionToIntentCaptureLayout();
263        mAppUI.syncModeOptionIndicators();
264        mAppUI.enableModeOptions();
265        mAppUI.showModeOptions();
266        mAppUI.setShutterButtonEnabled(true);
267        mAppUI.setShouldSuppressCaptureIndicator(true);
268    }
269
270    public void freezeScreenUntilPreviewReady() {
271        MainThread.checkMainThread();
272        mAppUI.freezeScreenUntilPreviewReady();
273    }
274
275    /** Set up listener to receive zoom changes from View and send to module. */
276    private final PreviewOverlay.OnZoomChangedListener mZoomChancedListener =
277            new PreviewOverlay.OnZoomChangedListener() {
278        @Override
279        public void onZoomValueChanged(float ratio) {
280            mListener.onZoomRatioChanged(ratio);
281        }
282
283        @Override
284        public void onZoomStart() {
285        }
286
287        @Override
288        public void onZoomEnd() {
289        }
290    };
291}
292