1/*
2 * Copyright (C) 2014 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.widget;
18
19import android.content.Context;
20import android.content.res.TypedArray;
21import android.graphics.drawable.Drawable;
22import android.view.View;
23import android.widget.ImageView;
24
25import com.android.camera.ButtonManager;
26import com.android.camera.app.AppController;
27import com.android.camera.debug.Log;
28import com.android.camera.settings.Keys;
29import com.android.camera.settings.SettingsManager;
30import com.android.camera.util.PhotoSphereHelper;
31import com.android.camera2.R;
32
33/**
34 * IndicatorIconController sets the visibility and icon state of
35 * on screen indicators.
36 *
37 * Indicators are only visible if they are in a non-default state.  The
38 * visibility of an indicator is set when an indicator's setting changes.
39 */
40public class IndicatorIconController
41    implements SettingsManager.OnSettingChangedListener,
42               ButtonManager.ButtonStatusListener {
43
44    private final static Log.Tag TAG = new Log.Tag("IndicatorIconCtrlr");
45
46    private ImageView mFlashIndicator;
47    private ImageView mHdrIndicator;
48    private ImageView mPanoIndicator;
49    private ImageView mCountdownTimerIndicator;
50
51    private ImageView mExposureIndicatorN2;
52    private ImageView mExposureIndicatorN1;
53    private ImageView mExposureIndicatorP1;
54    private ImageView mExposureIndicatorP2;
55
56    private TypedArray mFlashIndicatorPhotoIcons;
57    private TypedArray mFlashIndicatorVideoIcons;
58    private TypedArray mHdrPlusIndicatorIcons;
59    private TypedArray mHdrIndicatorIcons;
60    private TypedArray mPanoIndicatorIcons;
61    private TypedArray mCountdownTimerIndicatorIcons;
62
63    private AppController mController;
64
65    public IndicatorIconController(AppController controller, View root) {
66        mController = controller;
67        Context context = controller.getAndroidContext();
68
69        mFlashIndicator = (ImageView) root.findViewById(R.id.flash_indicator);
70        mFlashIndicatorPhotoIcons = context.getResources().obtainTypedArray(
71            R.array.camera_flashmode_indicator_icons);
72        mFlashIndicatorVideoIcons = context.getResources().obtainTypedArray(
73            R.array.video_flashmode_indicator_icons);
74
75        mHdrIndicator = (ImageView) root.findViewById(R.id.hdr_indicator);
76        mHdrPlusIndicatorIcons = context.getResources().obtainTypedArray(
77            R.array.pref_camera_hdr_plus_indicator_icons);
78        mHdrIndicatorIcons = context.getResources().obtainTypedArray(
79            R.array.pref_camera_hdr_indicator_icons);
80
81        int panoIndicatorArrayId = PhotoSphereHelper.getPanoramaOrientationIndicatorArrayId();
82        if (panoIndicatorArrayId > 0) {
83            mPanoIndicator = (ImageView) root.findViewById(R.id.pano_indicator);
84            mPanoIndicatorIcons =
85                context.getResources().obtainTypedArray(panoIndicatorArrayId);
86        }
87
88        mCountdownTimerIndicator = (ImageView) root.findViewById(R.id.countdown_timer_indicator);
89        mCountdownTimerIndicatorIcons = context.getResources().obtainTypedArray(
90                R.array.pref_camera_countdown_indicators);
91
92        mExposureIndicatorN2 = (ImageView) root.findViewById(R.id.exposure_n2_indicator);
93        mExposureIndicatorN1 = (ImageView) root.findViewById(R.id.exposure_n1_indicator);
94        mExposureIndicatorP1 = (ImageView) root.findViewById(R.id.exposure_p1_indicator);
95        mExposureIndicatorP2 = (ImageView) root.findViewById(R.id.exposure_p2_indicator);
96    }
97
98    @Override
99    public void onButtonVisibilityChanged(ButtonManager buttonManager, int buttonId) {
100        syncIndicatorWithButton(buttonId);
101    }
102
103    @Override
104    public void onButtonEnabledChanged(ButtonManager buttonManager, int buttonId) {
105        syncIndicatorWithButton(buttonId);
106    }
107
108    /**
109     * Syncs a specific indicator's icon and visibility
110     * based on the enabled state and visibility of a button.
111     */
112    private void syncIndicatorWithButton(int buttonId) {
113        switch (buttonId) {
114            case ButtonManager.BUTTON_FLASH: {
115                syncFlashIndicator();
116                break;
117            }
118            case ButtonManager.BUTTON_TORCH: {
119                syncFlashIndicator();
120                break;
121            }
122            case ButtonManager.BUTTON_HDR_PLUS: {
123                syncHdrIndicator();
124                break;
125            }
126            case ButtonManager.BUTTON_HDR: {
127                syncHdrIndicator();
128                break;
129            }
130            case ButtonManager.BUTTON_EXPOSURE_COMPENSATION: {
131                syncExposureIndicator();
132                break;
133            }
134            default:
135                // Do nothing.  The indicator doesn't care
136                // about button that don't correspond to indicators.
137        }
138    }
139
140    /**
141     * Sets all indicators to the correct resource and visibility
142     * based on the current settings.
143     */
144    public void syncIndicators() {
145        syncFlashIndicator();
146        syncHdrIndicator();
147        syncPanoIndicator();
148        syncExposureIndicator();
149        syncCountdownTimerIndicator();
150    }
151
152    /**
153     * If the new visibility is different from the current visibility
154     * on a view, change the visibility and call any registered
155     * {@link OnIndicatorVisibilityChangedListener}.
156     */
157    private static void changeVisibility(View view, int visibility) {
158        if (view.getVisibility() != visibility) {
159            view.setVisibility(visibility);
160        }
161    }
162
163    /**
164     * Sync the icon and visibility of the flash indicator.
165     */
166    private void syncFlashIndicator() {
167        ButtonManager buttonManager = mController.getButtonManager();
168        // If flash isn't an enabled and visible option,
169        // do not show the indicator.
170        if (buttonManager.isEnabled(ButtonManager.BUTTON_FLASH)
171                && buttonManager.isVisible(ButtonManager.BUTTON_FLASH)) {
172
173            int modeIndex = mController.getCurrentModuleIndex();
174            if (modeIndex == mController.getAndroidContext().getResources()
175                    .getInteger(R.integer.camera_mode_video)) {
176                setIndicatorState(mController.getCameraScope(),
177                                  Keys.KEY_VIDEOCAMERA_FLASH_MODE, mFlashIndicator,
178                                  mFlashIndicatorVideoIcons, false);
179            } else if (modeIndex == mController.getAndroidContext().getResources()
180                    .getInteger(R.integer.camera_mode_gcam)) {
181                setIndicatorState(mController.getCameraScope(),
182                                  Keys.KEY_HDR_PLUS_FLASH_MODE, mFlashIndicator,
183                                  mFlashIndicatorPhotoIcons, false);
184            } else {
185                setIndicatorState(mController.getCameraScope(),
186                                  Keys.KEY_FLASH_MODE, mFlashIndicator,
187                                  mFlashIndicatorPhotoIcons, false);
188            }
189        } else {
190            changeVisibility(mFlashIndicator, View.GONE);
191        }
192    }
193
194    /**
195     * Sync the icon and the visibility of the hdr/hdrplus indicator.
196     */
197    private void syncHdrIndicator() {
198        ButtonManager buttonManager = mController.getButtonManager();
199        // If hdr isn't an enabled and visible option,
200        // do not show the indicator.
201        if (buttonManager.isEnabled(ButtonManager.BUTTON_HDR_PLUS)
202                && buttonManager.isVisible(ButtonManager.BUTTON_HDR_PLUS)) {
203            setIndicatorState(SettingsManager.SCOPE_GLOBAL,
204                              Keys.KEY_CAMERA_HDR_PLUS, mHdrIndicator,
205                              mHdrPlusIndicatorIcons, false);
206        } else if (buttonManager.isEnabled(ButtonManager.BUTTON_HDR)
207                && buttonManager.isVisible(ButtonManager.BUTTON_HDR)) {
208            setIndicatorState(SettingsManager.SCOPE_GLOBAL,
209                              Keys.KEY_CAMERA_HDR, mHdrIndicator,
210                              mHdrIndicatorIcons, false);
211        } else {
212            changeVisibility(mHdrIndicator, View.GONE);
213        }
214    }
215
216    /**
217     * Sync the icon and the visibility of the pano indicator.
218     */
219    private void syncPanoIndicator() {
220        if (mPanoIndicator == null) {
221            Log.w(TAG, "Trying to sync a pano indicator that is not initialized.");
222            return;
223        }
224
225        ButtonManager buttonManager = mController.getButtonManager();
226        if (buttonManager.isPanoEnabled()) {
227            setIndicatorState(SettingsManager.SCOPE_GLOBAL,
228                              Keys.KEY_CAMERA_PANO_ORIENTATION, mPanoIndicator,
229                              mPanoIndicatorIcons, true);
230        } else {
231            changeVisibility(mPanoIndicator, View.GONE);
232        }
233    }
234
235    private void syncExposureIndicator() {
236        if (mExposureIndicatorN2 == null
237            || mExposureIndicatorN1 == null
238            || mExposureIndicatorP1 == null
239            || mExposureIndicatorP2 == null) {
240            Log.w(TAG, "Trying to sync exposure indicators that are not initialized.");
241            return;
242        }
243
244
245        // Reset all exposure indicator icons.
246        changeVisibility(mExposureIndicatorN2, View.GONE);
247        changeVisibility(mExposureIndicatorN1, View.GONE);
248        changeVisibility(mExposureIndicatorP1, View.GONE);
249        changeVisibility(mExposureIndicatorP2, View.GONE);
250
251        ButtonManager buttonManager = mController.getButtonManager();
252        if (buttonManager.isEnabled(ButtonManager.BUTTON_EXPOSURE_COMPENSATION)
253                && buttonManager.isVisible(ButtonManager.BUTTON_EXPOSURE_COMPENSATION)) {
254
255            int compValue = mController.getSettingsManager().getInteger(
256                    mController.getCameraScope(), Keys.KEY_EXPOSURE);
257            int comp = Math.round(compValue * buttonManager.getExposureCompensationStep());
258
259            // Turn on the appropriate indicator.
260            switch (comp) {
261                case -2:
262                    changeVisibility(mExposureIndicatorN2, View.VISIBLE);
263                    break;
264                case -1:
265                    changeVisibility(mExposureIndicatorN1, View.VISIBLE);
266                    break;
267                case 0:
268                    // Do nothing.
269                    break;
270                case 1:
271                    changeVisibility(mExposureIndicatorP1, View.VISIBLE);
272                    break;
273                case 2:
274                    changeVisibility(mExposureIndicatorP2, View.VISIBLE);
275            }
276        }
277    }
278
279    private void syncCountdownTimerIndicator() {
280        ButtonManager buttonManager = mController.getButtonManager();
281
282        if (buttonManager.isEnabled(ButtonManager.BUTTON_COUNTDOWN)
283            && buttonManager.isVisible(ButtonManager.BUTTON_COUNTDOWN)) {
284            setIndicatorState(SettingsManager.SCOPE_GLOBAL,
285                              Keys.KEY_COUNTDOWN_DURATION, mCountdownTimerIndicator,
286                              mCountdownTimerIndicatorIcons, false);
287        } else {
288            changeVisibility(mCountdownTimerIndicator, View.GONE);
289        }
290    }
291
292    /**
293     * Sets the image resource and visibility of the indicator
294     * based on the indicator's corresponding setting state.
295     */
296    private void setIndicatorState(String scope, String key, ImageView imageView,
297                                   TypedArray iconArray, boolean showDefault) {
298        SettingsManager settingsManager = mController.getSettingsManager();
299
300        int valueIndex = settingsManager.getIndexOfCurrentValue(scope, key);
301        if (valueIndex < 0) {
302            // This can happen when the setting is camera dependent
303            // and the camera is not yet open.  CameraAppUI.onChangeCamera()
304            // will call this again when the camera is open.
305            Log.w(TAG, "The setting for this indicator is not available.");
306            imageView.setVisibility(View.GONE);
307            return;
308        }
309        Drawable drawable = iconArray.getDrawable(valueIndex);
310        if (drawable == null) {
311            throw new IllegalStateException("Indicator drawable is null.");
312        }
313        imageView.setImageDrawable(drawable);
314
315        // Set the indicator visible if not in default state.
316        boolean visibilityChanged = false;
317        if (!showDefault && settingsManager.isDefault(scope, key)) {
318            changeVisibility(imageView, View.GONE);
319        } else {
320            changeVisibility(imageView, View.VISIBLE);
321        }
322    }
323
324    @Override
325    public void onSettingChanged(SettingsManager settingsManager, String key) {
326        if (key.equals(Keys.KEY_FLASH_MODE)) {
327            syncFlashIndicator();
328            return;
329        }
330        if (key.equals(Keys.KEY_VIDEOCAMERA_FLASH_MODE)) {
331            syncFlashIndicator();
332            return;
333        }
334        if (key.equals(Keys.KEY_CAMERA_HDR_PLUS)) {
335            syncHdrIndicator();
336            return;
337        }
338        if (key.equals(Keys.KEY_CAMERA_HDR)) {
339            syncHdrIndicator();
340            return;
341        }
342        if (key.equals(Keys.KEY_CAMERA_PANO_ORIENTATION)) {
343            syncPanoIndicator();
344            return;
345        }
346        if (key.equals(Keys.KEY_EXPOSURE)) {
347            syncExposureIndicator();
348            return;
349        }
350        if (key.equals(Keys.KEY_COUNTDOWN_DURATION)) {
351            syncCountdownTimerIndicator();
352            return;
353        }
354    }
355
356}
357