AlbumPage.java revision 3cf502a91b36bf6ce633f897505b0a2c3fc53ad5
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.Activity; 20import android.content.Context; 21import android.content.Intent; 22import android.graphics.Rect; 23import android.net.Uri; 24import android.os.Bundle; 25import android.os.Vibrator; 26import android.provider.MediaStore; 27import android.widget.Toast; 28 29import com.actionbarsherlock.view.Menu; 30import com.actionbarsherlock.view.MenuInflater; 31import com.actionbarsherlock.view.MenuItem; 32import com.android.gallery3d.R; 33import com.android.gallery3d.common.Utils; 34import com.android.gallery3d.data.DataManager; 35import com.android.gallery3d.data.MediaDetails; 36import com.android.gallery3d.data.MediaItem; 37import com.android.gallery3d.data.MediaObject; 38import com.android.gallery3d.data.MediaSet; 39import com.android.gallery3d.data.MtpDevice; 40import com.android.gallery3d.data.Path; 41import com.android.gallery3d.ui.ActionModeHandler; 42import com.android.gallery3d.ui.ActionModeHandler.ActionModeListener; 43import com.android.gallery3d.ui.AlbumSlotRenderer; 44import com.android.gallery3d.ui.DetailsHelper; 45import com.android.gallery3d.ui.DetailsHelper.CloseListener; 46import com.android.gallery3d.ui.GLCanvas; 47import com.android.gallery3d.ui.GLRoot; 48import com.android.gallery3d.ui.GLView; 49import com.android.gallery3d.ui.PhotoFallbackEffect; 50import com.android.gallery3d.ui.PreparePageFadeoutTexture; 51import com.android.gallery3d.ui.RelativePosition; 52import com.android.gallery3d.ui.SelectionManager; 53import com.android.gallery3d.ui.SlotView; 54import com.android.gallery3d.util.Future; 55import com.android.gallery3d.util.GalleryUtils; 56import com.android.gallery3d.util.MediaSetUtils; 57 58public class AlbumPage extends ActivityState implements GalleryActionBar.ClusterRunner, 59 SelectionManager.SelectionListener, MediaSet.SyncListener, GalleryActionBar.OnAlbumModeSelectedListener { 60 @SuppressWarnings("unused") 61 private static final String TAG = "AlbumPage"; 62 63 public static final String KEY_MEDIA_PATH = "media-path"; 64 public static final String KEY_PARENT_MEDIA_PATH = "parent-media-path"; 65 public static final String KEY_SET_CENTER = "set-center"; 66 public static final String KEY_AUTO_SELECT_ALL = "auto-select-all"; 67 public static final String KEY_SHOW_CLUSTER_MENU = "cluster-menu"; 68 public static final String KEY_EMPTY_ALBUM = "empty-album"; 69 public static final String KEY_RESUME_ANIMATION = "resume_animation"; 70 71 private static final int REQUEST_SLIDESHOW = 1; 72 public static final int REQUEST_PHOTO = 2; 73 private static final int REQUEST_DO_ANIMATION = 3; 74 75 private static final int BIT_LOADING_RELOAD = 1; 76 private static final int BIT_LOADING_SYNC = 2; 77 78 private static final float USER_DISTANCE_METER = 0.3f; 79 80 private boolean mIsActive = false; 81 private AlbumSlotRenderer mAlbumView; 82 private Path mMediaSetPath; 83 private String mParentMediaSetString; 84 private SlotView mSlotView; 85 86 private AlbumDataLoader mAlbumDataAdapter; 87 88 protected SelectionManager mSelectionManager; 89 private Vibrator mVibrator; 90 91 private boolean mGetContent; 92 private boolean mShowClusterMenu; 93 94 private ActionModeHandler mActionModeHandler; 95 private int mFocusIndex = 0; 96 private DetailsHelper mDetailsHelper; 97 private MyDetailsSource mDetailsSource; 98 private MediaSet mMediaSet; 99 private boolean mShowDetails; 100 private float mUserDistance; // in pixel 101 private Future<Integer> mSyncTask = null; 102 private boolean mLaunchedFromPhotoPage; 103 private boolean mInCameraApp; 104 105 private int mLoadingBits = 0; 106 private boolean mInitialSynced = false; 107 private RelativePosition mOpenCenter = new RelativePosition(); 108 109 private PhotoFallbackEffect mResumeEffect; 110 private PhotoFallbackEffect.PositionProvider mPositionProvider = 111 new PhotoFallbackEffect.PositionProvider() { 112 @Override 113 public Rect getPosition(int index) { 114 Rect rect = mSlotView.getSlotRect(index); 115 Rect bounds = mSlotView.bounds(); 116 rect.offset(bounds.left - mSlotView.getScrollX(), 117 bounds.top - mSlotView.getScrollY()); 118 return rect; 119 } 120 121 @Override 122 public int getItemIndex(Path path) { 123 int start = mSlotView.getVisibleStart(); 124 int end = mSlotView.getVisibleEnd(); 125 for (int i = start; i < end; ++i) { 126 MediaItem item = mAlbumDataAdapter.get(i); 127 if (item != null && item.getPath() == path) return i; 128 } 129 return -1; 130 } 131 }; 132 133 @Override 134 protected int getBackgroundColorId() { 135 return R.color.album_background; 136 } 137 138 private final GLView mRootPane = new GLView() { 139 private final float mMatrix[] = new float[16]; 140 141 @Override 142 protected void renderBackground(GLCanvas view) { 143 view.clearBuffer(getBackgroundColor()); 144 } 145 146 @Override 147 protected void onLayout( 148 boolean changed, int left, int top, int right, int bottom) { 149 150 int slotViewTop = mActivity.getGalleryActionBar().getHeight(); 151 int slotViewBottom = bottom - top; 152 int slotViewRight = right - left; 153 154 if (mShowDetails) { 155 mDetailsHelper.layout(left, slotViewTop, right, bottom); 156 } else { 157 mAlbumView.setHighlightItemPath(null); 158 } 159 160 // Set the mSlotView as a reference point to the open animation 161 mOpenCenter.setReferencePosition(0, slotViewTop); 162 mSlotView.layout(0, slotViewTop, slotViewRight, slotViewBottom); 163 GalleryUtils.setViewPointMatrix(mMatrix, 164 (right - left) / 2, (bottom - top) / 2, -mUserDistance); 165 } 166 167 @Override 168 protected void render(GLCanvas canvas) { 169 canvas.save(GLCanvas.SAVE_FLAG_MATRIX); 170 canvas.multiplyMatrix(mMatrix, 0); 171 super.render(canvas); 172 173 if (mResumeEffect != null) { 174 boolean more = mResumeEffect.draw(canvas); 175 if (!more) { 176 mResumeEffect = null; 177 mAlbumView.setSlotFilter(null); 178 } 179 // We want to render one more time even when no more effect 180 // required. So that the animated thumbnails could be draw 181 // with declarations in super.render(). 182 invalidate(); 183 } 184 canvas.restore(); 185 } 186 }; 187 188 // This are the transitions we want: 189 // 190 // +--------+ +------------+ +-------+ +----------+ 191 // | Camera |---------->| Fullscreen |--->| Album |--->| AlbumSet | 192 // | View | thumbnail | Photo | up | Page | up | Page | 193 // +--------+ +------------+ +-------+ +----------+ 194 // ^ | | ^ | 195 // | | | | | close 196 // +----------back--------+ +----back----+ +--back-> app 197 // 198 @Override 199 protected void onBackPressed() { 200 if (mShowDetails) { 201 hideDetails(); 202 } else if (mSelectionManager.inSelectionMode()) { 203 mSelectionManager.leaveSelectionMode(); 204 } else { 205 if(mLaunchedFromPhotoPage) { 206 mActivity.getTransitionStore().putIfNotPresent( 207 PhotoPage.KEY_ALBUMPAGE_TRANSITION, 208 PhotoPage.MSG_ALBUMPAGE_RESUMED); 209 } 210 // TODO: fix this regression 211 // mAlbumView.savePositions(PositionRepository.getInstance(mActivity)); 212 if (mInCameraApp) { 213 super.onBackPressed(); 214 } else { 215 onUpPressed(); 216 } 217 } 218 } 219 220 private void onUpPressed() { 221 if (mInCameraApp) { 222 GalleryUtils.startGalleryActivity(mActivity); 223 } else if (mActivity.getStateManager().getStateCount() > 1) { 224 super.onBackPressed(); 225 } else if (mParentMediaSetString != null) { 226 Bundle data = new Bundle(getData()); 227 data.putString(AlbumSetPage.KEY_MEDIA_PATH, mParentMediaSetString); 228 mActivity.getStateManager().switchState( 229 this, AlbumSetPage.class, data); 230 } 231 } 232 233 private void onDown(int index) { 234 mAlbumView.setPressedIndex(index); 235 } 236 237 private void onUp(boolean followedByLongPress) { 238 if (followedByLongPress) { 239 // Avoid showing press-up animations for long-press. 240 mAlbumView.setPressedIndex(-1); 241 } else { 242 mAlbumView.setPressedUp(); 243 } 244 } 245 246 private void onSingleTapUp(int slotIndex) { 247 if (!mIsActive) return; 248 249 if (mSelectionManager.inSelectionMode()) { 250 MediaItem item = mAlbumDataAdapter.get(slotIndex); 251 if (item == null) return; // Item not ready yet, ignore the click 252 mSelectionManager.toggle(item.getPath()); 253 mSlotView.invalidate(); 254 } else { 255 // Render transition in pressed state 256 mAlbumView.setPressedIndex(slotIndex); 257 PreparePageFadeoutTexture.prepareFadeOutTexture(mActivity, mRootPane); 258 mAlbumView.setPressedIndex(-1); 259 260 pickPhoto(slotIndex); 261 } 262 } 263 264 private void pickPhoto(int slotIndex) { 265 pickPhoto(slotIndex, false); 266 } 267 268 private void pickPhoto(int slotIndex, boolean startInFilmstrip) { 269 if (!mIsActive) return; 270 271 if (!startInFilmstrip) { 272 // Launch photos in lights out mode 273 mActivity.getGLRoot().setLightsOutMode(true); 274 } 275 276 MediaItem item = mAlbumDataAdapter.get(slotIndex); 277 if (item == null) return; // Item not ready yet, ignore the click 278 if (mGetContent) { 279 onGetContent(item); 280 } else if (mLaunchedFromPhotoPage) { 281 TransitionStore transitions = mActivity.getTransitionStore(); 282 transitions.put( 283 PhotoPage.KEY_ALBUMPAGE_TRANSITION, 284 PhotoPage.MSG_ALBUMPAGE_PICKED); 285 transitions.put(PhotoPage.KEY_INDEX_HINT, slotIndex); 286 onBackPressed(); 287 } else { 288 // Get into the PhotoPage. 289 // mAlbumView.savePositions(PositionRepository.getInstance(mActivity)); 290 Bundle data = new Bundle(); 291 data.putInt(PhotoPage.KEY_INDEX_HINT, slotIndex); 292 data.putParcelable(PhotoPage.KEY_OPEN_ANIMATION_RECT, 293 mSlotView.getSlotRect(slotIndex, mRootPane)); 294 data.putString(PhotoPage.KEY_MEDIA_SET_PATH, 295 mMediaSetPath.toString()); 296 data.putString(PhotoPage.KEY_MEDIA_ITEM_PATH, 297 item.getPath().toString()); 298 data.putInt(PhotoPage.KEY_ALBUMPAGE_TRANSITION, 299 PhotoPage.MSG_ALBUMPAGE_STARTED); 300 data.putBoolean(PhotoPage.KEY_START_IN_FILMSTRIP, 301 startInFilmstrip); 302 mActivity.getStateManager().startStateForResult( 303 PhotoPage.class, REQUEST_PHOTO, data); 304 } 305 } 306 307 private void onGetContent(final MediaItem item) { 308 DataManager dm = mActivity.getDataManager(); 309 Activity activity = mActivity; 310 if (mData.getString(Gallery.EXTRA_CROP) != null) { 311 // TODO: Handle MtpImagew 312 Uri uri = dm.getContentUri(item.getPath()); 313 Intent intent = new Intent(CropImage.ACTION_CROP, uri) 314 .addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT) 315 .putExtras(getData()); 316 if (mData.getParcelable(MediaStore.EXTRA_OUTPUT) == null) { 317 intent.putExtra(CropImage.KEY_RETURN_DATA, true); 318 } 319 activity.startActivity(intent); 320 activity.finish(); 321 } else { 322 activity.setResult(Activity.RESULT_OK, 323 new Intent(null, item.getContentUri())); 324 activity.finish(); 325 } 326 } 327 328 public void onLongTap(int slotIndex) { 329 if (mGetContent) return; 330 MediaItem item = mAlbumDataAdapter.get(slotIndex); 331 if (item == null) return; 332 mSelectionManager.setAutoLeaveSelectionMode(true); 333 mSelectionManager.toggle(item.getPath()); 334 mSlotView.invalidate(); 335 } 336 337 @Override 338 public void doCluster(int clusterType) { 339 String basePath = mMediaSet.getPath().toString(); 340 String newPath = FilterUtils.newClusterPath(basePath, clusterType); 341 Bundle data = new Bundle(getData()); 342 data.putString(AlbumSetPage.KEY_MEDIA_PATH, newPath); 343 if (mShowClusterMenu) { 344 Context context = mActivity.getAndroidContext(); 345 data.putString(AlbumSetPage.KEY_SET_TITLE, mMediaSet.getName()); 346 data.putString(AlbumSetPage.KEY_SET_SUBTITLE, 347 GalleryActionBar.getClusterByTypeString(context, clusterType)); 348 } 349 350 // mAlbumView.savePositions(PositionRepository.getInstance(mActivity)); 351 mActivity.getStateManager().startStateForResult( 352 AlbumSetPage.class, REQUEST_DO_ANIMATION, data); 353 } 354 355 @Override 356 protected void onCreate(Bundle data, Bundle restoreState) { 357 super.onCreate(data, restoreState); 358 mUserDistance = GalleryUtils.meterToPixel(USER_DISTANCE_METER); 359 initializeViews(); 360 initializeData(data); 361 mGetContent = data.getBoolean(Gallery.KEY_GET_CONTENT, false); 362 mShowClusterMenu = data.getBoolean(KEY_SHOW_CLUSTER_MENU, false); 363 mDetailsSource = new MyDetailsSource(); 364 Context context = mActivity.getAndroidContext(); 365 mVibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE); 366 367 // Enable auto-select-all for mtp album 368 if (data.getBoolean(KEY_AUTO_SELECT_ALL)) { 369 mSelectionManager.selectAll(); 370 } 371 372 mLaunchedFromPhotoPage = 373 mActivity.getStateManager().hasStateClass(PhotoPage.class); 374 mInCameraApp = data.getBoolean(PhotoPage.KEY_APP_BRIDGE, false); 375 376 // Don't show animation if it is restored or switched from filmstrip 377 if (!mLaunchedFromPhotoPage && restoreState == null && data != null) { 378 int[] center = data.getIntArray(KEY_SET_CENTER); 379 if (center != null) { 380 mOpenCenter.setAbsolutePosition(center[0], center[1]); 381 mSlotView.startScatteringAnimation(mOpenCenter); 382 } 383 } 384 } 385 386 @Override 387 protected void onResume() { 388 super.onResume(); 389 mIsActive = true; 390 391 mResumeEffect = mActivity.getTransitionStore().get(KEY_RESUME_ANIMATION); 392 if (mResumeEffect != null) { 393 mAlbumView.setSlotFilter(mResumeEffect); 394 mResumeEffect.setPositionProvider(mPositionProvider); 395 mResumeEffect.start(); 396 } 397 398 setContentPane(mRootPane); 399 400 boolean enableHomeButton = (mActivity.getStateManager().getStateCount() > 1) | 401 mParentMediaSetString != null; 402 GalleryActionBar actionBar = mActivity.getGalleryActionBar(); 403 actionBar.setDisplayOptions(enableHomeButton, false); 404 actionBar.enableAlbumModeMenu(GalleryActionBar.ALBUM_GRID_MODE_SELECTED, this); 405 406 // Set the reload bit here to prevent it exit this page in clearLoadingBit(). 407 setLoadingBit(BIT_LOADING_RELOAD); 408 mAlbumDataAdapter.resume(); 409 410 mAlbumView.resume(); 411 mActionModeHandler.resume(); 412 if (!mInitialSynced) { 413 setLoadingBit(BIT_LOADING_SYNC); 414 mSyncTask = mMediaSet.requestSync(this); 415 } 416 } 417 418 @Override 419 protected void onPause() { 420 super.onPause(); 421 mIsActive = false; 422 423 mAlbumView.setSlotFilter(null); 424 425 mAlbumDataAdapter.pause(); 426 mAlbumView.pause(); 427 DetailsHelper.pause(); 428 mActivity.getGalleryActionBar().disableAlbumModeMenu(true); 429 430 if (mSyncTask != null) { 431 mSyncTask.cancel(); 432 mSyncTask = null; 433 clearLoadingBit(BIT_LOADING_SYNC); 434 } 435 mActionModeHandler.pause(); 436 437 // The camera app should always launch in capture mode when 438 // resumed, so make the next resume faster by closing the grid 439 // view now 440 if (mInCameraApp) { 441 if (mActivity.getStateManager().getTopState() == this) 442 mActivity.getStateManager().finishState(this, false); 443 } 444 } 445 446 @Override 447 protected void onDestroy() { 448 super.onDestroy(); 449 if (mAlbumDataAdapter != null) { 450 mAlbumDataAdapter.setLoadingListener(null); 451 } 452 } 453 454 private void initializeViews() { 455 mSelectionManager = new SelectionManager(mActivity, false); 456 mSelectionManager.setSelectionListener(this); 457 Config.AlbumPage config = Config.AlbumPage.get(mActivity); 458 mSlotView = new SlotView(mActivity, config.slotViewSpec); 459 mAlbumView = new AlbumSlotRenderer(mActivity, mSlotView, 460 mSelectionManager, config.placeholderColor); 461 mSlotView.setSlotRenderer(mAlbumView); 462 mRootPane.addComponent(mSlotView); 463 mSlotView.setListener(new SlotView.SimpleListener() { 464 @Override 465 public void onDown(int index) { 466 AlbumPage.this.onDown(index); 467 } 468 469 @Override 470 public void onUp(boolean followedByLongPress) { 471 AlbumPage.this.onUp(followedByLongPress); 472 } 473 474 @Override 475 public void onSingleTapUp(int slotIndex) { 476 AlbumPage.this.onSingleTapUp(slotIndex); 477 } 478 479 @Override 480 public void onLongTap(int slotIndex) { 481 AlbumPage.this.onLongTap(slotIndex); 482 } 483 }); 484 mActionModeHandler = new ActionModeHandler(mActivity, mSelectionManager); 485 mActionModeHandler.setActionModeListener(new ActionModeListener() { 486 @Override 487 public boolean onActionItemClicked(MenuItem item) { 488 return onItemSelected(item); 489 } 490 }); 491 } 492 493 private void initializeData(Bundle data) { 494 mMediaSetPath = Path.fromString(data.getString(KEY_MEDIA_PATH)); 495 mParentMediaSetString = data.getString(KEY_PARENT_MEDIA_PATH); 496 mMediaSet = mActivity.getDataManager().getMediaSet(mMediaSetPath); 497 if (mMediaSet == null) { 498 Utils.fail("MediaSet is null. Path = %s", mMediaSetPath); 499 } 500 mSelectionManager.setSourceMediaSet(mMediaSet); 501 mAlbumDataAdapter = new AlbumDataLoader(mActivity, mMediaSet); 502 mAlbumDataAdapter.setLoadingListener(new MyLoadingListener()); 503 mAlbumView.setModel(mAlbumDataAdapter); 504 } 505 506 private void showDetails() { 507 mShowDetails = true; 508 if (mDetailsHelper == null) { 509 mDetailsHelper = new DetailsHelper(mActivity, mRootPane, mDetailsSource); 510 mDetailsHelper.setCloseListener(new CloseListener() { 511 @Override 512 public void onClose() { 513 hideDetails(); 514 } 515 }); 516 } 517 mDetailsHelper.show(); 518 } 519 520 private void hideDetails() { 521 mShowDetails = false; 522 mDetailsHelper.hide(); 523 mAlbumView.setHighlightItemPath(null); 524 mSlotView.invalidate(); 525 } 526 527 @Override 528 protected boolean onCreateActionBar(Menu menu) { 529 GalleryActionBar actionBar = mActivity.getGalleryActionBar(); 530 MenuInflater inflator = getSupportMenuInflater(); 531 if (mGetContent) { 532 inflator.inflate(R.menu.pickup, menu); 533 int typeBits = mData.getInt(Gallery.KEY_TYPE_BITS, 534 DataManager.INCLUDE_IMAGE); 535 actionBar.setTitle(GalleryUtils.getSelectionModePrompt(typeBits)); 536 } else { 537 inflator.inflate(R.menu.album, menu); 538 actionBar.setTitle(mMediaSet.getName()); 539 540 menu.findItem(R.id.action_slideshow) 541 .setVisible(!(mMediaSet instanceof MtpDevice)); 542 543 FilterUtils.setupMenuItems(actionBar, mMediaSetPath, true); 544 545 menu.findItem(R.id.action_group_by).setVisible(mShowClusterMenu); 546 menu.findItem(R.id.action_camera).setVisible( 547 MediaSetUtils.isCameraSource(mMediaSetPath) 548 && GalleryUtils.isCameraAvailable(mActivity)); 549 550 } 551 actionBar.setSubtitle(null); 552 return true; 553 } 554 555 private void prepareAnimationBackToFilmstrip(int slotIndex) { 556 if (mAlbumDataAdapter == null || !mAlbumDataAdapter.isActive(slotIndex)) return; 557 MediaItem item = mAlbumDataAdapter.get(slotIndex); 558 if (item == null) return; 559 PreparePageFadeoutTexture.prepareFadeOutTexture(mActivity, mRootPane); 560 TransitionStore transitions = mActivity.getTransitionStore(); 561 transitions.put(PhotoPage.KEY_INDEX_HINT, slotIndex); 562 transitions.put(PhotoPage.KEY_OPEN_ANIMATION_RECT, 563 mSlotView.getSlotRect(slotIndex, mRootPane)); 564 } 565 566 private void switchToFilmstrip() { 567 if (mAlbumDataAdapter.size() < 1) return; 568 int targetPhoto = mSlotView.getVisibleStart(); 569 prepareAnimationBackToFilmstrip(targetPhoto); 570 if(mLaunchedFromPhotoPage) { 571 onBackPressed(); 572 } else { 573 pickPhoto(targetPhoto, true); 574 } 575 } 576 577 @Override 578 protected boolean onItemSelected(MenuItem item) { 579 switch (item.getItemId()) { 580 case android.R.id.home: { 581 onUpPressed(); 582 return true; 583 } 584 case R.id.action_cancel: 585 mActivity.getStateManager().finishState(this); 586 return true; 587 case R.id.action_select: 588 mSelectionManager.setAutoLeaveSelectionMode(false); 589 mSelectionManager.enterSelectionMode(); 590 return true; 591 case R.id.action_group_by: { 592 mActivity.getGalleryActionBar().showClusterDialog(this); 593 return true; 594 } 595 case R.id.action_slideshow: { 596 Bundle data = new Bundle(); 597 data.putString(SlideshowPage.KEY_SET_PATH, 598 mMediaSetPath.toString()); 599 data.putBoolean(SlideshowPage.KEY_REPEAT, true); 600 mActivity.getStateManager().startStateForResult( 601 SlideshowPage.class, REQUEST_SLIDESHOW, data); 602 return true; 603 } 604 case R.id.action_details: { 605 if (mShowDetails) { 606 hideDetails(); 607 } else { 608 showDetails(); 609 } 610 return true; 611 } 612 case R.id.action_camera: { 613 GalleryUtils.startCameraActivity(mActivity); 614 return true; 615 } 616 default: 617 return false; 618 } 619 } 620 621 @Override 622 protected void onStateResult(int request, int result, Intent data) { 623 switch (request) { 624 case REQUEST_SLIDESHOW: { 625 // data could be null, if there is no images in the album 626 if (data == null) return; 627 mFocusIndex = data.getIntExtra(SlideshowPage.KEY_PHOTO_INDEX, 0); 628 mSlotView.setCenterIndex(mFocusIndex); 629 break; 630 } 631 case REQUEST_PHOTO: { 632 if (data == null) return; 633 mFocusIndex = data.getIntExtra(PhotoPage.KEY_RETURN_INDEX_HINT, 0); 634 mSlotView.makeSlotVisible(mFocusIndex); 635 break; 636 } 637 case REQUEST_DO_ANIMATION: { 638 mSlotView.startRisingAnimation(); 639 break; 640 } 641 } 642 } 643 644 @Override 645 public void onSelectionModeChange(int mode) { 646 switch (mode) { 647 case SelectionManager.ENTER_SELECTION_MODE: { 648 mActionModeHandler.startActionMode(); 649 if (mHapticsEnabled) mVibrator.vibrate(100); 650 break; 651 } 652 case SelectionManager.LEAVE_SELECTION_MODE: { 653 mActionModeHandler.finishActionMode(); 654 mRootPane.invalidate(); 655 break; 656 } 657 case SelectionManager.SELECT_ALL_MODE: { 658 mActionModeHandler.updateSupportedOperation(); 659 mRootPane.invalidate(); 660 break; 661 } 662 } 663 } 664 665 @Override 666 public void onSelectionChange(Path path, boolean selected) { 667 int count = mSelectionManager.getSelectedCount(); 668 String format = mActivity.getResources().getQuantityString( 669 R.plurals.number_of_items_selected, count); 670 mActionModeHandler.setTitle(String.format(format, count)); 671 mActionModeHandler.updateSupportedOperation(path, selected); 672 } 673 674 @Override 675 public void onSyncDone(final MediaSet mediaSet, final int resultCode) { 676 Log.d(TAG, "onSyncDone: " + Utils.maskDebugInfo(mediaSet.getName()) + " result=" 677 + resultCode); 678 ((Activity) mActivity).runOnUiThread(new Runnable() { 679 @Override 680 public void run() { 681 GLRoot root = mActivity.getGLRoot(); 682 root.lockRenderThread(); 683 try { 684 if (resultCode == MediaSet.SYNC_RESULT_SUCCESS) { 685 mInitialSynced = true; 686 } 687 clearLoadingBit(BIT_LOADING_SYNC); 688 if (resultCode == MediaSet.SYNC_RESULT_ERROR && mIsActive 689 && (mAlbumDataAdapter.size() == 0)) { 690 // show error toast only if the album is empty 691 Toast.makeText(mActivity, R.string.sync_album_error, 692 Toast.LENGTH_LONG).show(); 693 } 694 } finally { 695 root.unlockRenderThread(); 696 } 697 } 698 }); 699 } 700 701 private void setLoadingBit(int loadTaskBit) { 702 mLoadingBits |= loadTaskBit; 703 } 704 705 private void clearLoadingBit(int loadTaskBit) { 706 mLoadingBits &= ~loadTaskBit; 707 if (mLoadingBits == 0 && mIsActive) { 708 if (mAlbumDataAdapter.size() == 0) { 709 Intent result = new Intent(); 710 result.putExtra(KEY_EMPTY_ALBUM, true); 711 setStateResult(Activity.RESULT_OK, result); 712 mActivity.getStateManager().finishState(this); 713 } 714 } 715 } 716 717 private class MyLoadingListener implements LoadingListener { 718 @Override 719 public void onLoadingStarted() { 720 setLoadingBit(BIT_LOADING_RELOAD); 721 } 722 723 @Override 724 public void onLoadingFinished() { 725 clearLoadingBit(BIT_LOADING_RELOAD); 726 } 727 } 728 729 private class MyDetailsSource implements DetailsHelper.DetailsSource { 730 private int mIndex; 731 732 @Override 733 public int size() { 734 return mAlbumDataAdapter.size(); 735 } 736 737 @Override 738 public int setIndex() { 739 Path id = mSelectionManager.getSelected(false).get(0); 740 mIndex = mAlbumDataAdapter.findItem(id); 741 return mIndex; 742 } 743 744 @Override 745 public MediaDetails getDetails() { 746 // this relies on setIndex() being called beforehand 747 MediaObject item = mAlbumDataAdapter.get(mIndex); 748 if (item != null) { 749 mAlbumView.setHighlightItemPath(item.getPath()); 750 return item.getDetails(); 751 } else { 752 return null; 753 } 754 } 755 } 756 757 @Override 758 public void onAlbumModeSelected(int mode) { 759 if (mode == GalleryActionBar.ALBUM_FILMSTRIP_MODE_SELECTED) { 760 switchToFilmstrip(); 761 } 762 } 763} 764