Home | History | Annotate | Download | only in camera
      1 /*
      2  * Copyright (C) 2011 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 
     17 package com.android.camera;
     18 
     19 import com.android.camera.ui.PopupManager;
     20 import com.android.camera.ui.Rotatable;
     21 import com.android.camera.ui.RotateImageView;
     22 
     23 import android.content.Context;
     24 import android.graphics.PorterDuff;
     25 import android.graphics.drawable.Drawable;
     26 import android.util.AttributeSet;
     27 import android.util.Log;
     28 import android.view.View;
     29 import android.view.animation.Animation;
     30 import android.view.animation.Animation.AnimationListener;
     31 import android.view.animation.AnimationUtils;
     32 import android.widget.ImageView;
     33 import android.widget.RelativeLayout;
     34 
     35 /**
     36  * A widget that includes three mode selections {@code RotateImageView}'s and
     37  * a current mode indicator.
     38  */
     39 public class ModePicker extends RelativeLayout implements View.OnClickListener,
     40     PopupManager.OnOtherPopupShowedListener, Rotatable {
     41     public static final int MODE_CAMERA = 0;
     42     public static final int MODE_VIDEO = 1;
     43     public static final int MODE_PANORAMA = 2;
     44 
     45     private static final String TAG = "ModePicker";
     46     // Total mode number
     47     private static final int MODE_NUM = 3;
     48 
     49     /** A callback to be called when the user wants to switch activity. */
     50     public interface OnModeChangeListener {
     51         // Returns true if the listener agrees that the mode can be changed.
     52         public boolean onModeChanged(int newMode);
     53     }
     54 
     55     private final int DISABLED_COLOR;
     56     private final int CURRENT_MODE_BACKGROUND;
     57 
     58     private OnModeChangeListener mListener;
     59     private View mModeSelectionFrame;
     60     private RotateImageView mModeSelectionIcon[];
     61     private View mCurrentModeFrame;
     62     private RotateImageView mCurrentModeIcon[];
     63     private View mCurrentModeBar;
     64     private boolean mSelectionEnabled;
     65 
     66 
     67     private int mCurrentMode = 0;
     68     private Animation mFadeIn, mFadeOut;
     69 
     70     public ModePicker(Context context, AttributeSet attrs) {
     71         super(context, attrs);
     72         DISABLED_COLOR = context.getResources().getColor(R.color.icon_disabled_color);
     73         CURRENT_MODE_BACKGROUND = R.drawable.btn_mode_background;
     74         mFadeIn = AnimationUtils.loadAnimation(
     75                 context, R.anim.mode_selection_fade_in);
     76         mFadeOut = AnimationUtils.loadAnimation(
     77                 context, R.anim.mode_selection_fade_out);
     78         mFadeOut.setAnimationListener(mAnimationListener);
     79         PopupManager.getInstance(context).setOnOtherPopupShowedListener(this);
     80     }
     81 
     82     protected void onFinishInflate() {
     83         super.onFinishInflate();
     84 
     85         mModeSelectionFrame = findViewById(R.id.mode_selection);
     86         mModeSelectionIcon = new RotateImageView[MODE_NUM];
     87         mModeSelectionIcon[MODE_PANORAMA] =
     88                 (RotateImageView) findViewById(R.id.mode_panorama);
     89         mModeSelectionIcon[MODE_VIDEO] =
     90                 (RotateImageView) findViewById(R.id.mode_video);
     91         mModeSelectionIcon[MODE_CAMERA] =
     92                 (RotateImageView) findViewById(R.id.mode_camera);
     93 
     94         // The current mode frame is for Phone UI only.
     95         mCurrentModeFrame = findViewById(R.id.current_mode);
     96         if (mCurrentModeFrame != null) {
     97             mCurrentModeIcon = new RotateImageView[MODE_NUM];
     98             mCurrentModeIcon[0] = (RotateImageView) findViewById(R.id.mode_0);
     99             mCurrentModeIcon[1] = (RotateImageView) findViewById(R.id.mode_1);
    100             mCurrentModeIcon[2] = (RotateImageView) findViewById(R.id.mode_2);
    101         } else {
    102             // current_mode_bar is only for tablet.
    103             mCurrentModeBar = findViewById(R.id.current_mode_bar);
    104             enableModeSelection(true);
    105         }
    106         registerOnClickListener();
    107     }
    108 
    109     private void registerOnClickListener() {
    110         if (mCurrentModeFrame != null) {
    111             mCurrentModeFrame.setOnClickListener(this);
    112         }
    113         for (int i = 0; i < MODE_NUM; ++i) {
    114             mModeSelectionIcon[i].setOnClickListener(this);
    115         }
    116     }
    117 
    118     @Override
    119     public void onOtherPopupShowed() {
    120         if (mSelectionEnabled) enableModeSelection(false);
    121     }
    122 
    123     private AnimationListener mAnimationListener = new AnimationListener() {
    124         public void onAnimationEnd(Animation animation) {
    125             changeToSelectedMode();
    126             mCurrentModeFrame.setVisibility(View.VISIBLE);
    127             mModeSelectionFrame.setVisibility(View.GONE);
    128         }
    129 
    130         public void onAnimationRepeat(Animation animation) {
    131         }
    132 
    133         public void onAnimationStart(Animation animation) {
    134         }
    135     };
    136 
    137     private void enableModeSelection(boolean enabled) {
    138         if (mCurrentModeFrame != null) {
    139             mSelectionEnabled = enabled;
    140             // Animation Effect is applied on Phone UI only.
    141             mModeSelectionFrame.startAnimation(enabled ? mFadeIn : mFadeOut);
    142             if (enabled) {
    143                 mModeSelectionFrame.setVisibility(View.VISIBLE);
    144                 mCurrentModeFrame.setVisibility(View.GONE);
    145             }
    146         }
    147         updateModeState();
    148     }
    149 
    150     private void changeToSelectedMode() {
    151         if (mListener != null) {
    152             if (mListener.onModeChanged(mCurrentMode)) {
    153                 Log.e(TAG, "failed:onModeChanged:" + mCurrentMode);
    154             }
    155         }
    156     }
    157 
    158     public void onClick(View view) {
    159         if (view == mCurrentModeFrame) {
    160             PopupManager.getInstance(getContext()).notifyShowPopup(this);
    161             enableModeSelection(true);
    162         } else {
    163             // Set the selected mode as the current one and switch to it.
    164             for (int i = 0; i < MODE_NUM; ++i) {
    165                 if (view == mModeSelectionIcon[i] && (mCurrentMode != i)) {
    166                     setCurrentMode(i);
    167                     break;
    168                 }
    169             }
    170             if (mCurrentModeBar == null) {
    171                 enableModeSelection(false);
    172             } else {
    173                 changeToSelectedMode();
    174             }
    175         }
    176     }
    177 
    178     public void setOnModeChangeListener(OnModeChangeListener listener) {
    179         mListener = listener;
    180     }
    181 
    182     public void setCurrentMode(int mode) {
    183         mCurrentMode = mode;
    184         updateModeState();
    185     }
    186 
    187     public boolean onModeChanged(int mode) {
    188         setCurrentMode(mode);
    189         return true;
    190     }
    191 
    192     public void setOrientation(int orientation) {
    193         for (int i = 0; i < MODE_NUM; ++i) {
    194             mModeSelectionIcon[i].setOrientation(orientation);
    195             if (mCurrentModeFrame != null) {
    196                 mCurrentModeIcon[i].setOrientation(orientation);
    197             }
    198         }
    199     }
    200 
    201     @Override
    202     public void setEnabled(boolean enabled) {
    203         super.setEnabled(enabled);
    204 
    205         // Enable or disable the frames.
    206         if (mCurrentModeFrame != null) mCurrentModeFrame.setEnabled(enabled);
    207         mModeSelectionFrame.setEnabled(enabled);
    208 
    209         // Enable or disable the icons.
    210         for (int i = 0; i < MODE_NUM; ++i) {
    211             mModeSelectionIcon[i].setEnabled(enabled);
    212             if (mCurrentModeFrame != null) mCurrentModeIcon[i].setEnabled(enabled);
    213         }
    214         if (enabled) updateModeState();
    215     }
    216 
    217     private void highlightView(ImageView view, boolean enabled) {
    218         if (enabled) {
    219             view.clearColorFilter();
    220         } else {
    221             view.setColorFilter(DISABLED_COLOR, PorterDuff.Mode.SRC_ATOP);
    222         }
    223     }
    224 
    225     private void updateModeState() {
    226         // Grey-out the unselected icons for Phone UI.
    227         if (mCurrentModeFrame != null) {
    228             for (int i = 0; i < MODE_NUM; ++i) {
    229                 highlightView(mModeSelectionIcon[i], (i == mCurrentMode));
    230             }
    231         }
    232 
    233         // Update the current mode icons on the Phone UI. The selected mode
    234         // should be in the center of the current mode icon bar.
    235         if (mCurrentModeFrame != null) {
    236             for (int i = 0, j = 0; i < MODE_NUM; ++i) {
    237                 int target;
    238                 if (i == 1) {
    239                     // The second icon is always the selected mode.
    240                     target = mCurrentMode;
    241                 } else {
    242                     // Set the icons in order of camera, video and panorama.
    243                     if (j == mCurrentMode) j++;
    244                     target = j++;
    245                 }
    246                 mCurrentModeIcon[i].setImageDrawable(
    247                         mModeSelectionIcon[target].getDrawable());
    248             }
    249         }
    250     }
    251 
    252     @Override
    253     protected void onLayout(
    254             boolean changed, int left, int top, int right, int bottom) {
    255         super.onLayout(changed, left, top, right, bottom);
    256         // Layout the current mode indicator bar.
    257         if (mCurrentModeBar != null) {
    258             int viewWidth = mModeSelectionIcon[MODE_CAMERA].getWidth();
    259             int iconWidth = ((ImageView) mModeSelectionIcon[MODE_CAMERA])
    260                     .getDrawable().getIntrinsicWidth();
    261             int padding = (viewWidth - iconWidth) / 2;
    262             int l = mModeSelectionFrame.getLeft() + mCurrentMode * viewWidth;
    263             mCurrentModeBar.layout((l + padding),
    264                     (bottom - top - mCurrentModeBar.getHeight()),
    265                     (l + padding + iconWidth),
    266                     (bottom - top));
    267         }
    268     }
    269 }
    270