AlbumSetPage.java revision 05da3f520eacb9219964b6ed57ef37846d889fd7
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.os.Bundle; 24import android.os.Handler; 25import android.os.Message; 26import android.os.Vibrator; 27import android.view.Menu; 28import android.view.MenuInflater; 29import android.view.MenuItem; 30import android.view.View; 31import android.view.View.OnClickListener; 32import android.widget.Button; 33import android.widget.RelativeLayout; 34import android.widget.Toast; 35 36import com.android.gallery3d.R; 37import com.android.gallery3d.common.Utils; 38import com.android.gallery3d.data.DataManager; 39import com.android.gallery3d.data.MediaDetails; 40import com.android.gallery3d.data.MediaItem; 41import com.android.gallery3d.data.MediaObject; 42import com.android.gallery3d.data.MediaSet; 43import com.android.gallery3d.data.Path; 44import com.android.gallery3d.picasasource.PicasaSource; 45import com.android.gallery3d.settings.GallerySettings; 46import com.android.gallery3d.ui.ActionModeHandler; 47import com.android.gallery3d.ui.ActionModeHandler.ActionModeListener; 48import com.android.gallery3d.ui.AlbumSetSlotRenderer; 49import com.android.gallery3d.ui.DetailsHelper; 50import com.android.gallery3d.ui.DetailsHelper.CloseListener; 51import com.android.gallery3d.ui.FadeTexture; 52import com.android.gallery3d.ui.GLCanvas; 53import com.android.gallery3d.ui.GLRoot; 54import com.android.gallery3d.ui.GLView; 55import com.android.gallery3d.ui.SelectionManager; 56import com.android.gallery3d.ui.SlotView; 57import com.android.gallery3d.ui.SynchronizedHandler; 58import com.android.gallery3d.util.Future; 59import com.android.gallery3d.util.GalleryUtils; 60import com.android.gallery3d.util.HelpUtils; 61 62import java.lang.ref.WeakReference; 63import java.util.ArrayList; 64 65public class AlbumSetPage extends ActivityState implements 66 SelectionManager.SelectionListener, GalleryActionBar.ClusterRunner, 67 EyePosition.EyePositionListener, MediaSet.SyncListener { 68 @SuppressWarnings("unused") 69 private static final String TAG = "AlbumSetPage"; 70 71 private static final int MSG_PICK_ALBUM = 1; 72 73 public static final String KEY_MEDIA_PATH = "media-path"; 74 public static final String KEY_SET_TITLE = "set-title"; 75 public static final String KEY_SET_SUBTITLE = "set-subtitle"; 76 public static final String KEY_SELECTED_CLUSTER_TYPE = "selected-cluster"; 77 78 private static final int DATA_CACHE_SIZE = 256; 79 private static final int REQUEST_DO_ANIMATION = 1; 80 81 private static final int BIT_LOADING_RELOAD = 1; 82 private static final int BIT_LOADING_SYNC = 2; 83 84 private boolean mIsActive = false; 85 private SlotView mSlotView; 86 private AlbumSetSlotRenderer mAlbumSetView; 87 private Config.AlbumSetPage mConfig; 88 89 private MediaSet mMediaSet; 90 private String mTitle; 91 private String mSubtitle; 92 private boolean mShowClusterMenu; 93 private GalleryActionBar mActionBar; 94 private int mSelectedAction; 95 private Vibrator mVibrator; 96 97 protected SelectionManager mSelectionManager; 98 private AlbumSetDataLoader mAlbumSetDataAdapter; 99 100 private boolean mGetContent; 101 private boolean mGetAlbum; 102 private ActionModeHandler mActionModeHandler; 103 private DetailsHelper mDetailsHelper; 104 private MyDetailsSource mDetailsSource; 105 private boolean mShowDetails; 106 private EyePosition mEyePosition; 107 private Handler mHandler; 108 109 // The eyes' position of the user, the origin is at the center of the 110 // device and the unit is in pixels. 111 private float mX; 112 private float mY; 113 private float mZ; 114 115 private Future<Integer> mSyncTask = null; 116 117 private int mLoadingBits = 0; 118 private boolean mInitialSynced = false; 119 120 private Button mCameraButton; 121 private boolean mShowedEmptyToastForSelf = false; 122 123 @Override 124 protected int getBackgroundColorId() { 125 return R.color.albumset_background; 126 } 127 128 private final GLView mRootPane = new GLView() { 129 private final float mMatrix[] = new float[16]; 130 131 @Override 132 protected void onLayout( 133 boolean changed, int left, int top, int right, int bottom) { 134 mEyePosition.resetPosition(); 135 136 int slotViewTop = mActionBar.getHeight() + mConfig.paddingTop; 137 int slotViewBottom = bottom - top - mConfig.paddingBottom; 138 int slotViewRight = right - left; 139 140 if (mShowDetails) { 141 mDetailsHelper.layout(left, slotViewTop, right, bottom); 142 } else { 143 mAlbumSetView.setHighlightItemPath(null); 144 } 145 146 mSlotView.layout(0, slotViewTop, slotViewRight, slotViewBottom); 147 } 148 149 @Override 150 protected void render(GLCanvas canvas) { 151 canvas.save(GLCanvas.SAVE_FLAG_MATRIX); 152 GalleryUtils.setViewPointMatrix(mMatrix, 153 getWidth() / 2 + mX, getHeight() / 2 + mY, mZ); 154 canvas.multiplyMatrix(mMatrix, 0); 155 super.render(canvas); 156 canvas.restore(); 157 } 158 }; 159 160 @Override 161 public void onEyePositionChanged(float x, float y, float z) { 162 mRootPane.lockRendering(); 163 mX = x; 164 mY = y; 165 mZ = z; 166 mRootPane.unlockRendering(); 167 mRootPane.invalidate(); 168 } 169 170 @Override 171 public void onBackPressed() { 172 if (mShowDetails) { 173 hideDetails(); 174 } else if (mSelectionManager.inSelectionMode()) { 175 mSelectionManager.leaveSelectionMode(); 176 } else { 177 super.onBackPressed(); 178 } 179 } 180 181 private void getSlotCenter(int slotIndex, int center[]) { 182 Rect offset = new Rect(); 183 mRootPane.getBoundsOf(mSlotView, offset); 184 Rect r = mSlotView.getSlotRect(slotIndex); 185 int scrollX = mSlotView.getScrollX(); 186 int scrollY = mSlotView.getScrollY(); 187 center[0] = offset.left + (r.left + r.right) / 2 - scrollX; 188 center[1] = offset.top + (r.top + r.bottom) / 2 - scrollY; 189 } 190 191 public void onSingleTapUp(int slotIndex) { 192 if (!mIsActive) return; 193 194 if (mSelectionManager.inSelectionMode()) { 195 MediaSet targetSet = mAlbumSetDataAdapter.getMediaSet(slotIndex); 196 if (targetSet == null) return; // Content is dirty, we shall reload soon 197 mSelectionManager.toggle(targetSet.getPath()); 198 mSlotView.invalidate(); 199 } else { 200 // Show pressed-up animation for the single-tap. 201 mAlbumSetView.setPressedIndex(slotIndex); 202 mAlbumSetView.setPressedUp(); 203 mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_PICK_ALBUM, slotIndex, 0), 204 FadeTexture.DURATION); 205 } 206 } 207 208 private static boolean albumShouldOpenInFilmstrip(MediaSet album) { 209 int itemCount = album.getMediaItemCount(); 210 ArrayList<MediaItem> list = (itemCount == 1) ? album.getMediaItem(0, 1) : null; 211 // open in film strip only if there's one item in the album and the item exists 212 return (list != null && !list.isEmpty()); 213 } 214 215 WeakReference<Toast> mEmptyAlbumToast = null; 216 217 private void showEmptyAlbumToast(int toastLength) { 218 Toast toast; 219 if (mEmptyAlbumToast != null) { 220 toast = mEmptyAlbumToast.get(); 221 if (toast != null) { 222 toast.show(); 223 return; 224 } 225 } 226 toast = Toast.makeText(mActivity, R.string.empty_album, toastLength); 227 mEmptyAlbumToast = new WeakReference<Toast>(toast); 228 toast.show(); 229 } 230 231 private void hideEmptyAlbumToast() { 232 if (mEmptyAlbumToast != null) { 233 Toast toast = mEmptyAlbumToast.get(); 234 if (toast != null) toast.cancel(); 235 } 236 } 237 238 private void pickAlbum(int slotIndex) { 239 if (!mIsActive) return; 240 241 MediaSet targetSet = mAlbumSetDataAdapter.getMediaSet(slotIndex); 242 if (targetSet == null) return; // Content is dirty, we shall reload soon 243 if (targetSet.getTotalMediaItemCount() == 0) { 244 showEmptyAlbumToast(Toast.LENGTH_SHORT); 245 return; 246 } 247 hideEmptyAlbumToast(); 248 249 String mediaPath = targetSet.getPath().toString(); 250 251 Bundle data = new Bundle(getData()); 252 int[] center = new int[2]; 253 getSlotCenter(slotIndex, center); 254 data.putIntArray(AlbumPage.KEY_SET_CENTER, center); 255 if (mGetAlbum && targetSet.isLeafAlbum()) { 256 Activity activity = mActivity; 257 Intent result = new Intent() 258 .putExtra(AlbumPicker.KEY_ALBUM_PATH, targetSet.getPath().toString()); 259 activity.setResult(Activity.RESULT_OK, result); 260 activity.finish(); 261 } else if (targetSet.getSubMediaSetCount() > 0) { 262 data.putString(AlbumSetPage.KEY_MEDIA_PATH, mediaPath); 263 mActivity.getStateManager().startStateForResult( 264 AlbumSetPage.class, REQUEST_DO_ANIMATION, data); 265 } else { 266 if (!mGetContent && (targetSet.getSupportedOperations() 267 & MediaObject.SUPPORT_IMPORT) != 0) { 268 data.putBoolean(AlbumPage.KEY_AUTO_SELECT_ALL, true); 269 } else if (!mGetContent && albumShouldOpenInFilmstrip(targetSet)) { 270 data.putParcelable(PhotoPage.KEY_OPEN_ANIMATION_RECT, 271 mSlotView.getSlotRect(slotIndex, mRootPane)); 272 data.putInt(PhotoPage.KEY_INDEX_HINT, 0); 273 data.putString(PhotoPage.KEY_MEDIA_SET_PATH, 274 mediaPath); 275 data.putBoolean(PhotoPage.KEY_START_IN_FILMSTRIP, true); 276 data.putBoolean(PhotoPage.KEY_IN_CAMERA_ROLL, targetSet.isCameraRoll()); 277 mActivity.getStateManager().startStateForResult( 278 PhotoPage.class, AlbumPage.REQUEST_PHOTO, data); 279 return; 280 } 281 data.putString(AlbumPage.KEY_MEDIA_PATH, mediaPath); 282 283 // We only show cluster menu in the first AlbumPage in stack 284 boolean inAlbum = mActivity.getStateManager().hasStateClass(AlbumPage.class); 285 data.putBoolean(AlbumPage.KEY_SHOW_CLUSTER_MENU, !inAlbum); 286 mActivity.getStateManager().startStateForResult( 287 AlbumPage.class, REQUEST_DO_ANIMATION, data); 288 } 289 } 290 291 private void onDown(int index) { 292 mAlbumSetView.setPressedIndex(index); 293 } 294 295 private void onUp(boolean followedByLongPress) { 296 if (followedByLongPress) { 297 // Avoid showing press-up animations for long-press. 298 mAlbumSetView.setPressedIndex(-1); 299 } else { 300 mAlbumSetView.setPressedUp(); 301 } 302 } 303 304 public void onLongTap(int slotIndex) { 305 if (mGetContent || mGetAlbum) return; 306 MediaSet set = mAlbumSetDataAdapter.getMediaSet(slotIndex); 307 if (set == null) return; 308 mSelectionManager.setAutoLeaveSelectionMode(true); 309 mSelectionManager.toggle(set.getPath()); 310 mSlotView.invalidate(); 311 } 312 313 @Override 314 public void doCluster(int clusterType) { 315 String basePath = mMediaSet.getPath().toString(); 316 String newPath = FilterUtils.switchClusterPath(basePath, clusterType); 317 Bundle data = new Bundle(getData()); 318 data.putString(AlbumSetPage.KEY_MEDIA_PATH, newPath); 319 data.putInt(KEY_SELECTED_CLUSTER_TYPE, clusterType); 320 mActivity.getStateManager().switchState(this, AlbumSetPage.class, data); 321 } 322 323 @Override 324 public void onCreate(Bundle data, Bundle restoreState) { 325 super.onCreate(data, restoreState); 326 initializeViews(); 327 initializeData(data); 328 Context context = mActivity.getAndroidContext(); 329 mGetContent = data.getBoolean(Gallery.KEY_GET_CONTENT, false); 330 mGetAlbum = data.getBoolean(Gallery.KEY_GET_ALBUM, false); 331 mTitle = data.getString(AlbumSetPage.KEY_SET_TITLE); 332 mSubtitle = data.getString(AlbumSetPage.KEY_SET_SUBTITLE); 333 mEyePosition = new EyePosition(context, this); 334 mDetailsSource = new MyDetailsSource(); 335 mVibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE); 336 mActionBar = mActivity.getGalleryActionBar(); 337 mSelectedAction = data.getInt(AlbumSetPage.KEY_SELECTED_CLUSTER_TYPE, 338 FilterUtils.CLUSTER_BY_ALBUM); 339 340 mHandler = new SynchronizedHandler(mActivity.getGLRoot()) { 341 @Override 342 public void handleMessage(Message message) { 343 switch (message.what) { 344 case MSG_PICK_ALBUM: { 345 pickAlbum(message.arg1); 346 break; 347 } 348 default: throw new AssertionError(message.what); 349 } 350 } 351 }; 352 } 353 354 @Override 355 public void onDestroy() { 356 cleanupCameraButton(); 357 super.onDestroy(); 358 } 359 360 private boolean setupCameraButton() { 361 if (!GalleryUtils.isCameraAvailable(mActivity)) return false; 362 RelativeLayout galleryRoot = (RelativeLayout) ((Activity) mActivity) 363 .findViewById(R.id.gallery_root); 364 if (galleryRoot == null) return false; 365 366 mCameraButton = new Button(mActivity); 367 mCameraButton.setText(R.string.camera_label); 368 mCameraButton.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.frame_overlay_gallery_camera, 0, 0); 369 mCameraButton.setOnClickListener(new OnClickListener() { 370 @Override 371 public void onClick(View arg0) { 372 GalleryUtils.startCameraActivity(mActivity); 373 } 374 }); 375 RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams( 376 RelativeLayout.LayoutParams.WRAP_CONTENT, 377 RelativeLayout.LayoutParams.WRAP_CONTENT); 378 lp.addRule(RelativeLayout.CENTER_IN_PARENT); 379 galleryRoot.addView(mCameraButton, lp); 380 return true; 381 } 382 383 private void cleanupCameraButton() { 384 if (mCameraButton == null) return; 385 RelativeLayout galleryRoot = (RelativeLayout) ((Activity) mActivity) 386 .findViewById(R.id.gallery_root); 387 if (galleryRoot == null) return; 388 galleryRoot.removeView(mCameraButton); 389 mCameraButton = null; 390 } 391 392 private void showCameraButton() { 393 if (mCameraButton == null && !setupCameraButton()) return; 394 mCameraButton.setVisibility(View.VISIBLE); 395 } 396 397 private void hideCameraButton() { 398 if (mCameraButton == null) return; 399 mCameraButton.setVisibility(View.GONE); 400 } 401 402 private void clearLoadingBit(int loadingBit) { 403 mLoadingBits &= ~loadingBit; 404 if (mLoadingBits == 0 && mIsActive) { 405 if (mAlbumSetDataAdapter.size() == 0) { 406 // If this is not the top of the gallery folder hierarchy, 407 // tell the parent AlbumSetPage instance to handle displaying 408 // the empty album toast, otherwise show it within this 409 // instance 410 if (mActivity.getStateManager().getStateCount() > 1) { 411 Intent result = new Intent(); 412 result.putExtra(AlbumPage.KEY_EMPTY_ALBUM, true); 413 setStateResult(Activity.RESULT_OK, result); 414 mActivity.getStateManager().finishState(this); 415 } else { 416 mShowedEmptyToastForSelf = true; 417 showEmptyAlbumToast(Toast.LENGTH_LONG); 418 mSlotView.invalidate(); 419 showCameraButton(); 420 } 421 return; 422 } 423 } 424 // Hide the empty album toast if we are in the root instance of 425 // AlbumSetPage and the album is no longer empty (for instance, 426 // after a sync is completed and web albums have been synced) 427 if (mShowedEmptyToastForSelf) { 428 mShowedEmptyToastForSelf = false; 429 hideEmptyAlbumToast(); 430 hideCameraButton(); 431 } 432 } 433 434 private void setLoadingBit(int loadingBit) { 435 mLoadingBits |= loadingBit; 436 } 437 438 @Override 439 public void onPause() { 440 super.onPause(); 441 mIsActive = false; 442 mActionModeHandler.pause(); 443 mAlbumSetDataAdapter.pause(); 444 mAlbumSetView.pause(); 445 mEyePosition.pause(); 446 DetailsHelper.pause(); 447 // Call disableClusterMenu to avoid receiving callback after paused. 448 // Don't hide menu here otherwise the list menu will disappear earlier than 449 // the action bar, which is janky and unwanted behavior. 450 mActionBar.disableClusterMenu(false); 451 if (mSyncTask != null) { 452 mSyncTask.cancel(); 453 mSyncTask = null; 454 clearLoadingBit(BIT_LOADING_SYNC); 455 } 456 } 457 458 @Override 459 public void onResume() { 460 super.onResume(); 461 mIsActive = true; 462 setContentPane(mRootPane); 463 464 // Set the reload bit here to prevent it exit this page in clearLoadingBit(). 465 setLoadingBit(BIT_LOADING_RELOAD); 466 mAlbumSetDataAdapter.resume(); 467 468 mAlbumSetView.resume(); 469 mEyePosition.resume(); 470 mActionModeHandler.resume(); 471 if (mShowClusterMenu) { 472 mActionBar.enableClusterMenu(mSelectedAction, this); 473 } 474 if (!mInitialSynced) { 475 setLoadingBit(BIT_LOADING_SYNC); 476 mSyncTask = mMediaSet.requestSync(AlbumSetPage.this); 477 } 478 } 479 480 private void initializeData(Bundle data) { 481 String mediaPath = data.getString(AlbumSetPage.KEY_MEDIA_PATH); 482 mMediaSet = mActivity.getDataManager().getMediaSet(mediaPath); 483 mSelectionManager.setSourceMediaSet(mMediaSet); 484 mAlbumSetDataAdapter = new AlbumSetDataLoader( 485 mActivity, mMediaSet, DATA_CACHE_SIZE); 486 mAlbumSetDataAdapter.setLoadingListener(new MyLoadingListener()); 487 mAlbumSetView.setModel(mAlbumSetDataAdapter); 488 } 489 490 private void initializeViews() { 491 mSelectionManager = new SelectionManager(mActivity, true); 492 mSelectionManager.setSelectionListener(this); 493 494 mConfig = Config.AlbumSetPage.get(mActivity); 495 mSlotView = new SlotView(mActivity, mConfig.slotViewSpec); 496 mAlbumSetView = new AlbumSetSlotRenderer( 497 mActivity, mSelectionManager, mSlotView, mConfig.labelSpec, 498 mConfig.placeholderColor); 499 mSlotView.setSlotRenderer(mAlbumSetView); 500 mSlotView.setListener(new SlotView.SimpleListener() { 501 @Override 502 public void onDown(int index) { 503 AlbumSetPage.this.onDown(index); 504 } 505 506 @Override 507 public void onUp(boolean followedByLongPress) { 508 AlbumSetPage.this.onUp(followedByLongPress); 509 } 510 511 @Override 512 public void onSingleTapUp(int slotIndex) { 513 AlbumSetPage.this.onSingleTapUp(slotIndex); 514 } 515 516 @Override 517 public void onLongTap(int slotIndex) { 518 AlbumSetPage.this.onLongTap(slotIndex); 519 } 520 }); 521 522 mActionModeHandler = new ActionModeHandler(mActivity, mSelectionManager); 523 mActionModeHandler.setActionModeListener(new ActionModeListener() { 524 @Override 525 public boolean onActionItemClicked(MenuItem item) { 526 return onItemSelected(item); 527 } 528 }); 529 mRootPane.addComponent(mSlotView); 530 } 531 532 @Override 533 protected boolean onCreateActionBar(Menu menu) { 534 Activity activity = mActivity; 535 final boolean inAlbum = mActivity.getStateManager().hasStateClass(AlbumPage.class); 536 MenuInflater inflater = getSupportMenuInflater(); 537 538 if (mGetContent) { 539 inflater.inflate(R.menu.pickup, menu); 540 int typeBits = mData.getInt( 541 Gallery.KEY_TYPE_BITS, DataManager.INCLUDE_IMAGE); 542 mActionBar.setTitle(GalleryUtils.getSelectionModePrompt(typeBits)); 543 } else if (mGetAlbum) { 544 inflater.inflate(R.menu.pickup, menu); 545 mActionBar.setTitle(R.string.select_album); 546 } else { 547 inflater.inflate(R.menu.albumset, menu); 548 boolean wasShowingClusterMenu = mShowClusterMenu; 549 mShowClusterMenu = !inAlbum; 550 boolean selectAlbums = !inAlbum && 551 mActionBar.getClusterTypeAction() == FilterUtils.CLUSTER_BY_ALBUM; 552 MenuItem selectItem = menu.findItem(R.id.action_select); 553 selectItem.setTitle(activity.getString( 554 selectAlbums ? R.string.select_album : R.string.select_group)); 555 556 MenuItem cameraItem = menu.findItem(R.id.action_camera); 557 cameraItem.setVisible(GalleryUtils.isCameraAvailable(activity)); 558 559 FilterUtils.setupMenuItems(mActionBar, mMediaSet.getPath(), false); 560 561 Intent helpIntent = HelpUtils.getHelpIntent(activity, R.string.help_url_gallery_main); 562 563 MenuItem helpItem = menu.findItem(R.id.action_general_help); 564 helpItem.setVisible(helpIntent != null); 565 if (helpIntent != null) helpItem.setIntent(helpIntent); 566 567 mActionBar.setTitle(mTitle); 568 mActionBar.setSubtitle(mSubtitle); 569 if (mShowClusterMenu != wasShowingClusterMenu) { 570 if (mShowClusterMenu) { 571 mActionBar.enableClusterMenu(mSelectedAction, this); 572 } else { 573 mActionBar.disableClusterMenu(true); 574 } 575 } 576 } 577 return true; 578 } 579 580 @Override 581 protected boolean onItemSelected(MenuItem item) { 582 Activity activity = mActivity; 583 switch (item.getItemId()) { 584 case R.id.action_cancel: 585 activity.setResult(Activity.RESULT_CANCELED); 586 activity.finish(); 587 return true; 588 case R.id.action_select: 589 mSelectionManager.setAutoLeaveSelectionMode(false); 590 mSelectionManager.enterSelectionMode(); 591 return true; 592 case R.id.action_details: 593 if (mAlbumSetDataAdapter.size() != 0) { 594 if (mShowDetails) { 595 hideDetails(); 596 } else { 597 showDetails(); 598 } 599 } else { 600 Toast.makeText(activity, 601 activity.getText(R.string.no_albums_alert), 602 Toast.LENGTH_SHORT).show(); 603 } 604 return true; 605 case R.id.action_camera: { 606 GalleryUtils.startCameraActivity(activity); 607 return true; 608 } 609 case R.id.action_manage_offline: { 610 Bundle data = new Bundle(); 611 String mediaPath = mActivity.getDataManager().getTopSetPath( 612 DataManager.INCLUDE_ALL); 613 data.putString(AlbumSetPage.KEY_MEDIA_PATH, mediaPath); 614 mActivity.getStateManager().startState(ManageCachePage.class, data); 615 return true; 616 } 617 case R.id.action_sync_picasa_albums: { 618 PicasaSource.requestSync(activity); 619 return true; 620 } 621 case R.id.action_settings: { 622 activity.startActivity(new Intent(activity, GallerySettings.class)); 623 return true; 624 } 625 default: 626 return false; 627 } 628 } 629 630 @Override 631 protected void onStateResult(int requestCode, int resultCode, Intent data) { 632 if (data != null && data.getBooleanExtra(AlbumPage.KEY_EMPTY_ALBUM, false)) { 633 showEmptyAlbumToast(Toast.LENGTH_SHORT); 634 } 635 switch (requestCode) { 636 case REQUEST_DO_ANIMATION: { 637 mSlotView.startRisingAnimation(); 638 } 639 } 640 } 641 642 private String getSelectedString() { 643 int count = mSelectionManager.getSelectedCount(); 644 int action = mActionBar.getClusterTypeAction(); 645 int string = action == FilterUtils.CLUSTER_BY_ALBUM 646 ? R.plurals.number_of_albums_selected 647 : R.plurals.number_of_groups_selected; 648 String format = mActivity.getResources().getQuantityString(string, count); 649 return String.format(format, count); 650 } 651 652 @Override 653 public void onSelectionModeChange(int mode) { 654 switch (mode) { 655 case SelectionManager.ENTER_SELECTION_MODE: { 656 mActionBar.disableClusterMenu(true); 657 mActionModeHandler.startActionMode(); 658 if (mHapticsEnabled) mVibrator.vibrate(100); 659 break; 660 } 661 case SelectionManager.LEAVE_SELECTION_MODE: { 662 mActionModeHandler.finishActionMode(); 663 if (mShowClusterMenu) { 664 mActionBar.enableClusterMenu(mSelectedAction, this); 665 } 666 mRootPane.invalidate(); 667 break; 668 } 669 case SelectionManager.SELECT_ALL_MODE: { 670 mActionModeHandler.updateSupportedOperation(); 671 mRootPane.invalidate(); 672 break; 673 } 674 } 675 } 676 677 @Override 678 public void onSelectionChange(Path path, boolean selected) { 679 mActionModeHandler.setTitle(getSelectedString()); 680 mActionModeHandler.updateSupportedOperation(path, selected); 681 } 682 683 private void hideDetails() { 684 mShowDetails = false; 685 mDetailsHelper.hide(); 686 mAlbumSetView.setHighlightItemPath(null); 687 mSlotView.invalidate(); 688 } 689 690 private void showDetails() { 691 mShowDetails = true; 692 if (mDetailsHelper == null) { 693 mDetailsHelper = new DetailsHelper(mActivity, mRootPane, mDetailsSource); 694 mDetailsHelper.setCloseListener(new CloseListener() { 695 @Override 696 public void onClose() { 697 hideDetails(); 698 } 699 }); 700 } 701 mDetailsHelper.show(); 702 } 703 704 @Override 705 public void onSyncDone(final MediaSet mediaSet, final int resultCode) { 706 if (resultCode == MediaSet.SYNC_RESULT_ERROR) { 707 Log.d(TAG, "onSyncDone: " + Utils.maskDebugInfo(mediaSet.getName()) + " result=" 708 + resultCode); 709 } 710 ((Activity) mActivity).runOnUiThread(new Runnable() { 711 @Override 712 public void run() { 713 GLRoot root = mActivity.getGLRoot(); 714 root.lockRenderThread(); 715 try { 716 if (resultCode == MediaSet.SYNC_RESULT_SUCCESS) { 717 mInitialSynced = true; 718 } 719 clearLoadingBit(BIT_LOADING_SYNC); 720 if (resultCode == MediaSet.SYNC_RESULT_ERROR && mIsActive) { 721 Log.w(TAG, "failed to load album set"); 722 } 723 } finally { 724 root.unlockRenderThread(); 725 } 726 } 727 }); 728 } 729 730 private class MyLoadingListener implements LoadingListener { 731 @Override 732 public void onLoadingStarted() { 733 setLoadingBit(BIT_LOADING_RELOAD); 734 } 735 736 @Override 737 public void onLoadingFinished(boolean loadingFailed) { 738 clearLoadingBit(BIT_LOADING_RELOAD); 739 } 740 } 741 742 private class MyDetailsSource implements DetailsHelper.DetailsSource { 743 private int mIndex; 744 745 @Override 746 public int size() { 747 return mAlbumSetDataAdapter.size(); 748 } 749 750 @Override 751 public int setIndex() { 752 Path id = mSelectionManager.getSelected(false).get(0); 753 mIndex = mAlbumSetDataAdapter.findSet(id); 754 return mIndex; 755 } 756 757 @Override 758 public MediaDetails getDetails() { 759 MediaObject item = mAlbumSetDataAdapter.getMediaSet(mIndex); 760 if (item != null) { 761 mAlbumSetView.setHighlightItemPath(item.getPath()); 762 return item.getDetails(); 763 } else { 764 return null; 765 } 766 } 767 } 768} 769