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 if (button.isEnabled()) { 421 button.setEnabled(false); 422 if (mListener != null) { 423 mListener.onButtonEnabledChanged(this, buttonId); 424 } 425 } 426 button.setTag(R.string.tag_enabled_id, null); 427 428 if (button.getVisibility() != View.VISIBLE) { 429 button.setVisibility(View.VISIBLE); 430 if (mListener != null) { 431 mListener.onButtonVisibilityChanged(this, buttonId); 432 } 433 } 434 } 435 436 /** 437 * Enables a button that has already been initialized. 438 */ enableButton(int buttonId)439 public void enableButton(int buttonId) { 440 ImageButton button = getButtonOrError(buttonId); 441 if (!button.isEnabled()) { 442 button.setEnabled(true); 443 if (mListener != null) { 444 mListener.onButtonEnabledChanged(this, buttonId); 445 } 446 } 447 button.setTag(R.string.tag_enabled_id, buttonId); 448 449 if (button.getVisibility() != View.VISIBLE) { 450 button.setVisibility(View.VISIBLE); 451 if (mListener != null) { 452 mListener.onButtonVisibilityChanged(this, buttonId); 453 } 454 } 455 } 456 457 /** 458 * Disable click reactions for a button without affecting visual state. 459 * For most cases you'll want to use {@link #disableButton(int)}. 460 * @param buttonId The id of the button. 461 */ disableButtonClick(int buttonId)462 public void disableButtonClick(int buttonId) { 463 ImageButton button = getButtonOrError(buttonId); 464 if (button instanceof MultiToggleImageButton) { 465 ((MultiToggleImageButton) button).setClickEnabled(false); 466 } 467 } 468 469 /** 470 * Enable click reactions for a button without affecting visual state. 471 * For most cases you'll want to use {@link #enableButton(int)}. 472 * @param buttonId The id of the button. 473 */ enableButtonClick(int buttonId)474 public void enableButtonClick(int buttonId) { 475 ImageButton button = getButtonOrError(buttonId); 476 if (button instanceof MultiToggleImageButton) { 477 ((MultiToggleImageButton) button).setClickEnabled(true); 478 } 479 } 480 481 /** 482 * Hide a button by id. 483 */ hideButton(int buttonId)484 public void hideButton(int buttonId) { 485 View button; 486 try { 487 button = getButtonOrError(buttonId); 488 } catch (IllegalArgumentException e) { 489 button = getImageButtonOrError(buttonId); 490 } 491 if (button.getVisibility() == View.VISIBLE) { 492 button.setVisibility(View.GONE); 493 if (mListener != null) { 494 mListener.onButtonVisibilityChanged(this, buttonId); 495 } 496 } 497 } 498 setToInitialState()499 public void setToInitialState() { 500 mModeOptions.setMainBar(ModeOptions.BAR_STANDARD); 501 } 502 setExposureCompensationCallback(final CameraAppUI.BottomBarUISpec .ExposureCompensationSetCallback cb)503 public void setExposureCompensationCallback(final CameraAppUI.BottomBarUISpec 504 .ExposureCompensationSetCallback cb) { 505 if (cb == null) { 506 mModeOptionsExposure.setOnOptionClickListener(null); 507 } else { 508 mModeOptionsExposure 509 .setOnOptionClickListener(new RadioOptions.OnOptionClickListener() { 510 @Override 511 public void onOptionClicked(View v) { 512 int comp = Integer.parseInt((String)(v.getTag())); 513 514 if (mExposureCompensationStep != 0.0f) { 515 int compValue = 516 Math.round(comp / mExposureCompensationStep); 517 cb.setExposure(compValue); 518 } 519 } 520 }); 521 } 522 } 523 524 /** 525 * Set the exposure compensation parameters supported by the current camera mode. 526 * @param min Minimum exposure compensation value. 527 * @param max Maximum exposure compensation value. 528 * @param step Expsoure compensation step value. 529 */ setExposureCompensationParameters(int min, int max, float step)530 public void setExposureCompensationParameters(int min, int max, float step) { 531 mMaxExposureCompensation = max; 532 mMinExposureCompensation = min; 533 mExposureCompensationStep = step; 534 535 536 setVisible(mExposureN2, (Math.round(min * step) <= -2)); 537 setVisible(mExposureN1, (Math.round(min * step) <= -1)); 538 setVisible(mExposureP1, (Math.round(max * step) >= 1)); 539 setVisible(mExposureP2, (Math.round(max * step) >= 2)); 540 541 updateExposureButtons(); 542 } 543 setVisible(View v, boolean visible)544 private static void setVisible(View v, boolean visible) { 545 if (visible) { 546 v.setVisibility(View.VISIBLE); 547 } else { 548 v.setVisibility(View.INVISIBLE); 549 } 550 } 551 552 /** 553 * @return The exposure compensation step value. 554 **/ getExposureCompensationStep()555 public float getExposureCompensationStep() { 556 return mExposureCompensationStep; 557 } 558 559 /** 560 * Check if a button is enabled with the given button id.. 561 */ isEnabled(int buttonId)562 public boolean isEnabled(int buttonId) { 563 View button; 564 try { 565 button = getButtonOrError(buttonId); 566 } catch (IllegalArgumentException e) { 567 button = getImageButtonOrError(buttonId); 568 } 569 570 Integer enabledId = (Integer) button.getTag(R.string.tag_enabled_id); 571 if (enabledId != null) { 572 return (enabledId.intValue() == buttonId) && button.isEnabled(); 573 } else { 574 return false; 575 } 576 } 577 578 /** 579 * Check if a button is visible. 580 */ isVisible(int buttonId)581 public boolean isVisible(int buttonId) { 582 View button; 583 try { 584 button = getButtonOrError(buttonId); 585 } catch (IllegalArgumentException e) { 586 button = getImageButtonOrError(buttonId); 587 } 588 return (button.getVisibility() == View.VISIBLE); 589 } 590 591 /** 592 * Initialize a flash button. 593 */ initializeFlashButton(MultiToggleImageButton button, final ButtonCallback cb, int resIdImages)594 private void initializeFlashButton(MultiToggleImageButton button, 595 final ButtonCallback cb, int resIdImages) { 596 597 if (resIdImages > 0) { 598 button.overrideImageIds(resIdImages); 599 } 600 button.overrideContentDescriptions(R.array.camera_flash_descriptions); 601 602 int index = mSettingsManager.getIndexOfCurrentValue(mAppController.getCameraScope(), 603 Keys.KEY_FLASH_MODE); 604 button.setState(index >= 0 ? index : 0, false); 605 606 button.setOnStateChangeListener(new MultiToggleImageButton.OnStateChangeListener() { 607 @Override 608 public void stateChanged(View view, int state) { 609 mSettingsManager.setValueByIndex(mAppController.getCameraScope(), 610 Keys.KEY_FLASH_MODE, state); 611 if (cb != null) { 612 cb.onStateChanged(state); 613 } 614 } 615 }); 616 } 617 618 /** 619 * Initialize video torch button 620 */ initializeTorchButton(MultiToggleImageButton button, final ButtonCallback cb, int resIdImages)621 private void initializeTorchButton(MultiToggleImageButton button, 622 final ButtonCallback cb, int resIdImages) { 623 624 if (resIdImages > 0) { 625 button.overrideImageIds(resIdImages); 626 } 627 button.overrideContentDescriptions(R.array.video_flash_descriptions); 628 629 int index = mSettingsManager.getIndexOfCurrentValue(mAppController.getCameraScope(), 630 Keys.KEY_VIDEOCAMERA_FLASH_MODE); 631 button.setState(index >= 0 ? index : 0, false); 632 633 button.setOnStateChangeListener(new MultiToggleImageButton.OnStateChangeListener() { 634 @Override 635 public void stateChanged(View view, int state) { 636 mSettingsManager.setValueByIndex(mAppController.getCameraScope(), 637 Keys.KEY_VIDEOCAMERA_FLASH_MODE, state); 638 if (cb != null) { 639 cb.onStateChanged(state); 640 } 641 } 642 }); 643 } 644 645 /** 646 * Initialize hdr plus flash button 647 */ initializeHdrPlusFlashButton(MultiToggleImageButton button, final ButtonCallback cb, int resIdImages)648 private void initializeHdrPlusFlashButton(MultiToggleImageButton button, 649 final ButtonCallback cb, int resIdImages) { 650 651 if (resIdImages > 0) { 652 button.overrideImageIds(resIdImages); 653 } 654 button.overrideContentDescriptions(R.array.hdr_plus_flash_descriptions); 655 656 int index = mSettingsManager.getIndexOfCurrentValue(mAppController.getModuleScope(), 657 Keys.KEY_HDR_PLUS_FLASH_MODE); 658 button.setState(index >= 0 ? index : 0, false); 659 660 button.setOnStateChangeListener(new MultiToggleImageButton.OnStateChangeListener() { 661 @Override 662 public void stateChanged(View view, int state) { 663 mSettingsManager.setValueByIndex(mAppController.getModuleScope(), 664 Keys.KEY_HDR_PLUS_FLASH_MODE, state); 665 if (cb != null) { 666 cb.onStateChanged(state); 667 } 668 } 669 }); 670 } 671 672 /** 673 * Initialize a camera button. 674 */ initializeCameraButton(final MultiToggleImageButton button, final ButtonCallback cb, int resIdImages)675 private void initializeCameraButton(final MultiToggleImageButton button, 676 final ButtonCallback cb, int resIdImages) { 677 678 if (resIdImages > 0) { 679 button.overrideImageIds(resIdImages); 680 } 681 682 int index = mSettingsManager.getIndexOfCurrentValue(mAppController.getModuleScope(), 683 Keys.KEY_CAMERA_ID); 684 button.setState(index >= 0 ? index : 0, false); 685 686 button.setOnStateChangeListener(new MultiToggleImageButton.OnStateChangeListener() { 687 @Override 688 public void stateChanged(View view, int state) { 689 mSettingsManager.setValueByIndex(mAppController.getModuleScope(), 690 Keys.KEY_CAMERA_ID, state); 691 int cameraId = mSettingsManager.getInteger(mAppController.getModuleScope(), 692 Keys.KEY_CAMERA_ID); 693 // This is a quick fix for ISE in Gcam module which can be 694 // found by rapid pressing camera switch button. The assumption 695 // here is that each time this button is clicked, the listener 696 // will do something and then enable this button again. 697 button.setEnabled(false); 698 if (cb != null) { 699 cb.onStateChanged(cameraId); 700 } 701 mAppController.getCameraAppUI().onChangeCamera(); 702 } 703 }); 704 } 705 706 /** 707 * Initialize an hdr plus button. 708 */ initializeHdrPlusButton(MultiToggleImageButton button, final ButtonCallback cb, int resIdImages)709 private void initializeHdrPlusButton(MultiToggleImageButton button, 710 final ButtonCallback cb, int resIdImages) { 711 712 if (resIdImages > 0) { 713 button.overrideImageIds(resIdImages); 714 } 715 button.overrideContentDescriptions(R.array.hdr_plus_descriptions); 716 717 int index = mSettingsManager.getIndexOfCurrentValue(SettingsManager.SCOPE_GLOBAL, 718 Keys.KEY_CAMERA_HDR_PLUS); 719 button.setState(index >= 0 ? index : 0, false); 720 721 button.setOnStateChangeListener(new MultiToggleImageButton.OnStateChangeListener() { 722 @Override 723 public void stateChanged(View view, int state) { 724 mSettingsManager.setValueByIndex(SettingsManager.SCOPE_GLOBAL, 725 Keys.KEY_CAMERA_HDR_PLUS, state); 726 if (cb != null) { 727 cb.onStateChanged(state); 728 } 729 } 730 }); 731 } 732 733 /** 734 * Initialize an hdr button. 735 */ initializeHdrButton(MultiToggleImageButton button, final ButtonCallback cb, int resIdImages)736 private void initializeHdrButton(MultiToggleImageButton button, 737 final ButtonCallback cb, int resIdImages) { 738 739 if (resIdImages > 0) { 740 button.overrideImageIds(resIdImages); 741 } 742 button.overrideContentDescriptions(R.array.hdr_descriptions); 743 744 int index = mSettingsManager.getIndexOfCurrentValue(SettingsManager.SCOPE_GLOBAL, 745 Keys.KEY_CAMERA_HDR); 746 button.setState(index >= 0 ? index : 0, false); 747 748 button.setOnStateChangeListener(new MultiToggleImageButton.OnStateChangeListener() { 749 @Override 750 public void stateChanged(View view, int state) { 751 mSettingsManager.setValueByIndex(SettingsManager.SCOPE_GLOBAL, 752 Keys.KEY_CAMERA_HDR, state); 753 if (cb != null) { 754 cb.onStateChanged(state); 755 } 756 } 757 }); 758 } 759 760 /** 761 * Initialize a countdown timer button. 762 */ initializeCountdownButton(MultiToggleImageButton button, final ButtonCallback cb, int resIdImages)763 private void initializeCountdownButton(MultiToggleImageButton button, 764 final ButtonCallback cb, int resIdImages) { 765 if (resIdImages > 0) { 766 button.overrideImageIds(resIdImages); 767 } 768 769 int index = mSettingsManager.getIndexOfCurrentValue(SettingsManager.SCOPE_GLOBAL, 770 Keys.KEY_COUNTDOWN_DURATION); 771 button.setState(index >= 0 ? index : 0, false); 772 773 button.setOnStateChangeListener(new MultiToggleImageButton.OnStateChangeListener() { 774 @Override 775 public void stateChanged(View view, int state) { 776 mSettingsManager.setValueByIndex(SettingsManager.SCOPE_GLOBAL, 777 Keys.KEY_COUNTDOWN_DURATION, state); 778 if(cb != null) { 779 cb.onStateChanged(state); 780 } 781 } 782 }); 783 } 784 785 /** 786 * Update the visual state of the manual exposure buttons 787 */ updateExposureButtons()788 public void updateExposureButtons() { 789 int compValue = mSettingsManager.getInteger(mAppController.getCameraScope(), 790 Keys.KEY_EXPOSURE); 791 if (mExposureCompensationStep != 0.0f) { 792 int comp = Math.round(compValue * mExposureCompensationStep); 793 mModeOptionsExposure.setSelectedOptionByTag(String.valueOf(comp)); 794 } 795 } 796 797 /** 798 * Initialize a grid lines button. 799 */ initializeGridLinesButton(MultiToggleImageButton button, final ButtonCallback cb, int resIdImages)800 private void initializeGridLinesButton(MultiToggleImageButton button, 801 final ButtonCallback cb, int resIdImages) { 802 803 if (resIdImages > 0) { 804 button.overrideImageIds(resIdImages); 805 } 806 button.overrideContentDescriptions(R.array.grid_lines_descriptions); 807 808 button.setOnStateChangeListener(new MultiToggleImageButton.OnStateChangeListener() { 809 @Override 810 public void stateChanged(View view, int state) { 811 mSettingsManager.setValueByIndex(SettingsManager.SCOPE_GLOBAL, 812 Keys.KEY_CAMERA_GRID_LINES, state); 813 if (cb != null) { 814 cb.onStateChanged(state); 815 } 816 } 817 }); 818 819 int index = mSettingsManager.getIndexOfCurrentValue(SettingsManager.SCOPE_GLOBAL, 820 Keys.KEY_CAMERA_GRID_LINES); 821 button.setState(index >= 0 ? index : 0, true); 822 } 823 isPanoEnabled()824 public boolean isPanoEnabled() { 825 return mModeOptions.getMainBar() == ModeOptions.BAR_PANO; 826 } 827 828 /** 829 * Initialize a panorama orientation buttons. 830 */ initializePanoOrientationButtons(final ButtonCallback cb)831 public void initializePanoOrientationButtons(final ButtonCallback cb) { 832 int resIdImages = PhotoSphereHelper.getPanoramaOrientationOptionArrayId(); 833 int resIdDescriptions = PhotoSphereHelper.getPanoramaOrientationDescriptions(); 834 if (resIdImages > 0) { 835 TypedArray imageIds = null; 836 TypedArray descriptionIds = null; 837 try { 838 mModeOptions.setMainBar(ModeOptions.BAR_PANO); 839 imageIds = mAppController 840 .getAndroidContext().getResources().obtainTypedArray(resIdImages); 841 descriptionIds = mAppController 842 .getAndroidContext().getResources().obtainTypedArray(resIdDescriptions); 843 mModeOptionsPano.removeAllViews(); 844 final boolean isHorizontal = 845 (mModeOptionsPano.getOrientation() == LinearLayout.HORIZONTAL); 846 final int numImageIds = imageIds.length(); 847 for (int index = 0; index < numImageIds; index++) { 848 int i; 849 // if in portrait orientation (pano bar horizonal), order buttons normally 850 // if in landscape orientation (pano bar vertical), reverse button order 851 if (isHorizontal) { 852 i = index; 853 } else { 854 i = numImageIds - index - 1; 855 } 856 857 int imageId = imageIds.getResourceId(i, 0); 858 if (imageId > 0) { 859 ImageButton imageButton = (ImageButton) LayoutInflater 860 .from(mAppController.getAndroidContext()) 861 .inflate(R.layout.mode_options_imagebutton_template, 862 mModeOptionsPano, false); 863 imageButton.setImageResource(imageId); 864 imageButton.setTag(String.valueOf(i)); 865 mModeOptionsPano.addView(imageButton); 866 867 int descriptionId = descriptionIds.getResourceId(i, 0); 868 if (descriptionId > 0) { 869 imageButton.setContentDescription( 870 mAppController.getAndroidContext().getString(descriptionId)); 871 } 872 } 873 } 874 mModeOptionsPano.updateListeners(); 875 mModeOptionsPano 876 .setOnOptionClickListener(new RadioOptions.OnOptionClickListener() { 877 @Override 878 public void onOptionClicked(View v) { 879 if (cb != null) { 880 int state = Integer.parseInt((String)v.getTag()); 881 mSettingsManager.setValueByIndex(SettingsManager.SCOPE_GLOBAL, 882 Keys.KEY_CAMERA_PANO_ORIENTATION, 883 state); 884 cb.onStateChanged(state); 885 } 886 } 887 }); 888 updatePanoButtons(); 889 } finally { 890 if (imageIds != null) { 891 imageIds.recycle(); 892 } 893 if (descriptionIds != null) { 894 descriptionIds.recycle(); 895 } 896 } 897 } 898 } 899 updatePanoButtons()900 private void updatePanoButtons() { 901 int modeIndex = mSettingsManager.getIndexOfCurrentValue(SettingsManager.SCOPE_GLOBAL, 902 Keys.KEY_CAMERA_PANO_ORIENTATION); 903 mModeOptionsPano.setSelectedOptionByTag(String.valueOf(modeIndex)); 904 } 905 } 906