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