blob: b79baa55d78d3ce94f047f9dc6126975ccbcc150 [file] [log] [blame]
repo synca72d73c2011-07-27 19:29:41 +08001/*
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
17package com.android.camera;
18
Chung-yih Wang5f6e3542011-09-29 11:05:38 +080019import com.android.camera.ui.PopupManager;
Chih-yu Huang3ebe49d2011-10-07 18:44:53 +080020import com.android.camera.ui.Rotatable;
repo synca72d73c2011-07-27 19:29:41 +080021import com.android.camera.ui.RotateImageView;
22
23import android.content.Context;
24import android.graphics.PorterDuff;
25import android.graphics.drawable.Drawable;
26import android.util.AttributeSet;
Chung-yih Wang46f44302011-09-28 11:07:28 +080027import android.util.Log;
repo synca72d73c2011-07-27 19:29:41 +080028import android.view.View;
Chung-yih Wang20ff6a12011-09-08 10:35:03 +080029import android.view.animation.Animation;
30import android.view.animation.Animation.AnimationListener;
31import android.view.animation.AnimationUtils;
repo synca72d73c2011-07-27 19:29:41 +080032import android.widget.ImageView;
33import android.widget.RelativeLayout;
34
35/**
36 * A widget that includes three mode selections {@code RotateImageView}'s and
37 * a current mode indicator.
38 */
Chung-yih Wang5f6e3542011-09-29 11:05:38 +080039public class ModePicker extends RelativeLayout implements View.OnClickListener,
Chih-yu Huang3ebe49d2011-10-07 18:44:53 +080040 PopupManager.OnOtherPopupShowedListener, Rotatable {
Chung-yih Wang20ff6a12011-09-08 10:35:03 +080041 public static final int MODE_CAMERA = 0;
repo synca72d73c2011-07-27 19:29:41 +080042 public static final int MODE_VIDEO = 1;
Chung-yih Wang20ff6a12011-09-08 10:35:03 +080043 public static final int MODE_PANORAMA = 2;
repo synca72d73c2011-07-27 19:29:41 +080044
Chung-yih Wang46f44302011-09-28 11:07:28 +080045 private static final String TAG = "ModePicker";
Chih-yu Huang3ea573b2011-08-22 18:12:07 +080046 // Total mode number
47 private static final int MODE_NUM = 3;
48
repo synca72d73c2011-07-27 19:29:41 +080049 /** 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;
Chih-yu Huang3ea573b2011-08-22 18:12:07 +080056 private final int CURRENT_MODE_BACKGROUND;
repo synca72d73c2011-07-27 19:29:41 +080057
58 private OnModeChangeListener mListener;
Chung-yih Wang20ff6a12011-09-08 10:35:03 +080059 private View mModeSelectionFrame;
60 private RotateImageView mModeSelectionIcon[];
61 private View mCurrentModeFrame;
62 private RotateImageView mCurrentModeIcon[];
63 private View mCurrentModeBar;
Chung-yih Wang5f6e3542011-09-29 11:05:38 +080064 private boolean mSelectionEnabled;
65
Chung-yih Wang20ff6a12011-09-08 10:35:03 +080066
Wu-cheng Li3cd761b2011-09-20 15:48:37 +080067 private int mCurrentMode = 0;
Chung-yih Wang20ff6a12011-09-08 10:35:03 +080068 private Animation mFadeIn, mFadeOut;
repo synca72d73c2011-07-27 19:29:41 +080069
70 public ModePicker(Context context, AttributeSet attrs) {
71 super(context, attrs);
repo synca72d73c2011-07-27 19:29:41 +080072 DISABLED_COLOR = context.getResources().getColor(R.color.icon_disabled_color);
Chih-yu Huang3ea573b2011-08-22 18:12:07 +080073 CURRENT_MODE_BACKGROUND = R.drawable.btn_mode_background;
Chung-yih Wang20ff6a12011-09-08 10:35:03 +080074 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);
Chung-yih Wang5f6e3542011-09-29 11:05:38 +080079 PopupManager.getInstance(context).setOnOtherPopupShowedListener(this);
repo synca72d73c2011-07-27 19:29:41 +080080 }
81
82 protected void onFinishInflate() {
83 super.onFinishInflate();
84
Chung-yih Wang20ff6a12011-09-08 10:35:03 +080085 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);
repo synca72d73c2011-07-27 19:29:41 +080093
Chung-yih Wang20ff6a12011-09-08 10:35:03 +080094 // The current mode frame is for Phone UI only.
95 mCurrentModeFrame = findViewById(R.id.current_mode);
96 if (mCurrentModeFrame != null) {
Chung-yih Wang20ff6a12011-09-08 10:35:03 +080097 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 }
Chung-yih Wang46f44302011-09-28 11:07:28 +0800106 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 }
repo synca72d73c2011-07-27 19:29:41 +0800116 }
117
Chung-yih Wang5f6e3542011-09-29 11:05:38 +0800118 @Override
119 public void onOtherPopupShowed() {
120 if (mSelectionEnabled) enableModeSelection(false);
121 }
122
Chung-yih Wang20ff6a12011-09-08 10:35:03 +0800123 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
repo synca72d73c2011-07-27 19:29:41 +0800137 private void enableModeSelection(boolean enabled) {
Chung-yih Wang20ff6a12011-09-08 10:35:03 +0800138 if (mCurrentModeFrame != null) {
Chung-yih Wang5f6e3542011-09-29 11:05:38 +0800139 mSelectionEnabled = enabled;
Chung-yih Wang20ff6a12011-09-08 10:35:03 +0800140 // 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 }
Chung-yih Wang20ff6a12011-09-08 10:35:03 +0800146 }
147 updateModeState();
148 }
149
150 private void changeToSelectedMode() {
Chung-yih Wang46f44302011-09-28 11:07:28 +0800151 if (mListener != null) {
152 if (mListener.onModeChanged(mCurrentMode)) {
153 Log.e(TAG, "failed:onModeChanged:" + mCurrentMode);
Chung-yih Wang20ff6a12011-09-08 10:35:03 +0800154 }
repo synca72d73c2011-07-27 19:29:41 +0800155 }
156 }
157
158 public void onClick(View view) {
Chung-yih Wang20ff6a12011-09-08 10:35:03 +0800159 if (view == mCurrentModeFrame) {
Chung-yih Wang5f6e3542011-09-29 11:05:38 +0800160 PopupManager.getInstance(getContext()).notifyShowPopup(this);
Chung-yih Wang20ff6a12011-09-08 10:35:03 +0800161 enableModeSelection(true);
162 } else {
Chung-yih Wang46f44302011-09-28 11:07:28 +0800163 // 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 }
Chung-yih Wang20ff6a12011-09-08 10:35:03 +0800170 if (mCurrentModeBar == null) {
repo synca72d73c2011-07-27 19:29:41 +0800171 enableModeSelection(false);
Chung-yih Wang20ff6a12011-09-08 10:35:03 +0800172 } else {
173 changeToSelectedMode();
repo synca72d73c2011-07-27 19:29:41 +0800174 }
175 }
repo synca72d73c2011-07-27 19:29:41 +0800176 }
177
repo synca72d73c2011-07-27 19:29:41 +0800178 public void setOnModeChangeListener(OnModeChangeListener listener) {
179 mListener = listener;
180 }
181
182 public void setCurrentMode(int mode) {
repo synca72d73c2011-07-27 19:29:41 +0800183 mCurrentMode = mode;
Chung-yih Wang46f44302011-09-28 11:07:28 +0800184 updateModeState();
repo synca72d73c2011-07-27 19:29:41 +0800185 }
186
187 public boolean onModeChanged(int mode) {
188 setCurrentMode(mode);
189 return true;
190 }
191
Chih-yu Huang3ebe49d2011-10-07 18:44:53 +0800192 public void setOrientation(int orientation) {
Chih-yu Huang3ea573b2011-08-22 18:12:07 +0800193 for (int i = 0; i < MODE_NUM; ++i) {
Chih-yu Huang3ebe49d2011-10-07 18:44:53 +0800194 mModeSelectionIcon[i].setOrientation(orientation);
Chung-yih Wang20ff6a12011-09-08 10:35:03 +0800195 if (mCurrentModeFrame != null) {
Chih-yu Huang3ebe49d2011-10-07 18:44:53 +0800196 mCurrentModeIcon[i].setOrientation(orientation);
Chung-yih Wang20ff6a12011-09-08 10:35:03 +0800197 }
repo synca72d73c2011-07-27 19:29:41 +0800198 }
repo synca72d73c2011-07-27 19:29:41 +0800199 }
200
201 @Override
202 public void setEnabled(boolean enabled) {
203 super.setEnabled(enabled);
repo synca72d73c2011-07-27 19:29:41 +0800204
Chung-yih Wang20ff6a12011-09-08 10:35:03 +0800205 // Enable or disable the frames.
206 if (mCurrentModeFrame != null) mCurrentModeFrame.setEnabled(enabled);
207 mModeSelectionFrame.setEnabled(enabled);
Chih-yu Huang3ea573b2011-08-22 18:12:07 +0800208
Chung-yih Wang20ff6a12011-09-08 10:35:03 +0800209 // Enable or disable the icons.
Chih-yu Huang3ea573b2011-08-22 18:12:07 +0800210 for (int i = 0; i < MODE_NUM; ++i) {
Chung-yih Wang20ff6a12011-09-08 10:35:03 +0800211 mModeSelectionIcon[i].setEnabled(enabled);
212 if (mCurrentModeFrame != null) mCurrentModeIcon[i].setEnabled(enabled);
repo synca72d73c2011-07-27 19:29:41 +0800213 }
Chung-yih Wang20ff6a12011-09-08 10:35:03 +0800214 if (enabled) updateModeState();
repo synca72d73c2011-07-27 19:29:41 +0800215 }
216
Chung-yih Wang46f44302011-09-28 11:07:28 +0800217 private void highlightView(ImageView view, boolean enabled) {
repo synca72d73c2011-07-27 19:29:41 +0800218 if (enabled) {
Chung-yih Wang46f44302011-09-28 11:07:28 +0800219 view.clearColorFilter();
repo synca72d73c2011-07-27 19:29:41 +0800220 } else {
Chung-yih Wang46f44302011-09-28 11:07:28 +0800221 view.setColorFilter(DISABLED_COLOR, PorterDuff.Mode.SRC_ATOP);
repo synca72d73c2011-07-27 19:29:41 +0800222 }
Chung-yih Wang20ff6a12011-09-08 10:35:03 +0800223 }
224
225 private void updateModeState() {
Chih-Chung Changda705aa2011-10-31 18:50:52 +0800226 // 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 }
Chung-yih Wang20ff6a12011-09-08 10:35:03 +0800231 }
Chih-Chung Changda705aa2011-10-31 18:50:52 +0800232
Chung-yih Wang20ff6a12011-09-08 10:35:03 +0800233 // 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 }
repo synca72d73c2011-07-27 19:29:41 +0800268 }
269}