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