108b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling/*
208b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling * Copyright (C) 2014 The Android Open Source Project
308b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling *
408b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling * Licensed under the Apache License, Version 2.0 (the "License");
508b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling * you may not use this file except in compliance with the License.
608b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling * You may obtain a copy of the License at
708b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling *
808b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling *      http://www.apache.org/licenses/LICENSE-2.0
908b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling *
1008b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling * Unless required by applicable law or agreed to in writing, software
1108b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling * distributed under the License is distributed on an "AS IS" BASIS,
1208b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1308b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling * See the License for the specific language governing permissions and
1408b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling * limitations under the License.
1508b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling */
1608b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling
1708b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberlingpackage com.android.camera;
1808b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling
1908b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberlingimport android.graphics.Bitmap;
2008b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberlingimport android.graphics.Matrix;
2108b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberlingimport android.graphics.RectF;
2208b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberlingimport android.view.TextureView;
2308b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberlingimport android.view.View;
2408b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberlingimport android.view.ViewGroup;
2508b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling
2626b3334755ffccc039249005435d5cc598d0689eAndy Huibersimport com.android.camera.debug.Log;
27a31162ce3ab4f9c68e46658b16b2c49f4dc0d145Andy Huibersimport com.android.camera.ui.CountDownView;
2826b3334755ffccc039249005435d5cc598d0689eAndy Huibersimport com.android.camera.ui.PreviewOverlay;
2926b3334755ffccc039249005435d5cc598d0689eAndy Huibersimport com.android.camera.ui.PreviewOverlay.OnZoomChangedListener;
3008b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberlingimport com.android.camera.ui.PreviewStatusListener;
3108b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberlingimport com.android.camera.ui.ProgressOverlay;
32987ee64612e2510004fdf08536746c87234d01c1Paul Rohdeimport com.android.camera.ui.focus.FocusRing;
3308b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberlingimport com.android.camera2.R;
3408b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling
3508b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling/**
3608b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling * Contains the UI for the CaptureModule.
3708b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling */
388e8d3088e057df3a866e67b6d20ec950f9d4e4f6Senpo Hupublic class CaptureModuleUI implements PreviewStatusListener.PreviewAreaChangedListener {
398e8d3088e057df3a866e67b6d20ec950f9d4e4f6Senpo Hu
408e8d3088e057df3a866e67b6d20ec950f9d4e4f6Senpo Hu    public interface CaptureModuleUIListener {
418e8d3088e057df3a866e67b6d20ec950f9d4e4f6Senpo Hu        public void onZoomRatioChanged(float zoomRatio);
428e8d3088e057df3a866e67b6d20ec950f9d4e4f6Senpo Hu    }
4308b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling
4426b3334755ffccc039249005435d5cc598d0689eAndy Huibers    private static final Log.Tag TAG = new Log.Tag("CaptureModuleUI");
4526b3334755ffccc039249005435d5cc598d0689eAndy Huibers
4608b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling    private final CameraActivity mActivity;
478e8d3088e057df3a866e67b6d20ec950f9d4e4f6Senpo Hu    private final CaptureModuleUIListener mListener;
4808b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling    private final View mRootView;
4908b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling
5026b3334755ffccc039249005435d5cc598d0689eAndy Huibers    private final PreviewOverlay mPreviewOverlay;
5108b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling    private final ProgressOverlay mProgressOverlay;
5208b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling    private final TextureView mPreviewView;
5308b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling
54987ee64612e2510004fdf08536746c87234d01c1Paul Rohde    private final FocusRing mFocusRing;
55a31162ce3ab4f9c68e46658b16b2c49f4dc0d145Andy Huibers    private final CountDownView mCountdownView;
56a31162ce3ab4f9c68e46658b16b2c49f4dc0d145Andy Huibers
5708b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling    private int mPreviewAreaWidth;
5808b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling    private int mPreviewAreaHeight;
5908b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling
6026b3334755ffccc039249005435d5cc598d0689eAndy Huibers    /** Maximum zoom; intialize to 1.0 (disabled) */
6126b3334755ffccc039249005435d5cc598d0689eAndy Huibers    private float mMaxZoom = 1f;
6226b3334755ffccc039249005435d5cc598d0689eAndy Huibers
6326b3334755ffccc039249005435d5cc598d0689eAndy Huibers    /** Set up listener to receive zoom changes from View and send to module. */
64971ad50c0f220a396ffce50245617ff59ed0a09ezafir    private final OnZoomChangedListener mZoomChangedListener = new OnZoomChangedListener() {
6526b3334755ffccc039249005435d5cc598d0689eAndy Huibers        @Override
662192fbaaf598d4440a8d537a70095ea56bc9a5ebSol Boucher        public void onZoomValueChanged(float ratio) {
678e8d3088e057df3a866e67b6d20ec950f9d4e4f6Senpo Hu            mListener.onZoomRatioChanged(ratio);
6826b3334755ffccc039249005435d5cc598d0689eAndy Huibers        }
6926b3334755ffccc039249005435d5cc598d0689eAndy Huibers
7026b3334755ffccc039249005435d5cc598d0689eAndy Huibers        @Override
7126b3334755ffccc039249005435d5cc598d0689eAndy Huibers        public void onZoomStart() {
7226b3334755ffccc039249005435d5cc598d0689eAndy Huibers        }
7326b3334755ffccc039249005435d5cc598d0689eAndy Huibers
7426b3334755ffccc039249005435d5cc598d0689eAndy Huibers        @Override
7526b3334755ffccc039249005435d5cc598d0689eAndy Huibers        public void onZoomEnd() {
7626b3334755ffccc039249005435d5cc598d0689eAndy Huibers        }
7726b3334755ffccc039249005435d5cc598d0689eAndy Huibers    };
7826b3334755ffccc039249005435d5cc598d0689eAndy Huibers
798e8d3088e057df3a866e67b6d20ec950f9d4e4f6Senpo Hu    public CaptureModuleUI(CameraActivity activity, View parent, CaptureModuleUIListener listener) {
8008b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling        mActivity = activity;
818e8d3088e057df3a866e67b6d20ec950f9d4e4f6Senpo Hu        mListener = listener;
8208b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling        mRootView = parent;
8308b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling
8408b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling        ViewGroup moduleRoot = (ViewGroup) mRootView.findViewById(R.id.module_layout);
852272f8a6bfc8adca8ada7a215bef038d45256085Senpo Hu        mActivity.getLayoutInflater().inflate(R.layout.capture_module, moduleRoot, true);
8608b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling
8708b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling        mPreviewView = (TextureView) mRootView.findViewById(R.id.preview_content);
8808b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling
8926b3334755ffccc039249005435d5cc598d0689eAndy Huibers        mPreviewOverlay = (PreviewOverlay) mRootView.findViewById(R.id.preview_overlay);
9008b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling        mProgressOverlay = (ProgressOverlay) mRootView.findViewById(R.id.progress_overlay);
9108b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling
92987ee64612e2510004fdf08536746c87234d01c1Paul Rohde        mFocusRing = (FocusRing) mRootView.findViewById(R.id.focus_ring);
93a31162ce3ab4f9c68e46658b16b2c49f4dc0d145Andy Huibers        mCountdownView = (CountDownView) mRootView.findViewById(R.id.count_down_view);
9408b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling    }
9508b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling
9608b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling    /**
9708b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling     * Getter for the width of the visible area of the preview.
9808b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling     */
9908b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling    public int getPreviewAreaWidth() {
10008b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling        return mPreviewAreaWidth;
10108b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling    }
10208b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling
10308b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling    /**
10408b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling     * Getter for the height of the visible area of the preview.
10508b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling     */
10608b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling    public int getPreviewAreaHeight() {
10708b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling        return mPreviewAreaHeight;
10808b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling    }
10908b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling
11008b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling    public Matrix getPreviewTransform(Matrix m) {
11108b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling        return mPreviewView.getTransform(m);
11208b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling    }
11308b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling
114987ee64612e2510004fdf08536746c87234d01c1Paul Rohde    public FocusRing getFocusRing() {
115987ee64612e2510004fdf08536746c87234d01c1Paul Rohde        return mFocusRing;
116ca3c564536f154b83e380e37382bc7b9f6049302Andy Huibers    }
117ca3c564536f154b83e380e37382bc7b9f6049302Andy Huibers
118ca3c564536f154b83e380e37382bc7b9f6049302Andy Huibers    public void showDebugMessage(String message) {
119987ee64612e2510004fdf08536746c87234d01c1Paul Rohde        /* NoOp */
12008b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling    }
12126b3334755ffccc039249005435d5cc598d0689eAndy Huibers
12208b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling    /**
123a31162ce3ab4f9c68e46658b16b2c49f4dc0d145Andy Huibers     * Starts the countdown timer.
124a31162ce3ab4f9c68e46658b16b2c49f4dc0d145Andy Huibers     *
125a31162ce3ab4f9c68e46658b16b2c49f4dc0d145Andy Huibers     * @param sec seconds to countdown
126a31162ce3ab4f9c68e46658b16b2c49f4dc0d145Andy Huibers     */
127a31162ce3ab4f9c68e46658b16b2c49f4dc0d145Andy Huibers    public void startCountdown(int sec) {
128a31162ce3ab4f9c68e46658b16b2c49f4dc0d145Andy Huibers        mCountdownView.startCountDown(sec);
129a31162ce3ab4f9c68e46658b16b2c49f4dc0d145Andy Huibers    }
130a31162ce3ab4f9c68e46658b16b2c49f4dc0d145Andy Huibers
131a31162ce3ab4f9c68e46658b16b2c49f4dc0d145Andy Huibers    /**
132a31162ce3ab4f9c68e46658b16b2c49f4dc0d145Andy Huibers     * Sets a listener that gets notified when the countdown is finished.
133a31162ce3ab4f9c68e46658b16b2c49f4dc0d145Andy Huibers     */
134a31162ce3ab4f9c68e46658b16b2c49f4dc0d145Andy Huibers    public void setCountdownFinishedListener(CountDownView.OnCountDownStatusListener listener) {
135a31162ce3ab4f9c68e46658b16b2c49f4dc0d145Andy Huibers        mCountdownView.setCountDownStatusListener(listener);
136a31162ce3ab4f9c68e46658b16b2c49f4dc0d145Andy Huibers    }
137a31162ce3ab4f9c68e46658b16b2c49f4dc0d145Andy Huibers
138a31162ce3ab4f9c68e46658b16b2c49f4dc0d145Andy Huibers    /**
139a31162ce3ab4f9c68e46658b16b2c49f4dc0d145Andy Huibers     * Returns whether the countdown is on-going.
140a31162ce3ab4f9c68e46658b16b2c49f4dc0d145Andy Huibers     */
141a31162ce3ab4f9c68e46658b16b2c49f4dc0d145Andy Huibers    public boolean isCountingDown() {
142a31162ce3ab4f9c68e46658b16b2c49f4dc0d145Andy Huibers        return mCountdownView.isCountingDown();
143a31162ce3ab4f9c68e46658b16b2c49f4dc0d145Andy Huibers    }
144a31162ce3ab4f9c68e46658b16b2c49f4dc0d145Andy Huibers
145a31162ce3ab4f9c68e46658b16b2c49f4dc0d145Andy Huibers    /**
146a31162ce3ab4f9c68e46658b16b2c49f4dc0d145Andy Huibers     * Cancels the on-going countdown, if any.
147a31162ce3ab4f9c68e46658b16b2c49f4dc0d145Andy Huibers     */
148a31162ce3ab4f9c68e46658b16b2c49f4dc0d145Andy Huibers    public void cancelCountDown() {
149a31162ce3ab4f9c68e46658b16b2c49f4dc0d145Andy Huibers        mCountdownView.cancelCountDown();
150a31162ce3ab4f9c68e46658b16b2c49f4dc0d145Andy Huibers    }
151a31162ce3ab4f9c68e46658b16b2c49f4dc0d145Andy Huibers
152a31162ce3ab4f9c68e46658b16b2c49f4dc0d145Andy Huibers    /**
15308b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling     * Sets the progress of the gcam picture taking.
15408b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling     *
15508b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling     * @param percent amount of process done in percent 0-100.
15608b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling     */
15708b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling    public void setPictureTakingProgress(int percent) {
15808b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling        mProgressOverlay.setProgress(percent);
15908b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling    }
16008b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling
16108b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling    public Bitmap getBitMapFromPreview() {
16208b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling        Matrix m = new Matrix();
16308b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling        m = getPreviewTransform(m);
16408b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling        Bitmap src = mPreviewView.getBitmap();
16508b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling        return Bitmap.createBitmap(src, 0, 0, src.getWidth(), src.getHeight(), m, true);
16608b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling    }
16726b3334755ffccc039249005435d5cc598d0689eAndy Huibers
16826b3334755ffccc039249005435d5cc598d0689eAndy Huibers    /**
16926b3334755ffccc039249005435d5cc598d0689eAndy Huibers     * Enables zoom UI, setting maximum zoom.
17026b3334755ffccc039249005435d5cc598d0689eAndy Huibers     * Called from Module when camera is available.
17126b3334755ffccc039249005435d5cc598d0689eAndy Huibers     *
17226b3334755ffccc039249005435d5cc598d0689eAndy Huibers     * @param maxZoom maximum zoom value.
17326b3334755ffccc039249005435d5cc598d0689eAndy Huibers     */
17426b3334755ffccc039249005435d5cc598d0689eAndy Huibers    public void initializeZoom(float maxZoom) {
17526b3334755ffccc039249005435d5cc598d0689eAndy Huibers        mMaxZoom = maxZoom;
176971ad50c0f220a396ffce50245617ff59ed0a09ezafir        mPreviewOverlay.setupZoom(mMaxZoom, 0, mZoomChangedListener);
17726b3334755ffccc039249005435d5cc598d0689eAndy Huibers    }
1788e8d3088e057df3a866e67b6d20ec950f9d4e4f6Senpo Hu
1798e8d3088e057df3a866e67b6d20ec950f9d4e4f6Senpo Hu    @Override
1808e8d3088e057df3a866e67b6d20ec950f9d4e4f6Senpo Hu    public void onPreviewAreaChanged(RectF previewArea) {
1818e8d3088e057df3a866e67b6d20ec950f9d4e4f6Senpo Hu        // TODO: mFaceView.onPreviewAreaChanged(previewArea);
1828e8d3088e057df3a866e67b6d20ec950f9d4e4f6Senpo Hu        mCountdownView.onPreviewAreaChanged(previewArea);
1838e8d3088e057df3a866e67b6d20ec950f9d4e4f6Senpo Hu        mProgressOverlay.setBounds(previewArea);
1848e8d3088e057df3a866e67b6d20ec950f9d4e4f6Senpo Hu    }
18508b3c94a7d7aff30b5da8e99649346e37b67a5c5Sascha Haeberling}
186