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