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