PhotoPage.java revision 88cc2ca5f5596762a5546ec7426756f2036be455
1/* 2 * Copyright (C) 2010 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.gallery3d.app; 18 19import android.app.ActionBar.OnMenuVisibilityListener; 20import android.app.Activity; 21import android.content.ActivityNotFoundException; 22import android.content.Context; 23import android.content.Intent; 24import android.graphics.Rect; 25import android.net.Uri; 26import android.nfc.NfcAdapter; 27import android.os.Bundle; 28import android.os.Handler; 29import android.os.Message; 30import android.view.Menu; 31import android.view.MenuInflater; 32import android.view.MenuItem; 33import android.view.View; 34import android.view.WindowManager; 35import android.widget.ShareActionProvider; 36import android.widget.Toast; 37 38import com.android.gallery3d.R; 39import com.android.gallery3d.data.DataManager; 40import com.android.gallery3d.data.MediaDetails; 41import com.android.gallery3d.data.MediaItem; 42import com.android.gallery3d.data.MediaObject; 43import com.android.gallery3d.data.MediaSet; 44import com.android.gallery3d.data.MtpDevice; 45import com.android.gallery3d.data.Path; 46import com.android.gallery3d.data.SnailSource; 47import com.android.gallery3d.picasasource.PicasaSource; 48import com.android.gallery3d.ui.DetailsHelper; 49import com.android.gallery3d.ui.DetailsHelper.CloseListener; 50import com.android.gallery3d.ui.DetailsHelper.DetailsSource; 51import com.android.gallery3d.ui.GLCanvas; 52import com.android.gallery3d.ui.GLView; 53import com.android.gallery3d.ui.ImportCompleteListener; 54import com.android.gallery3d.ui.MenuExecutor; 55import com.android.gallery3d.ui.PhotoView; 56import com.android.gallery3d.ui.ScreenNail; 57import com.android.gallery3d.ui.SelectionManager; 58import com.android.gallery3d.ui.SynchronizedHandler; 59import com.android.gallery3d.util.GalleryUtils; 60 61public class PhotoPage extends ActivityState implements 62 PhotoView.Listener, OrientationManager.Listener, AppBridge.Server { 63 private static final String TAG = "PhotoPage"; 64 65 private static final int MSG_HIDE_BARS = 1; 66 private static final int MSG_LOCK_ORIENTATION = 2; 67 private static final int MSG_UNLOCK_ORIENTATION = 3; 68 private static final int MSG_ON_FULL_SCREEN_CHANGED = 4; 69 private static final int MSG_UPDATE_ACTION_BAR = 5; 70 71 private static final int HIDE_BARS_TIMEOUT = 3500; 72 73 private static final int REQUEST_SLIDESHOW = 1; 74 private static final int REQUEST_CROP = 2; 75 private static final int REQUEST_CROP_PICASA = 3; 76 private static final int REQUEST_EDIT = 4; 77 78 public static final String KEY_MEDIA_SET_PATH = "media-set-path"; 79 public static final String KEY_MEDIA_ITEM_PATH = "media-item-path"; 80 public static final String KEY_INDEX_HINT = "index-hint"; 81 public static final String KEY_OPEN_ANIMATION_RECT = "open-animation-rect"; 82 public static final String KEY_APP_BRIDGE = "app-bridge"; 83 84 public static final String KEY_RETURN_INDEX_HINT = "return-index-hint"; 85 86 private GalleryApp mApplication; 87 private SelectionManager mSelectionManager; 88 89 private PhotoView mPhotoView; 90 private PhotoPage.Model mModel; 91 private DetailsHelper mDetailsHelper; 92 private boolean mShowDetails; 93 private Path mPendingSharePath; 94 95 // mMediaSet could be null if there is no KEY_MEDIA_SET_PATH supplied. 96 // E.g., viewing a photo in gmail attachment 97 private MediaSet mMediaSet; 98 private Menu mMenu; 99 100 private int mCurrentIndex = 0; 101 private Handler mHandler; 102 private boolean mShowBars = true; 103 // The value of canShowBars() last time the bar updates state. 104 private boolean mCanShowBars = false; 105 private volatile boolean mActionBarAllowed = true; 106 private GalleryActionBar mActionBar; 107 private MyMenuVisibilityListener mMenuVisibilityListener; 108 private boolean mIsMenuVisible; 109 private MediaItem mCurrentPhoto = null; 110 private MenuExecutor mMenuExecutor; 111 private boolean mIsActive; 112 private ShareActionProvider mShareActionProvider; 113 private String mSetPathString; 114 // This is the original mSetPathString before adding the camera preview item. 115 private String mOriginalSetPathString; 116 private AppBridge mAppBridge; 117 private ScreenNail mScreenNail; 118 private MediaItem mScreenNailItem; 119 private OrientationManager mOrientationManager; 120 121 private NfcAdapter mNfcAdapter; 122 123 public static interface Model extends PhotoView.Model { 124 public void resume(); 125 public void pause(); 126 public boolean isEmpty(); 127 public MediaItem getCurrentMediaItem(); 128 public void setCurrentPhoto(Path path, int indexHint); 129 } 130 131 private class MyMenuVisibilityListener implements OnMenuVisibilityListener { 132 @Override 133 public void onMenuVisibilityChanged(boolean isVisible) { 134 mIsMenuVisible = isVisible; 135 refreshHidingMessage(); 136 } 137 } 138 139 private final GLView mRootPane = new GLView() { 140 141 @Override 142 protected void renderBackground(GLCanvas view) { 143 view.clearBuffer(); 144 } 145 146 @Override 147 protected void onLayout( 148 boolean changed, int left, int top, int right, int bottom) { 149 mPhotoView.layout(0, 0, right - left, bottom - top); 150 if (mShowDetails) { 151 mDetailsHelper.layout(left, mActionBar.getHeight(), right, bottom); 152 } 153 } 154 155 @Override 156 protected void orient(int displayRotation, int compensation) { 157 displayRotation = mOrientationManager.getDisplayRotation(); 158 Log.d(TAG, "orient -- display rotation " + displayRotation 159 + ", compensation = " + compensation); 160 super.orient(displayRotation, compensation); 161 } 162 }; 163 164 @Override 165 public void onCreate(Bundle data, Bundle restoreState) { 166 mActionBar = mActivity.getGalleryActionBar(); 167 mSelectionManager = new SelectionManager(mActivity, false); 168 mMenuExecutor = new MenuExecutor(mActivity, mSelectionManager); 169 170 mPhotoView = new PhotoView(mActivity); 171 mPhotoView.setListener(this); 172 mRootPane.addComponent(mPhotoView); 173 mApplication = (GalleryApp)((Activity) mActivity).getApplication(); 174 mOrientationManager = mActivity.getOrientationManager(); 175 mOrientationManager.addListener(this); 176 177 mSetPathString = data.getString(KEY_MEDIA_SET_PATH); 178 mOriginalSetPathString = mSetPathString; 179 mNfcAdapter = NfcAdapter.getDefaultAdapter(mActivity.getAndroidContext()); 180 Path itemPath = Path.fromString(data.getString(KEY_MEDIA_ITEM_PATH)); 181 182 if (mSetPathString != null) { 183 mAppBridge = (AppBridge) data.getParcelable(KEY_APP_BRIDGE); 184 if (mAppBridge != null) { 185 mOrientationManager.lockOrientation(); 186 187 // Get the ScreenNail from AppBridge and register it. 188 mScreenNail = mAppBridge.attachScreenNail(); 189 int id = SnailSource.registerScreenNail(mScreenNail); 190 Path screenNailSetPath = SnailSource.getSetPath(id); 191 Path screenNailItemPath = SnailSource.getItemPath(id); 192 mScreenNailItem = (MediaItem) mActivity.getDataManager() 193 .getMediaObject(screenNailItemPath); 194 195 // Combine the original MediaSet with the one for CameraScreenNail. 196 mSetPathString = "/combo/item/{" + screenNailSetPath + 197 "," + mSetPathString + "}"; 198 199 // Start from the screen nail. 200 itemPath = screenNailItemPath; 201 202 // Action bar should not be displayed when camera starts. 203 mFlags |= FLAG_HIDE_ACTION_BAR; 204 mShowBars = false; 205 } 206 207 mMediaSet = mActivity.getDataManager().getMediaSet(mSetPathString); 208 mCurrentIndex = data.getInt(KEY_INDEX_HINT, 0); 209 if (mMediaSet == null) { 210 Log.w(TAG, "failed to restore " + mSetPathString); 211 } 212 PhotoDataAdapter pda = new PhotoDataAdapter( 213 mActivity, mPhotoView, mMediaSet, itemPath, mCurrentIndex, 214 mAppBridge == null ? -1 : 0); 215 mModel = pda; 216 mPhotoView.setModel(mModel); 217 218 pda.setDataListener(new PhotoDataAdapter.DataListener() { 219 220 @Override 221 public void onPhotoChanged(int index, Path item) { 222 mCurrentIndex = index; 223 if (item != null) { 224 MediaItem photo = mModel.getCurrentMediaItem(); 225 if (photo != null) updateCurrentPhoto(photo); 226 } 227 updateBars(); 228 } 229 230 @Override 231 public void onLoadingFinished() { 232 GalleryUtils.setSpinnerVisibility((Activity) mActivity, false); 233 if (!mModel.isEmpty()) { 234 MediaItem photo = mModel.getCurrentMediaItem(); 235 if (photo != null) updateCurrentPhoto(photo); 236 } else if (mIsActive) { 237 mActivity.getStateManager().finishState(PhotoPage.this); 238 } 239 } 240 241 @Override 242 public void onLoadingStarted() { 243 GalleryUtils.setSpinnerVisibility((Activity) mActivity, true); 244 } 245 }); 246 } else { 247 // Get default media set by the URI 248 MediaItem mediaItem = (MediaItem) 249 mActivity.getDataManager().getMediaObject(itemPath); 250 mModel = new SinglePhotoDataAdapter(mActivity, mPhotoView, mediaItem); 251 mPhotoView.setModel(mModel); 252 updateCurrentPhoto(mediaItem); 253 } 254 255 mHandler = new SynchronizedHandler(mActivity.getGLRoot()) { 256 @Override 257 public void handleMessage(Message message) { 258 switch (message.what) { 259 case MSG_HIDE_BARS: { 260 hideBars(); 261 break; 262 } 263 case MSG_LOCK_ORIENTATION: { 264 mOrientationManager.lockOrientation(); 265 updateBars(); 266 break; 267 } 268 case MSG_UNLOCK_ORIENTATION: { 269 mOrientationManager.unlockOrientation(); 270 updateBars(); 271 break; 272 } 273 case MSG_ON_FULL_SCREEN_CHANGED: { 274 mAppBridge.onFullScreenChanged(message.arg1 == 1); 275 break; 276 } 277 case MSG_UPDATE_ACTION_BAR: { 278 updateBars(); 279 break; 280 } 281 default: throw new AssertionError(message.what); 282 } 283 } 284 }; 285 286 // start the opening animation only if it's not restored. 287 if (restoreState == null) { 288 mPhotoView.setOpenAnimationRect((Rect) data.getParcelable(KEY_OPEN_ANIMATION_RECT)); 289 } 290 } 291 292 private void updateShareURI(Path path) { 293 if (mShareActionProvider != null) { 294 DataManager manager = mActivity.getDataManager(); 295 int type = manager.getMediaType(path); 296 Intent intent = new Intent(Intent.ACTION_SEND); 297 intent.setType(MenuExecutor.getMimeType(type)); 298 intent.putExtra(Intent.EXTRA_STREAM, manager.getContentUri(path)); 299 mShareActionProvider.setShareIntent(intent); 300 if (mNfcAdapter != null) { 301 mNfcAdapter.setBeamPushUris(new Uri[]{manager.getContentUri(path)}, 302 (Activity)mActivity); 303 } 304 mPendingSharePath = null; 305 } else { 306 // This happens when ActionBar is not created yet. 307 mPendingSharePath = path; 308 } 309 } 310 311 private void updateCurrentPhoto(MediaItem photo) { 312 if (mCurrentPhoto == photo) return; 313 mCurrentPhoto = photo; 314 if (mCurrentPhoto == null) return; 315 updateMenuOperations(); 316 updateTitle(); 317 if (mShowDetails) { 318 mDetailsHelper.reloadDetails(mModel.getCurrentIndex()); 319 } 320 mPhotoView.showVideoPlayIcon( 321 photo.getMediaType() == MediaObject.MEDIA_TYPE_VIDEO); 322 323 if ((photo.getSupportedOperations() & MediaItem.SUPPORT_SHARE) != 0) { 324 updateShareURI(photo.getPath()); 325 } 326 } 327 328 private void updateTitle() { 329 if (mCurrentPhoto == null) return; 330 boolean showTitle = mActivity.getAndroidContext().getResources().getBoolean( 331 R.bool.show_action_bar_title); 332 if (showTitle && mCurrentPhoto.getName() != null) 333 mActionBar.setTitle(mCurrentPhoto.getName()); 334 else 335 mActionBar.setTitle(""); 336 } 337 338 private void updateMenuOperations() { 339 if (mMenu == null) return; 340 MenuItem item = mMenu.findItem(R.id.action_slideshow); 341 if (item != null) { 342 item.setVisible(canDoSlideShow()); 343 } 344 if (mCurrentPhoto == null) return; 345 int supportedOperations = mCurrentPhoto.getSupportedOperations(); 346 if (!GalleryUtils.isEditorAvailable((Context) mActivity, "image/*")) { 347 supportedOperations &= ~MediaObject.SUPPORT_EDIT; 348 } 349 350 MenuExecutor.updateMenuOperation(mMenu, supportedOperations); 351 } 352 353 private boolean canDoSlideShow() { 354 if (mMediaSet == null || mCurrentPhoto == null) { 355 return false; 356 } 357 if (mCurrentPhoto.getMediaType() != MediaObject.MEDIA_TYPE_IMAGE) { 358 return false; 359 } 360 if (mMediaSet instanceof MtpDevice) { 361 return false; 362 } 363 return true; 364 } 365 366 ////////////////////////////////////////////////////////////////////////// 367 // Action Bar show/hide management 368 ////////////////////////////////////////////////////////////////////////// 369 370 private void showBars() { 371 if (mShowBars) return; 372 mShowBars = true; 373 mActionBar.show(); 374 WindowManager.LayoutParams params = 375 ((Activity) mActivity).getWindow().getAttributes(); 376 params.systemUiVisibility = View.SYSTEM_UI_FLAG_VISIBLE; 377 ((Activity) mActivity).getWindow().setAttributes(params); 378 refreshHidingMessage(); 379 } 380 381 private void hideBars() { 382 if (!mShowBars) return; 383 mShowBars = false; 384 mActionBar.hide(); 385 WindowManager.LayoutParams params = 386 ((Activity) mActivity).getWindow().getAttributes(); 387 params.systemUiVisibility = View.SYSTEM_UI_FLAG_LOW_PROFILE; 388 ((Activity) mActivity).getWindow().setAttributes(params); 389 mHandler.removeMessages(MSG_HIDE_BARS); 390 } 391 392 private void refreshHidingMessage() { 393 mHandler.removeMessages(MSG_HIDE_BARS); 394 if (!mIsMenuVisible) { 395 mHandler.sendEmptyMessageDelayed(MSG_HIDE_BARS, HIDE_BARS_TIMEOUT); 396 } 397 } 398 399 private boolean canShowBars() { 400 // No bars if we are showing camera preview. 401 if (mAppBridge != null && mCurrentIndex == 0) return false; 402 // No bars if it's not allowed. 403 if (!mActionBarAllowed) return false; 404 // No bars if the orientation is locked. 405 if (mOrientationManager.isOrientationLocked()) return false; 406 407 return true; 408 } 409 410 private void toggleBars() { 411 mCanShowBars = canShowBars(); 412 if (mShowBars) { 413 hideBars(); 414 } else { 415 if (mCanShowBars) showBars(); 416 } 417 } 418 419 private void updateBars() { 420 boolean v = canShowBars(); 421 if (mCanShowBars == v) return; 422 mCanShowBars = v; 423 424 if (mCanShowBars) { 425 showBars(); 426 } else { 427 hideBars(); 428 } 429 } 430 431 @Override 432 public void onOrientationCompensationChanged(int degrees) { 433 mActivity.getGLRoot().setOrientationCompensation(degrees); 434 } 435 436 @Override 437 protected void onBackPressed() { 438 if (mShowDetails) { 439 hideDetails(); 440 } else if (mScreenNail == null 441 || !switchWithCaptureAnimation(-1)) { 442 // We are leaving this page. Set the result now. 443 setResult(); 444 super.onBackPressed(); 445 } 446 } 447 448 private void onUpPressed() { 449 if (mActivity.getStateManager().getStateCount() > 1) { 450 super.onBackPressed(); 451 } else if (mOriginalSetPathString != null) { 452 // We're in view mode so set up the stacks on our own. 453 Bundle data = new Bundle(getData()); 454 data.putString(AlbumPage.KEY_MEDIA_PATH, mOriginalSetPathString); 455 data.putString(AlbumPage.KEY_PARENT_MEDIA_PATH, 456 mActivity.getDataManager().getTopSetPath( 457 DataManager.INCLUDE_ALL)); 458 mActivity.getStateManager().switchState(this, AlbumPage.class, data); 459 } 460 } 461 462 private void setResult() { 463 Intent result = null; 464 if (!mPhotoView.getFilmMode()) { 465 result = new Intent(); 466 result.putExtra(KEY_RETURN_INDEX_HINT, mCurrentIndex); 467 } 468 setStateResult(Activity.RESULT_OK, result); 469 } 470 471 ////////////////////////////////////////////////////////////////////////// 472 // AppBridge.Server interface 473 ////////////////////////////////////////////////////////////////////////// 474 475 @Override 476 public void setCameraNaturalFrame(Rect frame) { 477 mPhotoView.setCameraNaturalFrame(frame); 478 } 479 480 @Override 481 public boolean switchWithCaptureAnimation(int offset) { 482 return mPhotoView.switchWithCaptureAnimation(offset); 483 } 484 485 @Override 486 protected boolean onCreateActionBar(Menu menu) { 487 MenuInflater inflater = ((Activity) mActivity).getMenuInflater(); 488 inflater.inflate(R.menu.photo, menu); 489 mShareActionProvider = GalleryActionBar.initializeShareActionProvider(menu); 490 if (mPendingSharePath != null) updateShareURI(mPendingSharePath); 491 mMenu = menu; 492 updateMenuOperations(); 493 updateTitle(); 494 return true; 495 } 496 497 @Override 498 protected boolean onItemSelected(MenuItem item) { 499 MediaItem current = mModel.getCurrentMediaItem(); 500 501 if (current == null) { 502 // item is not ready, ignore 503 return true; 504 } 505 506 int currentIndex = mModel.getCurrentIndex(); 507 Path path = current.getPath(); 508 509 DataManager manager = mActivity.getDataManager(); 510 int action = item.getItemId(); 511 boolean needsConfirm = false; 512 switch (action) { 513 case android.R.id.home: { 514 onUpPressed(); 515 return true; 516 } 517 case R.id.action_slideshow: { 518 Bundle data = new Bundle(); 519 data.putString(SlideshowPage.KEY_SET_PATH, mMediaSet.getPath().toString()); 520 data.putString(SlideshowPage.KEY_ITEM_PATH, path.toString()); 521 data.putInt(SlideshowPage.KEY_PHOTO_INDEX, currentIndex); 522 data.putBoolean(SlideshowPage.KEY_REPEAT, true); 523 mActivity.getStateManager().startStateForResult( 524 SlideshowPage.class, REQUEST_SLIDESHOW, data); 525 return true; 526 } 527 case R.id.action_crop: { 528 Activity activity = (Activity) mActivity; 529 Intent intent = new Intent(CropImage.CROP_ACTION); 530 intent.setClass(activity, CropImage.class); 531 intent.setData(manager.getContentUri(path)); 532 activity.startActivityForResult(intent, PicasaSource.isPicasaImage(current) 533 ? REQUEST_CROP_PICASA 534 : REQUEST_CROP); 535 return true; 536 } 537 case R.id.action_edit: { 538 Intent intent = new Intent(Intent.ACTION_EDIT) 539 .setData(manager.getContentUri(path)) 540 .setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); 541 ((Activity) mActivity).startActivityForResult(Intent.createChooser(intent, null), 542 REQUEST_EDIT); 543 return true; 544 } 545 case R.id.action_details: { 546 if (mShowDetails) { 547 hideDetails(); 548 } else { 549 showDetails(currentIndex); 550 } 551 return true; 552 } 553 case R.id.action_delete: 554 needsConfirm = true; 555 case R.id.action_setas: 556 case R.id.action_rotate_ccw: 557 case R.id.action_rotate_cw: 558 case R.id.action_show_on_map: 559 mSelectionManager.deSelectAll(); 560 mSelectionManager.toggle(path); 561 mMenuExecutor.onMenuClicked(item, needsConfirm, null); 562 return true; 563 case R.id.action_import: 564 mSelectionManager.deSelectAll(); 565 mSelectionManager.toggle(path); 566 mMenuExecutor.onMenuClicked(item, needsConfirm, 567 new ImportCompleteListener(mActivity)); 568 return true; 569 default : 570 return false; 571 } 572 } 573 574 private void hideDetails() { 575 mShowDetails = false; 576 mDetailsHelper.hide(); 577 } 578 579 private void showDetails(int index) { 580 mShowDetails = true; 581 if (mDetailsHelper == null) { 582 mDetailsHelper = new DetailsHelper(mActivity, mRootPane, new MyDetailsSource()); 583 mDetailsHelper.setCloseListener(new CloseListener() { 584 @Override 585 public void onClose() { 586 hideDetails(); 587 } 588 }); 589 } 590 mDetailsHelper.reloadDetails(index); 591 mDetailsHelper.show(); 592 } 593 594 //////////////////////////////////////////////////////////////////////////// 595 // Callbacks from PhotoView 596 //////////////////////////////////////////////////////////////////////////// 597 @Override 598 public void onSingleTapUp(int x, int y) { 599 if (mAppBridge != null) { 600 if (mAppBridge.onSingleTapUp(x, y)) return; 601 } 602 603 MediaItem item = mModel.getCurrentMediaItem(); 604 if (item == null || item == mScreenNailItem) { 605 // item is not ready or it is camera preview, ignore 606 return; 607 } 608 609 boolean playVideo = 610 (item.getSupportedOperations() & MediaItem.SUPPORT_PLAY) != 0; 611 612 if (playVideo) { 613 // determine if the point is at center (1/6) of the photo view. 614 // (The position of the "play" icon is at center (1/6) of the photo) 615 int w = mPhotoView.getWidth(); 616 int h = mPhotoView.getHeight(); 617 playVideo = (Math.abs(x - w / 2) * 12 <= w) 618 && (Math.abs(y - h / 2) * 12 <= h); 619 } 620 621 if (playVideo) { 622 playVideo((Activity) mActivity, item.getPlayUri(), item.getName()); 623 } else { 624 toggleBars(); 625 } 626 } 627 628 @Override 629 public void lockOrientation() { 630 mHandler.sendEmptyMessage(MSG_LOCK_ORIENTATION); 631 } 632 633 @Override 634 public void unlockOrientation() { 635 mHandler.sendEmptyMessage(MSG_UNLOCK_ORIENTATION); 636 } 637 638 @Override 639 public void onActionBarAllowed(boolean allowed) { 640 mActionBarAllowed = allowed; 641 mHandler.sendEmptyMessage(MSG_UPDATE_ACTION_BAR); 642 } 643 644 @Override 645 public void onFullScreenChanged(boolean full) { 646 Message m = mHandler.obtainMessage( 647 MSG_ON_FULL_SCREEN_CHANGED, full ? 1 : 0, 0); 648 m.sendToTarget(); 649 } 650 651 public static void playVideo(Activity activity, Uri uri, String title) { 652 try { 653 Intent intent = new Intent(Intent.ACTION_VIEW) 654 .setDataAndType(uri, "video/*"); 655 intent.putExtra(Intent.EXTRA_TITLE, title); 656 activity.startActivity(intent); 657 } catch (ActivityNotFoundException e) { 658 Toast.makeText(activity, activity.getString(R.string.video_err), 659 Toast.LENGTH_SHORT).show(); 660 } 661 } 662 663 private void setCurrentPhotoByIntent(Intent intent) { 664 if (intent == null) return; 665 Path path = mApplication.getDataManager() 666 .findPathByUri(intent.getData(), intent.getType()); 667 if (path != null) { 668 mModel.setCurrentPhoto(path, mCurrentIndex); 669 } 670 } 671 672 @Override 673 protected void onStateResult(int requestCode, int resultCode, Intent data) { 674 switch (requestCode) { 675 case REQUEST_EDIT: 676 setCurrentPhotoByIntent(data); 677 break; 678 case REQUEST_CROP: 679 if (resultCode == Activity.RESULT_OK) { 680 setCurrentPhotoByIntent(data); 681 } 682 break; 683 case REQUEST_CROP_PICASA: { 684 if (resultCode == Activity.RESULT_OK) { 685 Context context = mActivity.getAndroidContext(); 686 String message = context.getString(R.string.crop_saved, 687 context.getString(R.string.folder_download)); 688 Toast.makeText(context, message, Toast.LENGTH_SHORT).show(); 689 } 690 break; 691 } 692 case REQUEST_SLIDESHOW: { 693 if (data == null) break; 694 String path = data.getStringExtra(SlideshowPage.KEY_ITEM_PATH); 695 int index = data.getIntExtra(SlideshowPage.KEY_PHOTO_INDEX, 0); 696 if (path != null) { 697 mModel.setCurrentPhoto(Path.fromString(path), index); 698 } 699 } 700 } 701 } 702 703 @Override 704 public void onPause() { 705 super.onPause(); 706 mIsActive = false; 707 if (mAppBridge != null) mAppBridge.setServer(null); 708 DetailsHelper.pause(); 709 mPhotoView.pause(); 710 mModel.pause(); 711 mHandler.removeMessages(MSG_HIDE_BARS); 712 mActionBar.removeOnMenuVisibilityListener(mMenuVisibilityListener); 713 714 mMenuExecutor.pause(); 715 } 716 717 @Override 718 protected void onResume() { 719 super.onResume(); 720 mIsActive = true; 721 setContentPane(mRootPane); 722 723 mModel.resume(); 724 mPhotoView.resume(); 725 if (mMenuVisibilityListener == null) { 726 mMenuVisibilityListener = new MyMenuVisibilityListener(); 727 } 728 mActionBar.setDisplayOptions(mSetPathString != null, true); 729 mActionBar.addOnMenuVisibilityListener(mMenuVisibilityListener); 730 731 if (mAppBridge != null) { 732 mAppBridge.setServer(this); 733 mPhotoView.resetToFirstPicture(); 734 } 735 } 736 737 @Override 738 protected void onDestroy() { 739 if (mAppBridge != null) { 740 // Unregister the ScreenNail and notify mAppBridge. 741 SnailSource.unregisterScreenNail(mScreenNail); 742 mAppBridge.detachScreenNail(); 743 mAppBridge = null; 744 mScreenNail = null; 745 } 746 mOrientationManager.removeListener(this); 747 748 // Remove all pending messages. 749 mHandler.removeCallbacksAndMessages(null); 750 super.onDestroy(); 751 } 752 753 private class MyDetailsSource implements DetailsSource { 754 private int mIndex; 755 756 @Override 757 public MediaDetails getDetails() { 758 return mModel.getCurrentMediaItem().getDetails(); 759 } 760 761 @Override 762 public int size() { 763 return mMediaSet != null ? mMediaSet.getMediaItemCount() : 1; 764 } 765 766 @Override 767 public int findIndex(int indexHint) { 768 mIndex = indexHint; 769 return indexHint; 770 } 771 772 @Override 773 public int getIndex() { 774 return mIndex; 775 } 776 } 777} 778