summaryrefslogtreecommitdiffstats
path: root/src/com/android/camera/WideAnglePanoramaUI.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/camera/WideAnglePanoramaUI.java')
-rw-r--r--src/com/android/camera/WideAnglePanoramaUI.java461
1 files changed, 461 insertions, 0 deletions
diff --git a/src/com/android/camera/WideAnglePanoramaUI.java b/src/com/android/camera/WideAnglePanoramaUI.java
new file mode 100644
index 000000000..0ce9d62dc
--- /dev/null
+++ b/src/com/android/camera/WideAnglePanoramaUI.java
@@ -0,0 +1,461 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.camera;
+
+import android.app.AlertDialog;
+import android.app.ProgressDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Matrix;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.graphics.SurfaceTexture;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.TextureView;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.android.camera.ui.CameraControls;
+import com.android.camera.ui.CameraRootView;
+import com.android.camera.ui.ModuleSwitcher;
+import com.android.camera2.R;
+
+/**
+ * The UI of {@link WideAnglePanoramaModule}.
+ */
+public class WideAnglePanoramaUI implements
+ TextureView.SurfaceTextureListener,
+ ShutterButton.OnShutterButtonListener,
+ View.OnLayoutChangeListener {
+
+ @SuppressWarnings("unused")
+ private static final String TAG = "CAM_WidePanoramaUI";
+
+ private CameraActivity mActivity;
+ private WideAnglePanoramaController mController;
+
+ private ViewGroup mRootView;
+ private ModuleSwitcher mSwitcher;
+ private ViewGroup mPanoLayout;
+ private FrameLayout mCaptureLayout;
+ private View mReviewLayout;
+ private ImageView mReview;
+ private View mPreviewBorder;
+ private View mLeftIndicator;
+ private View mRightIndicator;
+ private View mCaptureIndicator;
+ private PanoProgressBar mCaptureProgressBar;
+ private PanoProgressBar mSavingProgressBar;
+ private TextView mTooFastPrompt;
+ private TextureView mTextureView;
+ private ShutterButton mShutterButton;
+ private CameraControls mCameraControls;
+
+ private Matrix mProgressDirectionMatrix = new Matrix();
+ private float[] mProgressAngle = new float[2];
+
+ private DialogHelper mDialogHelper;
+
+ // Color definitions.
+ private int mIndicatorColor;
+ private int mIndicatorColorFast;
+ private int mReviewBackground;
+ private SurfaceTexture mSurfaceTexture;
+
+ /** Constructor. */
+ public WideAnglePanoramaUI(
+ CameraActivity activity,
+ WideAnglePanoramaController controller,
+ ViewGroup root) {
+ mActivity = activity;
+ mController = controller;
+ mRootView = root;
+
+ createContentView();
+ mSwitcher = (ModuleSwitcher) mRootView.findViewById(R.id.camera_switcher);
+ Log.v(TAG, "setting CurrentIndex:" + ModuleSwitcher.WIDE_ANGLE_PANO_MODULE_INDEX);
+ mSwitcher.setCurrentIndex(ModuleSwitcher.WIDE_ANGLE_PANO_MODULE_INDEX);
+ mSwitcher.setSwitchListener(mActivity);
+ }
+
+ public void onStartCapture() {
+ hideSwitcher();
+ mShutterButton.setImageResource(R.drawable.btn_shutter_recording);
+ mCaptureIndicator.setVisibility(View.VISIBLE);
+ showDirectionIndicators(PanoProgressBar.DIRECTION_NONE);
+ }
+
+ public void showPreviewUI() {
+ mCaptureLayout.setVisibility(View.VISIBLE);
+ showUI();
+ }
+
+ public void onStopCapture() {
+ mCaptureIndicator.setVisibility(View.INVISIBLE);
+ hideTooFastIndication();
+ hideDirectionIndicators();
+ }
+
+ public void hideSwitcher() {
+ mSwitcher.closePopup();
+ mSwitcher.setVisibility(View.INVISIBLE);
+ }
+
+ public void hideUI() {
+ hideSwitcher();
+ mCameraControls.setVisibility(View.INVISIBLE);
+ }
+
+ public void showUI() {
+ showSwitcher();
+ mCameraControls.setVisibility(View.VISIBLE);
+ }
+
+ public void showSwitcher() {
+ mSwitcher.setVisibility(View.VISIBLE);
+ }
+
+ public void setCaptureProgressOnDirectionChangeListener(
+ PanoProgressBar.OnDirectionChangeListener listener) {
+ mCaptureProgressBar.setOnDirectionChangeListener(listener);
+ }
+
+ public void resetCaptureProgress() {
+ mCaptureProgressBar.reset();
+ }
+
+ public void setMaxCaptureProgress(int max) {
+ mCaptureProgressBar.setMaxProgress(max);
+ }
+
+ public void showCaptureProgress() {
+ mCaptureProgressBar.setVisibility(View.VISIBLE);
+ }
+
+ public void updateCaptureProgress(
+ float panningRateXInDegree, float panningRateYInDegree,
+ float progressHorizontalAngle, float progressVerticalAngle,
+ float maxPanningSpeed) {
+
+ if ((Math.abs(panningRateXInDegree) > maxPanningSpeed)
+ || (Math.abs(panningRateYInDegree) > maxPanningSpeed)) {
+ showTooFastIndication();
+ } else {
+ hideTooFastIndication();
+ }
+
+ // progressHorizontalAngle and progressVerticalAngle are relative to the
+ // camera. Convert them to UI direction.
+ mProgressAngle[0] = progressHorizontalAngle;
+ mProgressAngle[1] = progressVerticalAngle;
+ mProgressDirectionMatrix.mapPoints(mProgressAngle);
+
+ int angleInMajorDirection =
+ (Math.abs(mProgressAngle[0]) > Math.abs(mProgressAngle[1]))
+ ? (int) mProgressAngle[0]
+ : (int) mProgressAngle[1];
+ mCaptureProgressBar.setProgress((angleInMajorDirection));
+ }
+
+ public void setProgressOrientation(int orientation) {
+ mProgressDirectionMatrix.reset();
+ mProgressDirectionMatrix.postRotate(orientation);
+ }
+
+ public void showDirectionIndicators(int direction) {
+ switch (direction) {
+ case PanoProgressBar.DIRECTION_NONE:
+ mLeftIndicator.setVisibility(View.VISIBLE);
+ mRightIndicator.setVisibility(View.VISIBLE);
+ break;
+ case PanoProgressBar.DIRECTION_LEFT:
+ mLeftIndicator.setVisibility(View.VISIBLE);
+ mRightIndicator.setVisibility(View.INVISIBLE);
+ break;
+ case PanoProgressBar.DIRECTION_RIGHT:
+ mLeftIndicator.setVisibility(View.INVISIBLE);
+ mRightIndicator.setVisibility(View.VISIBLE);
+ break;
+ }
+ }
+
+ public SurfaceTexture getSurfaceTexture() {
+ return mSurfaceTexture;
+ }
+
+ @Override
+ public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int i, int i2) {
+ mSurfaceTexture = surfaceTexture;
+ mController.onPreviewUIReady();
+ }
+
+ @Override
+ public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int i, int i2) {
+
+ }
+
+ @Override
+ public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
+ mController.onPreviewUIDestroyed();
+ mSurfaceTexture = null;
+ Log.d(TAG, "surfaceTexture is destroyed");
+ return true;
+ }
+
+ @Override
+ public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {
+ }
+
+ private void hideDirectionIndicators() {
+ mLeftIndicator.setVisibility(View.INVISIBLE);
+ mRightIndicator.setVisibility(View.INVISIBLE);
+ }
+
+ public Point getPreviewAreaSize() {
+ return new Point(
+ mTextureView.getWidth(), mTextureView.getHeight());
+ }
+
+ public void reset() {
+ mShutterButton.setImageResource(R.drawable.btn_new_shutter);
+ mReviewLayout.setVisibility(View.GONE);
+ mCaptureProgressBar.setVisibility(View.INVISIBLE);
+ }
+
+ public void showFinalMosaic(Bitmap bitmap, int orientation) {
+ if (bitmap != null && orientation != 0) {
+ Matrix rotateMatrix = new Matrix();
+ rotateMatrix.setRotate(orientation);
+ bitmap = Bitmap.createBitmap(
+ bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(),
+ rotateMatrix, false);
+ }
+
+ mReview.setImageBitmap(bitmap);
+ mCaptureLayout.setVisibility(View.GONE);
+ mReviewLayout.setVisibility(View.VISIBLE);
+ }
+
+ public void onConfigurationChanged(
+ Configuration newConfig, boolean threadRunning) {
+ Drawable lowResReview = null;
+ if (threadRunning) lowResReview = mReview.getDrawable();
+
+ // Change layout in response to configuration change
+ /* TODO (shkong):mCaptureLayout.setOrientation(
+ newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE
+ ? LinearLayout.HORIZONTAL : LinearLayout.VERTICAL);*/
+ LayoutInflater inflater = (LayoutInflater)
+ mActivity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+
+ mPanoLayout.removeView(mReviewLayout);
+ inflater.inflate(R.layout.pano_module_review, mPanoLayout);
+
+ mPanoLayout.bringChildToFront(mCameraControls);
+ setViews(mActivity.getResources());
+ if (threadRunning) {
+ mReview.setImageDrawable(lowResReview);
+ mCaptureLayout.setVisibility(View.GONE);
+ mReviewLayout.setVisibility(View.VISIBLE);
+ }
+ }
+
+ public void resetSavingProgress() {
+ mSavingProgressBar.reset();
+ mSavingProgressBar.setRightIncreasing(true);
+ }
+
+ public void updateSavingProgress(int progress) {
+ mSavingProgressBar.setProgress(progress);
+ }
+
+ @Override
+ public void onShutterButtonFocus(boolean pressed) {
+ // Do nothing.
+ }
+
+ @Override
+ public void onShutterButtonClick() {
+ mController.onShutterButtonClick();
+ }
+
+ @Override
+ public void onLayoutChange(
+ View v, int l, int t, int r, int b,
+ int oldl, int oldt, int oldr, int oldb) {
+ mController.onPreviewUILayoutChange(l, t, r, b);
+ }
+
+ public void showAlertDialog(
+ String title, String failedString,
+ String OKString, Runnable runnable) {
+ mDialogHelper.showAlertDialog(title, failedString, OKString, runnable);
+ }
+
+ public void showWaitingDialog(String title) {
+ mDialogHelper.showWaitingDialog(title);
+ }
+
+ public void dismissAllDialogs() {
+ mDialogHelper.dismissAll();
+ }
+
+ private void createContentView() {
+ LayoutInflater inflator = (LayoutInflater) mActivity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ inflator.inflate(R.layout.panorama_module, mRootView, true);
+ mPanoLayout = (ViewGroup) mRootView.findViewById(R.id.pano_layout);
+ Resources appRes = mActivity.getResources();
+ mIndicatorColor = appRes.getColor(R.color.pano_progress_indication);
+ mReviewBackground = appRes.getColor(R.color.review_background);
+ mIndicatorColorFast = appRes.getColor(R.color.pano_progress_indication_fast);
+ mDialogHelper = new DialogHelper();
+ setViews(appRes);
+ }
+
+ private void setViews(Resources appRes) {
+ mCaptureLayout = (FrameLayout) mRootView.findViewById(R.id.panorama_capture_layout);
+ // TODO (shkong): set display change listener properly.
+ ((CameraRootView) mRootView).setDisplayChangeListener(null);
+ mTextureView = (TextureView) mRootView.findViewById(R.id.pano_preview_textureview);
+ mTextureView.setSurfaceTextureListener(this);
+ mTextureView.addOnLayoutChangeListener(this);
+ mCameraControls = (CameraControls) mRootView.findViewById(R.id.camera_controls);
+ mCaptureProgressBar = (PanoProgressBar) mRootView.findViewById(R.id.pano_pan_progress_bar);
+ mCaptureProgressBar.setBackgroundColor(appRes.getColor(R.color.pano_progress_empty));
+ mCaptureProgressBar.setDoneColor(appRes.getColor(R.color.pano_progress_done));
+ mCaptureProgressBar.setIndicatorColor(mIndicatorColor);
+ mCaptureProgressBar.setIndicatorWidth(20);
+
+ mPreviewBorder = mCaptureLayout.findViewById(R.id.pano_preview_area_border);
+
+ mLeftIndicator = mRootView.findViewById(R.id.pano_pan_left_indicator);
+ mRightIndicator = mRootView.findViewById(R.id.pano_pan_right_indicator);
+ mLeftIndicator.setEnabled(false);
+ mRightIndicator.setEnabled(false);
+ mTooFastPrompt = (TextView) mRootView.findViewById(R.id.pano_capture_too_fast_textview);
+
+ mSavingProgressBar = (PanoProgressBar) mRootView.findViewById(R.id.pano_saving_progress_bar);
+ mSavingProgressBar.setIndicatorWidth(0);
+ mSavingProgressBar.setMaxProgress(100);
+ mSavingProgressBar.setBackgroundColor(appRes.getColor(R.color.pano_progress_empty));
+ mSavingProgressBar.setDoneColor(appRes.getColor(R.color.pano_progress_indication));
+
+ mCaptureIndicator = mRootView.findViewById(R.id.pano_capture_indicator);
+
+ mReviewLayout = mRootView.findViewById(R.id.pano_review_layout);
+ mReview = (ImageView) mRootView.findViewById(R.id.pano_reviewarea);
+ mReview.setBackgroundColor(mReviewBackground);
+ View cancelButton = mRootView.findViewById(R.id.pano_review_cancel_button);
+ cancelButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View arg0) {
+ mController.cancelHighResStitching();
+ }
+ });
+
+ mShutterButton = (ShutterButton) mRootView.findViewById(R.id.shutter_button);
+ mShutterButton.setImageResource(R.drawable.btn_new_shutter);
+ mShutterButton.setOnShutterButtonListener(this);
+ }
+
+ private void showTooFastIndication() {
+ mTooFastPrompt.setVisibility(View.VISIBLE);
+ // The PreviewArea also contains the border for "too fast" indication.
+ mPreviewBorder.setVisibility(View.VISIBLE);
+ mCaptureProgressBar.setIndicatorColor(mIndicatorColorFast);
+ mLeftIndicator.setEnabled(true);
+ mRightIndicator.setEnabled(true);
+ }
+
+ private void hideTooFastIndication() {
+ mTooFastPrompt.setVisibility(View.GONE);
+ mPreviewBorder.setVisibility(View.INVISIBLE);
+ mCaptureProgressBar.setIndicatorColor(mIndicatorColor);
+ mLeftIndicator.setEnabled(false);
+ mRightIndicator.setEnabled(false);
+ }
+
+ private class DialogHelper {
+ private ProgressDialog mProgressDialog;
+ private AlertDialog mAlertDialog;
+
+ DialogHelper() {
+ mProgressDialog = null;
+ mAlertDialog = null;
+ }
+
+ public void dismissAll() {
+ if (mAlertDialog != null) {
+ mAlertDialog.dismiss();
+ mAlertDialog = null;
+ }
+ if (mProgressDialog != null) {
+ mProgressDialog.dismiss();
+ mProgressDialog = null;
+ }
+ }
+
+ public void showAlertDialog(
+ CharSequence title, CharSequence message,
+ CharSequence buttonMessage, final Runnable buttonRunnable) {
+ dismissAll();
+ mAlertDialog = (new AlertDialog.Builder(mActivity))
+ .setTitle(title)
+ .setMessage(message)
+ .setNeutralButton(buttonMessage, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialogInterface, int i) {
+ buttonRunnable.run();
+ }
+ })
+ .show();
+ }
+
+ public void showWaitingDialog(CharSequence message) {
+ dismissAll();
+ mProgressDialog = ProgressDialog.show(mActivity, null, message, true, false);
+ }
+ }
+
+ private static class FlipBitmapDrawable extends BitmapDrawable {
+
+ public FlipBitmapDrawable(Resources res, Bitmap bitmap) {
+ super(res, bitmap);
+ }
+
+ @Override
+ public void draw(Canvas canvas) {
+ Rect bounds = getBounds();
+ int cx = bounds.centerX();
+ int cy = bounds.centerY();
+ canvas.save(Canvas.MATRIX_SAVE_FLAG);
+ canvas.rotate(180, cx, cy);
+ super.draw(canvas);
+ canvas.restore();
+ }
+ }
+}