1 /* 2 * Copyright (C) 2013 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 android.content.Context; 20 import android.content.res.TypedArray; 21 import android.view.LayoutInflater; 22 import android.view.View; 23 import android.widget.ImageButton; 24 import android.widget.LinearLayout; 25 26 import com.android.camera.app.AppController; 27 import com.android.camera.app.CameraAppUI; 28 import com.android.camera.settings.Keys; 29 import com.android.camera.settings.SettingsManager; 30 import com.android.camera.ui.RadioOptions; 31 import com.android.camera.util.PhotoSphereHelper; 32 import com.android.camera.widget.ModeOptions; 33 import com.android.camera2.R; 34 35 /** 36 * A class for generating pre-initialized 37 * {@link #android.widget.ImageButton}s. 38 */ 39 public class ButtonManager implements SettingsManager.OnSettingChangedListener { 40 41 public static final int BUTTON_FLASH = 0; 42 public static final int BUTTON_TORCH = 1; 43 public static final int BUTTON_HDR_PLUS_FLASH = 2; 44 public static final int BUTTON_CAMERA = 3; 45 public static final int BUTTON_HDR_PLUS = 4; 46 public static final int BUTTON_HDR = 5; 47 public static final int BUTTON_CANCEL = 6; 48 public static final int BUTTON_DONE = 7; 49 public static final int BUTTON_RETAKE = 8; 50 public static final int BUTTON_REVIEW = 9; 51 public static final int BUTTON_GRID_LINES = 10; 52 public static final int BUTTON_EXPOSURE_COMPENSATION = 11; 53 public static final int BUTTON_COUNTDOWN = 12; 54 55 /** For two state MultiToggleImageButtons, the off index. */ 56 public static final int OFF = 0; 57 /** For two state MultiToggleImageButtons, the on index. */ 58 public static final int ON = 1; 59 60 /** A reference to the application's settings manager. */ 61 private final SettingsManager mSettingsManager; 62 63 /** Bottom bar options toggle buttons. */ 64 private MultiToggleImageButton mButtonCamera; 65 private MultiToggleImageButton mButtonFlash; 66 private MultiToggleImageButton mButtonHdr; 67 private MultiToggleImageButton mButtonGridlines; 68 private MultiToggleImageButton mButtonCountdown; 69 70 /** Intent UI buttons. */ 71 private ImageButton mButtonCancel; 72 private ImageButton mButtonDone; 73 private ImageButton mButtonRetake; // same as review. 74 75 private ImageButton mButtonExposureCompensation; 76 private ImageButton mExposureN2; 77 private ImageButton mExposureN1; 78 private ImageButton mExposure0; 79 private ImageButton mExposureP1; 80 private ImageButton mExposureP2; 81 private RadioOptions mModeOptionsExposure; 82 private RadioOptions mModeOptionsPano; 83 private View mModeOptionsButtons; 84 private ModeOptions mModeOptions; 85 86 private int mMinExposureCompensation; 87 private int mMaxExposureCompensation; 88 private float mExposureCompensationStep; 89 90 /** A listener for button enabled and visibility 91 state changes. */ 92 private ButtonStatusListener mListener; 93 94 /** An reference to the gcam mode index. */ 95 private static int sGcamIndex; 96 97 private final AppController mAppController; 98 99 /** 100 * Get a new global ButtonManager. 101 */ ButtonManager(AppController app)102 public ButtonManager(AppController app) { 103 mAppController = app; 104 105 Context context = app.getAndroidContext(); 106 sGcamIndex = context.getResources().getInteger(R.integer.camera_mode_gcam); 107 108 mSettingsManager = app.getSettingsManager(); 109 mSettingsManager.addListener(this); 110 } 111 112 /** 113 * Load references to buttons under a root View. 114 * Call this after the root clears/reloads all of its children 115 * to prevent stale references button views. 116 */ load(View root)117 public void load(View root) { 118 getButtonsReferences(root); 119 } 120 121 /** 122 * ButtonStatusListener provides callbacks for when button's 123 * visibility changes and enabled status changes. 124 */ 125 public interface ButtonStatusListener { 126 /** 127 * A button's visibility has changed. 128 */ onButtonVisibilityChanged(ButtonManager buttonManager, int buttonId)129 public void onButtonVisibilityChanged(ButtonManager buttonManager, int buttonId); 130 131 /** 132 * A button's enabled state has changed. 133 */ onButtonEnabledChanged(ButtonManager buttonManager, int buttonId)134 public void onButtonEnabledChanged(ButtonManager buttonManager, int buttonId); 135 } 136 137 /** 138 * Sets the ButtonStatusListener. 139 */ setListener(ButtonStatusListener listener)140 public void setListener(ButtonStatusListener listener) { 141 mListener = listener; 142 } 143 144 /** 145 * Gets references to all known buttons. 146 */ getButtonsReferences(View root)147 private void getButtonsReferences(View root) { 148 mButtonCamera 149 = (MultiToggleImageButton) root.findViewById(R.id.camera_toggle_button); 150 mButtonFlash 151 = (MultiToggleImageButton) root.findViewById(R.id.flash_toggle_button); 152 mButtonHdr 153 = (MultiToggleImageButton) root.findViewById(R.id.hdr_plus_toggle_button); 154 mButtonGridlines 155 = (MultiToggleImageButton) root.findViewById(R.id.grid_lines_toggle_button); 156 mButtonCancel 157 = (ImageButton) root.findViewById(R.id.cancel_button); 158 mButtonDone 159 = (ImageButton) root.findViewById(R.id.done_button); 160 mButtonRetake 161 = (ImageButton) root.findViewById(R.id.retake_button); 162 163 mButtonExposureCompensation = 164 (ImageButton) root.findViewById(R.id.exposure_button); 165 mExposureN2 = (ImageButton) root.findViewById(R.id.exposure_n2); 166 mExposureN1 = (ImageButton) root.findViewById(R.id.exposure_n1); 167 mExposure0 = (ImageButton) root.findViewById(R.id.exposure_0); 168 mExposureP1 = (ImageButton) root.findViewById(R.id.exposure_p1); 169 mExposureP2 = (ImageButton) root.findViewById(R.id.exposure_p2); 170 mModeOptionsExposure = (RadioOptions) root.findViewById(R.id.mode_options_exposure); 171 mModeOptionsPano = (RadioOptions) root.findViewById(R.id.mode_options_pano); 172 mModeOptionsButtons = root.findViewById(R.id.mode_options_buttons); 173 mModeOptions = (ModeOptions) root.findViewById(R.id.mode_options); 174 175 mButtonCountdown = (MultiToggleImageButton) root.findViewById(R.id.countdown_toggle_button); 176 } 177 178 @Override onSettingChanged(SettingsManager settingsManager, String key)179 public void onSettingChanged(SettingsManager settingsManager, String key) { 180 MultiToggleImageButton button = null; 181 int index = 0; 182 183 if (key.equals(Keys.KEY_FLASH_MODE)) { 184 index = mSettingsManager.getIndexOfCurrentValue(mAppController.getCameraScope(), 185 Keys.KEY_FLASH_MODE); 186 button = getButtonOrError(BUTTON_FLASH); 187 } else if (key.equals(Keys.KEY_VIDEOCAMERA_FLASH_MODE)) { 188 index = mSettingsManager.getIndexOfCurrentValue(mAppController.getCameraScope(), 189 Keys.KEY_VIDEOCAMERA_FLASH_MODE); 190 button = getButtonOrError(BUTTON_TORCH); 191 } else if (key.equals(Keys.KEY_HDR_PLUS_FLASH_MODE)) { 192 index = mSettingsManager.getIndexOfCurrentValue(mAppController.getModuleScope(), 193 Keys.KEY_HDR_PLUS_FLASH_MODE); 194 button = getButtonOrError(BUTTON_HDR_PLUS_FLASH); 195 } else if (key.equals(Keys.KEY_CAMERA_ID)) { 196 index = mSettingsManager.getIndexOfCurrentValue(mAppController.getModuleScope(), 197 Keys.KEY_CAMERA_ID); 198 button = getButtonOrError(BUTTON_CAMERA); 199 } else if (key.equals(Keys.KEY_CAMERA_HDR_PLUS)) { 200 index = mSettingsManager.getIndexOfCurrentValue(SettingsManager.SCOPE_GLOBAL, 201 Keys.KEY_CAMERA_HDR_PLUS); 202 button = getButtonOrError(BUTTON_HDR_PLUS); 203 } else if (key.equals(Keys.KEY_CAMERA_HDR)) { 204 index = mSettingsManager.getIndexOfCurrentValue(SettingsManager.SCOPE_GLOBAL, 205 Keys.KEY_CAMERA_HDR); 206 button = getButtonOrError(BUTTON_HDR); 207 } else if (key.equals(Keys.KEY_CAMERA_GRID_LINES)) { 208 index = mSettingsManager.getIndexOfCurrentValue(SettingsManager.SCOPE_GLOBAL, 209 Keys.KEY_CAMERA_GRID_LINES); 210 button = getButtonOrError(BUTTON_GRID_LINES); 211 } else if (key.equals(Keys.KEY_CAMERA_PANO_ORIENTATION)) { 212 updatePanoButtons(); 213 } else if (key.equals(Keys.KEY_EXPOSURE)) { 214 updateExposureButtons(); 215 } else if (key.equals(Keys.KEY_COUNTDOWN_DURATION)) { 216 index = mSettingsManager.getIndexOfCurrentValue(SettingsManager.SCOPE_GLOBAL, 217 Keys.KEY_COUNTDOWN_DURATION); 218 button = getButtonOrError(BUTTON_COUNTDOWN); 219 } 220 221 if (button != null && button.getState() != index) { 222 button.setState(Math.max(index, 0), false); 223 } 224 } 225 226 /** 227 * A callback executed in the state listener of a button. 228 * 229 * Used by a module to set specific behavior when a button's 230 * state changes. 231 */ 232 public interface ButtonCallback { onStateChanged(int state)233 public void onStateChanged(int state); 234 } 235 236 /** 237 * Returns the appropriate {@link com.android.camera.MultiToggleImageButton} 238 * based on button id. An IllegalStateException will be throw if the 239 * button could not be found in the view hierarchy. 240 */ getButtonOrError(int buttonId)241 private MultiToggleImageButton getButtonOrError(int buttonId) { 242 switch (buttonId) { 243 case BUTTON_FLASH: 244 if (mButtonFlash == null) { 245 throw new IllegalStateException("Flash button could not be found."); 246 } 247 return mButtonFlash; 248 case BUTTON_TORCH: 249 if (mButtonFlash == null) { 250 throw new IllegalStateException("Torch button could not be found."); 251 } 252 return mButtonFlash; 253 case BUTTON_HDR_PLUS_FLASH: 254 if (mButtonFlash == null) { 255 throw new IllegalStateException("Hdr plus torch button could not be found."); 256 } 257 return mButtonFlash; 258 case BUTTON_CAMERA: 259 if (mButtonCamera == null) { 260 throw new IllegalStateException("Camera button could not be found."); 261 } 262 return mButtonCamera; 263 case BUTTON_HDR_PLUS: 264 if (mButtonHdr == null) { 265 throw new IllegalStateException("Hdr plus button could not be found."); 266 } 267 return mButtonHdr; 268 case BUTTON_HDR: 269 if (mButtonHdr == null) { 270 throw new IllegalStateException("Hdr button could not be found."); 271 } 272 return mButtonHdr; 273 case BUTTON_GRID_LINES: 274 if (mButtonGridlines == null) { 275 throw new IllegalStateException("Grid lines button could not be found."); 276 } 277 return mButtonGridlines; 278 case BUTTON_COUNTDOWN: 279 if (mButtonCountdown == null) { 280 throw new IllegalStateException("Countdown button could not be found."); 281 } 282 return mButtonCountdown; 283 default: 284 throw new IllegalArgumentException("button not known by id=" + buttonId); 285 } 286 } 287 288 /** 289 * Returns the appropriate {@link android.widget.ImageButton} 290 * based on button id. An IllegalStateException will be throw if the 291 * button could not be found in the view hierarchy. 292 */ getImageButtonOrError(int buttonId)293 private ImageButton getImageButtonOrError(int buttonId) { 294 switch (buttonId) { 295 case BUTTON_CANCEL: 296 if (mButtonCancel == null) { 297 throw new IllegalStateException("Cancel button could not be found."); 298 } 299 return mButtonCancel; 300 case BUTTON_DONE: 301 if (mButtonDone == null) { 302 throw new IllegalStateException("Done button could not be found."); 303 } 304 return mButtonDone; 305 case BUTTON_RETAKE: 306 if (mButtonRetake == null) { 307 throw new IllegalStateException("Retake button could not be found."); 308 } 309 return mButtonRetake; 310 case BUTTON_REVIEW: 311 if (mButtonRetake == null) { 312 throw new IllegalStateException("Review button could not be found."); 313 } 314 return mButtonRetake; 315 case BUTTON_EXPOSURE_COMPENSATION: 316 if (mButtonExposureCompensation == null) { 317 throw new IllegalStateException("Exposure Compensation button could not be found."); 318 } 319 return mButtonExposureCompensation; 320 default: 321 throw new IllegalArgumentException("button not known by id=" + buttonId); 322 } 323 } 324 325 /** 326 * Initialize a known button by id, with a state change callback and 327 * a resource id that points to an array of drawables, and then enable 328 * the button. 329 */ initializeButton(int buttonId, ButtonCallback cb)330 public void initializeButton(int buttonId, ButtonCallback cb) { 331 MultiToggleImageButton button = getButtonOrError(buttonId); 332 switch (buttonId) { 333 case BUTTON_FLASH: 334 initializeFlashButton(button, cb, R.array.camera_flashmode_icons); 335 break; 336 case BUTTON_TORCH: 337 initializeTorchButton(button, cb, R.array.video_flashmode_icons); 338 break; 339 case BUTTON_HDR_PLUS_FLASH: 340 initializeHdrPlusFlashButton(button, cb, R.array.camera_flashmode_icons); 341 break; 342 case BUTTON_CAMERA: 343 initializeCameraButton(button, cb, R.array.camera_id_icons); 344 break; 345 case BUTTON_HDR_PLUS: 346 initializeHdrPlusButton(button, cb, R.array.pref_camera_hdr_plus_icons); 347 break; 348 case BUTTON_HDR: 349 initializeHdrButton(button, cb, R.array.pref_camera_hdr_icons); 350 break; 351 case BUTTON_GRID_LINES: 352 initializeGridLinesButton(button, cb, R.array.grid_lines_icons); 353 break; 354 case BUTTON_COUNTDOWN: 355 initializeCountdownButton(button, cb, R.array.countdown_duration_icons); 356 break; 357 default: 358 throw new IllegalArgumentException("button not known by id=" + buttonId); 359 } 360 361 enableButton(buttonId); 362 } 363 364 /** 365 * Initialize a known button with a click listener and a resource id. 366 * Sets the button visible. 367 */ initializePushButton(int buttonId, View.OnClickListener cb, int imageId)368 public void initializePushButton(int buttonId, View.OnClickListener cb, 369 int imageId) { 370 ImageButton button = getImageButtonOrError(buttonId); 371 button.setOnClickListener(cb); 372 button.setImageResource(imageId); 373 374 if (!button.isEnabled()) { 375 button.setEnabled(true); 376 if (mListener != null) { 377 mListener.onButtonEnabledChanged(this, buttonId); 378 } 379 } 380 button.setTag(R.string.tag_enabled_id, buttonId); 381 382 if (button.getVisibility() != View.VISIBLE) { 383 button.setVisibility(View.VISIBLE); 384 if (mListener != null) { 385 mListener.onButtonVisibilityChanged(this, buttonId); 386 } 387 } 388 } 389 390 /** 391 * Initialize a known button with a click listener. Sets the button visible. 392 */ initializePushButton(int buttonId, View.OnClickListener cb)393 public void initializePushButton(int buttonId, View.OnClickListener cb) { 394 ImageButton button = getImageButtonOrError(buttonId); 395 if (cb != null) { 396 button.setOnClickListener(cb); 397 } 398 399 if (!button.isEnabled()) { 400 button.setEnabled(true); 401 if (mListener != null) { 402 mListener.onButtonEnabledChanged(this, buttonId); 403 } 404 } 405 button.setTag(R.string.tag_enabled_id, buttonId); 406 407 if (button.getVisibility() != View.VISIBLE) { 408 button.setVisibility(View.VISIBLE); 409 if (mListener != null) { 410 mListener.onButtonVisibilityChanged(this, buttonId); 411 } 412 } 413 } 414 415 /** 416 * Sets a button in its disabled (greyed out) state. 417 */ disableButton(int buttonId)418 public void disableButton(int buttonId) { 419 MultiToggleImageButton button = getButtonOrError(buttonId); 420 421 // HDR and HDR+ buttons share the same button object, 422 // but change actual image icons at runtime. 423 // This extra check is to ensure the correct icons are used 424 // in the case of the HDR[+] button being disabled at startup, 425 // e.g. app startup with front-facing camera. 426 // b/18104680 427 if (buttonId == BUTTON_HDR_PLUS) { 428 initializeHdrPlusButtonIcons(button, R.array.pref_camera_hdr_plus_icons); 429 } else if (buttonId == BUTTON_HDR) { 430 initializeHdrButtonIcons(button, R.array.pref_camera_hdr_icons); 431 } 432 433 if (button.isEnabled()) { 434 button.setEnabled(false); 435 if (mListener != null) { 436 mListener.onButtonEnabledChanged(this, buttonId); 437 } 438 } 439 button.setTag(R.string.tag_enabled_id, null); 440 441 if (button.getVisibility() != View.VISIBLE) { 442 button.setVisibility(View.VISIBLE); 443 if (mListener != null) { 444 mListener.onButtonVisibilityChanged(this, buttonId); 445 } 446 } 447 } 448 449 /** 450 * Enables a button that has already been initialized. 451 */ enableButton(int buttonId)452 public void enableButton(int buttonId) { 453 ImageButton button = getButtonOrError(buttonId); 454 if (!button.isEnabled()) { 455 button.setEnabled(true); 456 if (mListener != null) { 457 mListener.onButtonEnabledChanged(this, buttonId); 458 } 459 } 460 button.setTag(R.string.tag_enabled_id, buttonId); 461 462 if (button.getVisibility() != View.VISIBLE) { 463 button.setVisibility(View.VISIBLE); 464 if (mListener != null) { 465 mListener.onButtonVisibilityChanged(this, buttonId); 466 } 467 } 468 } 469 470 /** 471 * Disable click reactions for a button without affecting visual state. 472 * For most cases you'll want to use {@link #disableButton(int)}. 473 * @param buttonId The id of the button. 474 */ disableButtonClick(int buttonId)475 public void disableButtonClick(int buttonId) { 476 ImageButton button = getButtonOrError(buttonId); 477 if (button instanceof MultiToggleImageButton) { 478 ((MultiToggleImageButton) button).setClickEnabled(false); 479 } 480 } 481 482 /** 483 * Enable click reactions for a button without affecting visual state. 484 * For most cases you'll want to use {@link #enableButton(int)}. 485 * @param buttonId The id of the button. 486 */ enableButtonClick(int buttonId)487 public void enableButtonClick(int buttonId) { 488 ImageButton button = getButtonOrError(buttonId); 489 if (button instanceof MultiToggleImageButton) { 490 ((MultiToggleImageButton) button).setClickEnabled(true); 491 } 492 } 493 494 /** 495 * Hide a button by id. 496 */ hideButton(int buttonId)497 public void hideButton(int buttonId) { 498 View button; 499 try { 500 button = getButtonOrError(buttonId); 501 } catch (IllegalArgumentException e) { 502 button = getImageButtonOrError(buttonId); 503 } 504 if (button.getVisibility() == View.VISIBLE) { 505 button.setVisibility(View.GONE); 506 if (mListener != null) { 507 mListener.onButtonVisibilityChanged(this, buttonId); 508 } 509 } 510 } 511 setToInitialState()512 public void setToInitialState() { 513 mModeOptions.setMainBar(ModeOptions.BAR_STANDARD); 514 } 515 setExposureCompensationCallback(final CameraAppUI.BottomBarUISpec .ExposureCompensationSetCallback cb)516 public void setExposureCompensationCallback(final CameraAppUI.BottomBarUISpec 517 .ExposureCompensationSetCallback cb) { 518 if (cb == null) { 519 mModeOptionsExposure.setOnOptionClickListener(null); 520 } else { 521 mModeOptionsExposure 522 .setOnOptionClickListener(new RadioOptions.OnOptionClickListener() { 523 @Override 524 public void onOptionClicked(View v) { 525 int comp = Integer.parseInt((String)(v.getTag())); 526 527 if (mExposureCompensationStep != 0.0f) { 528 int compValue = 529 Math.round(comp / mExposureCompensationStep); 530 cb.setExposure(compValue); 531 } 532 } 533 }); 534 } 535 } 536 537 /** 538 * Set the exposure compensation parameters supported by the current camera mode. 539 * @param min Minimum exposure compensation value. 540 * @param max Maximum exposure compensation value. 541 * @param step Expsoure compensation step value. 542 */ setExposureCompensationParameters(int min, int max, float step)543 public void setExposureCompensationParameters(int min, int max, float step) { 544 mMaxExposureCompensation = max; 545 mMinExposureCompensation = min; 546 mExposureCompensationStep = step; 547 548 549 setVisible(mExposureN2, (Math.round(min * step) <= -2)); 550 setVisible(mExposureN1, (Math.round(min * step) <= -1)); 551 setVisible(mExposureP1, (Math.round(max * step) >= 1)); 552 setVisible(mExposureP2, (Math.round(max * step) >= 2)); 553 554 updateExposureButtons(); 555 } 556 setVisible(View v, boolean visible)557 private static void setVisible(View v, boolean visible) { 558 if (visible) { 559 v.setVisibility(View.VISIBLE); 560 } else { 561 v.setVisibility(View.INVISIBLE); 562 } 563 } 564 565 /** 566 * @return The exposure compensation step value. 567 **/ getExposureCompensationStep()568 public float getExposureCompensationStep() { 569 return mExposureCompensationStep; 570 } 571 572 /** 573 * Check if a button is enabled with the given button id.. 574 */ isEnabled(int buttonId)575 public boolean isEnabled(int buttonId) { 576 View button; 577 try { 578 button = getButtonOrError(buttonId); 579 } catch (IllegalArgumentException e) { 580 button = getImageButtonOrError(buttonId); 581 } 582 583 Integer enabledId = (Integer) button.getTag(R.string.tag_enabled_id); 584 if (enabledId != null) { 585 return (enabledId.intValue() == buttonId) && button.isEnabled(); 586 } else { 587 return false; 588 } 589 } 590 591 /** 592 * Check if a button is visible. 593 */ isVisible(int buttonId)594 public boolean isVisible(int buttonId) { 595 View button; 596 try { 597 button = getButtonOrError(buttonId); 598 } catch (IllegalArgumentException e) { 599 button = getImageButtonOrError(buttonId); 600 } 601 return (button.getVisibility() == View.VISIBLE); 602 } 603 604 /** 605 * Initialize a flash button. 606 */ initializeFlashButton(MultiToggleImageButton button, final ButtonCallback cb, int resIdImages)607 private void initializeFlashButton(MultiToggleImageButton button, 608 final ButtonCallback cb, int resIdImages) { 609 610 if (resIdImages > 0) { 611 button.overrideImageIds(resIdImages); 612 } 613 button.overrideContentDescriptions(R.array.camera_flash_descriptions); 614 615 int index = mSettingsManager.getIndexOfCurrentValue(mAppController.getCameraScope(), 616 Keys.KEY_FLASH_MODE); 617 button.setState(index >= 0 ? index : 0, false); 618 619 button.setOnStateChangeListener(new MultiToggleImageButton.OnStateChangeListener() { 620 @Override 621 public void stateChanged(View view, int state) { 622 mSettingsManager.setValueByIndex(mAppController.getCameraScope(), 623 Keys.KEY_FLASH_MODE, state); 624 if (cb != null) { 625 cb.onStateChanged(state); 626 } 627 } 628 }); 629 } 630 631 /** 632 * Initialize video torch button 633 */ initializeTorchButton(MultiToggleImageButton button, final ButtonCallback cb, int resIdImages)634 private void initializeTorchButton(MultiToggleImageButton button, 635 final ButtonCallback cb, int resIdImages) { 636 637 if (resIdImages > 0) { 638 button.overrideImageIds(resIdImages); 639 } 640 button.overrideContentDescriptions(R.array.video_flash_descriptions); 641 642 int index = mSettingsManager.getIndexOfCurrentValue(mAppController.getCameraScope(), 643 Keys.KEY_VIDEOCAMERA_FLASH_MODE); 644 button.setState(index >= 0 ? index : 0, false); 645 646 button.setOnStateChangeListener(new MultiToggleImageButton.OnStateChangeListener() { 647 @Override 648 public void stateChanged(View view, int state) { 649 mSettingsManager.setValueByIndex(mAppController.getCameraScope(), 650 Keys.KEY_VIDEOCAMERA_FLASH_MODE, state); 651 if (cb != null) { 652 cb.onStateChanged(state); 653 } 654 } 655 }); 656 } 657 658 /** 659 * Initialize hdr plus flash button 660 */ initializeHdrPlusFlashButton(MultiToggleImageButton button, final ButtonCallback cb, int resIdImages)661 private void initializeHdrPlusFlashButton(MultiToggleImageButton button, 662 final ButtonCallback cb, int resIdImages) { 663 664 if (resIdImages > 0) { 665 button.overrideImageIds(resIdImages); 666 } 667 button.overrideContentDescriptions(R.array.hdr_plus_flash_descriptions); 668 669 int index = mSettingsManager.getIndexOfCurrentValue(mAppController.getModuleScope(), 670 Keys.KEY_HDR_PLUS_FLASH_MODE); 671 button.setState(index >= 0 ? index : 0, false); 672 673 button.setOnStateChangeListener(new MultiToggleImageButton.OnStateChangeListener() { 674 @Override 675 public void stateChanged(View view, int state) { 676 mSettingsManager.setValueByIndex(mAppController.getModuleScope(), 677 Keys.KEY_HDR_PLUS_FLASH_MODE, state); 678 if (cb != null) { 679 cb.onStateChanged(state); 680 } 681 } 682 }); 683 } 684 685 /** 686 * Initialize a camera button. 687 */ initializeCameraButton(final MultiToggleImageButton button, final ButtonCallback cb, int resIdImages)688 private void initializeCameraButton(final MultiToggleImageButton button, 689 final ButtonCallback cb, int resIdImages) { 690 691 if (resIdImages > 0) { 692 button.overrideImageIds(resIdImages); 693 } 694 695 int index = mSettingsManager.getIndexOfCurrentValue(mAppController.getModuleScope(), 696 Keys.KEY_CAMERA_ID); 697 button.setState(index >= 0 ? index : 0, false); 698 699 button.setOnStateChangeListener(new MultiToggleImageButton.OnStateChangeListener() { 700 @Override 701 public void stateChanged(View view, int state) { 702 mSettingsManager.setValueByIndex(mAppController.getModuleScope(), 703 Keys.KEY_CAMERA_ID, state); 704 int cameraId = mSettingsManager.getInteger(mAppController.getModuleScope(), 705 Keys.KEY_CAMERA_ID); 706 // This is a quick fix for ISE in Gcam module which can be 707 // found by rapid pressing camera switch button. The assumption 708 // here is that each time this button is clicked, the listener 709 // will do something and then enable this button again. 710 button.setEnabled(false); 711 if (cb != null) { 712 cb.onStateChanged(cameraId); 713 } 714 mAppController.getCameraAppUI().onChangeCamera(); 715 } 716 }); 717 } 718 719 /** 720 * Initialize an hdr plus button. 721 */ initializeHdrPlusButton(MultiToggleImageButton button, final ButtonCallback cb, int resIdImages)722 private void initializeHdrPlusButton(MultiToggleImageButton button, 723 final ButtonCallback cb, int resIdImages) { 724 725 initializeHdrPlusButtonIcons(button, resIdImages); 726 727 int index = mSettingsManager.getIndexOfCurrentValue(SettingsManager.SCOPE_GLOBAL, 728 Keys.KEY_CAMERA_HDR_PLUS); 729 button.setState(index >= 0 ? index : 0, false); 730 731 button.setOnStateChangeListener(new MultiToggleImageButton.OnStateChangeListener() { 732 @Override 733 public void stateChanged(View view, int state) { 734 mSettingsManager.setValueByIndex(SettingsManager.SCOPE_GLOBAL, 735 Keys.KEY_CAMERA_HDR_PLUS, state); 736 if (cb != null) { 737 cb.onStateChanged(state); 738 } 739 } 740 }); 741 } 742 initializeHdrPlusButtonIcons(MultiToggleImageButton button, int resIdImages)743 private void initializeHdrPlusButtonIcons(MultiToggleImageButton button, int resIdImages) { 744 if (resIdImages > 0) { 745 button.overrideImageIds(resIdImages); 746 } 747 button.overrideContentDescriptions(R.array.hdr_plus_descriptions); 748 } 749 750 /** 751 * Initialize an hdr button. 752 */ initializeHdrButton(MultiToggleImageButton button, final ButtonCallback cb, int resIdImages)753 private void initializeHdrButton(MultiToggleImageButton button, 754 final ButtonCallback cb, int resIdImages) { 755 756 initializeHdrButtonIcons(button, resIdImages); 757 758 int index = mSettingsManager.getIndexOfCurrentValue(SettingsManager.SCOPE_GLOBAL, 759 Keys.KEY_CAMERA_HDR); 760 button.setState(index >= 0 ? index : 0, false); 761 762 button.setOnStateChangeListener(new MultiToggleImageButton.OnStateChangeListener() { 763 @Override 764 public void stateChanged(View view, int state) { 765 mSettingsManager.setValueByIndex(SettingsManager.SCOPE_GLOBAL, 766 Keys.KEY_CAMERA_HDR, state); 767 if (cb != null) { 768 cb.onStateChanged(state); 769 } 770 } 771 }); 772 } 773 initializeHdrButtonIcons(MultiToggleImageButton button, int resIdImages)774 private void initializeHdrButtonIcons(MultiToggleImageButton button, int resIdImages) { 775 if (resIdImages > 0) { 776 button.overrideImageIds(resIdImages); 777 } 778 button.overrideContentDescriptions(R.array.hdr_descriptions); 779 } 780 781 /** 782 * Initialize a countdown timer button. 783 */ initializeCountdownButton(MultiToggleImageButton button, final ButtonCallback cb, int resIdImages)784 private void initializeCountdownButton(MultiToggleImageButton button, 785 final ButtonCallback cb, int resIdImages) { 786 if (resIdImages > 0) { 787 button.overrideImageIds(resIdImages); 788 } 789 790 int index = mSettingsManager.getIndexOfCurrentValue(SettingsManager.SCOPE_GLOBAL, 791 Keys.KEY_COUNTDOWN_DURATION); 792 button.setState(index >= 0 ? index : 0, false); 793 794 button.setOnStateChangeListener(new MultiToggleImageButton.OnStateChangeListener() { 795 @Override 796 public void stateChanged(View view, int state) { 797 mSettingsManager.setValueByIndex(SettingsManager.SCOPE_GLOBAL, 798 Keys.KEY_COUNTDOWN_DURATION, state); 799 if(cb != null) { 800 cb.onStateChanged(state); 801 } 802 } 803 }); 804 } 805 806 /** 807 * Update the visual state of the manual exposure buttons 808 */ updateExposureButtons()809 public void updateExposureButtons() { 810 int compValue = mSettingsManager.getInteger(mAppController.getCameraScope(), 811 Keys.KEY_EXPOSURE); 812 if (mExposureCompensationStep != 0.0f) { 813 int comp = Math.round(compValue * mExposureCompensationStep); 814 mModeOptionsExposure.setSelectedOptionByTag(String.valueOf(comp)); 815 } 816 } 817 818 /** 819 * Initialize a grid lines button. 820 */ initializeGridLinesButton(MultiToggleImageButton button, final ButtonCallback cb, int resIdImages)821 private void initializeGridLinesButton(MultiToggleImageButton button, 822 final ButtonCallback cb, int resIdImages) { 823 824 if (resIdImages > 0) { 825 button.overrideImageIds(resIdImages); 826 } 827 button.overrideContentDescriptions(R.array.grid_lines_descriptions); 828 829 button.setOnStateChangeListener(new MultiToggleImageButton.OnStateChangeListener() { 830 @Override 831 public void stateChanged(View view, int state) { 832 mSettingsManager.setValueByIndex(SettingsManager.SCOPE_GLOBAL, 833 Keys.KEY_CAMERA_GRID_LINES, state); 834 if (cb != null) { 835 cb.onStateChanged(state); 836 } 837 } 838 }); 839 840 int index = mSettingsManager.getIndexOfCurrentValue(SettingsManager.SCOPE_GLOBAL, 841 Keys.KEY_CAMERA_GRID_LINES); 842 button.setState(index >= 0 ? index : 0, true); 843 } 844 isPanoEnabled()845 public boolean isPanoEnabled() { 846 return mModeOptions.getMainBar() == ModeOptions.BAR_PANO; 847 } 848 849 /** 850 * Initialize a panorama orientation buttons. 851 */ initializePanoOrientationButtons(final ButtonCallback cb)852 public void initializePanoOrientationButtons(final ButtonCallback cb) { 853 int resIdImages = PhotoSphereHelper.getPanoramaOrientationOptionArrayId(); 854 int resIdDescriptions = PhotoSphereHelper.getPanoramaOrientationDescriptions(); 855 if (resIdImages > 0) { 856 TypedArray imageIds = null; 857 TypedArray descriptionIds = null; 858 try { 859 mModeOptions.setMainBar(ModeOptions.BAR_PANO); 860 imageIds = mAppController 861 .getAndroidContext().getResources().obtainTypedArray(resIdImages); 862 descriptionIds = mAppController 863 .getAndroidContext().getResources().obtainTypedArray(resIdDescriptions); 864 mModeOptionsPano.removeAllViews(); 865 final boolean isHorizontal = 866 (mModeOptionsPano.getOrientation() == LinearLayout.HORIZONTAL); 867 final int numImageIds = imageIds.length(); 868 for (int index = 0; index < numImageIds; index++) { 869 int i; 870 // if in portrait orientation (pano bar horizonal), order buttons normally 871 // if in landscape orientation (pano bar vertical), reverse button order 872 if (isHorizontal) { 873 i = index; 874 } else { 875 i = numImageIds - index - 1; 876 } 877 878 int imageId = imageIds.getResourceId(i, 0); 879 if (imageId > 0) { 880 ImageButton imageButton = (ImageButton) LayoutInflater 881 .from(mAppController.getAndroidContext()) 882 .inflate(R.layout.mode_options_imagebutton_template, 883 mModeOptionsPano, false); 884 imageButton.setImageResource(imageId); 885 imageButton.setTag(String.valueOf(i)); 886 mModeOptionsPano.addView(imageButton); 887 888 int descriptionId = descriptionIds.getResourceId(i, 0); 889 if (descriptionId > 0) { 890 imageButton.setContentDescription( 891 mAppController.getAndroidContext().getString(descriptionId)); 892 } 893 } 894 } 895 mModeOptionsPano.updateListeners(); 896 mModeOptionsPano 897 .setOnOptionClickListener(new RadioOptions.OnOptionClickListener() { 898 @Override 899 public void onOptionClicked(View v) { 900 if (cb != null) { 901 int state = Integer.parseInt((String)v.getTag()); 902 mSettingsManager.setValueByIndex(SettingsManager.SCOPE_GLOBAL, 903 Keys.KEY_CAMERA_PANO_ORIENTATION, 904 state); 905 cb.onStateChanged(state); 906 } 907 } 908 }); 909 updatePanoButtons(); 910 } finally { 911 if (imageIds != null) { 912 imageIds.recycle(); 913 } 914 if (descriptionIds != null) { 915 descriptionIds.recycle(); 916 } 917 } 918 } 919 } 920 updatePanoButtons()921 private void updatePanoButtons() { 922 int modeIndex = mSettingsManager.getIndexOfCurrentValue(SettingsManager.SCOPE_GLOBAL, 923 Keys.KEY_CAMERA_PANO_ORIENTATION); 924 mModeOptionsPano.setSelectedOptionByTag(String.valueOf(modeIndex)); 925 } 926 } 927