2 * Copyright (C) 2010 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com.android.gallery3d.app;
19 import android.app.Activity;
20 import android.content.Context;
21 import android.content.Intent;
22 import android.graphics.Rect;
23 import android.net.Uri;
24 import android.os.Bundle;
25 import android.os.Handler;
26 import android.os.Message;
27 import android.provider.MediaStore;
28 import android.view.HapticFeedbackConstants;
29 import android.view.Menu;
30 import android.view.MenuInflater;
31 import android.view.MenuItem;
32 import android.widget.Toast;
34 import com.android.gallery3d.R;
35 import com.android.gallery3d.common.Utils;
36 import com.android.gallery3d.data.DataManager;
37 import com.android.gallery3d.data.MediaDetails;
38 import com.android.gallery3d.data.MediaItem;
39 import com.android.gallery3d.data.MediaObject;
40 import com.android.gallery3d.data.MediaSet;
41 import com.android.gallery3d.data.Path;
42 import com.android.gallery3d.filtershow.crop.CropActivity;
43 import com.android.gallery3d.filtershow.crop.CropExtras;
44 import com.android.gallery3d.glrenderer.FadeTexture;
45 import com.android.gallery3d.glrenderer.GLCanvas;
46 import com.android.gallery3d.ui.ActionModeHandler;
47 import com.android.gallery3d.ui.ActionModeHandler.ActionModeListener;
48 import com.android.gallery3d.ui.AlbumSlotRenderer;
49 import com.android.gallery3d.ui.DetailsHelper;
50 import com.android.gallery3d.ui.DetailsHelper.CloseListener;
51 import com.android.gallery3d.ui.GLRoot;
52 import com.android.gallery3d.ui.GLView;
53 import com.android.gallery3d.ui.PhotoFallbackEffect;
54 import com.android.gallery3d.ui.RelativePosition;
55 import com.android.gallery3d.ui.SelectionManager;
56 import com.android.gallery3d.ui.SlotView;
57 import com.android.gallery3d.ui.SynchronizedHandler;
58 import com.android.gallery3d.util.Future;
59 import com.android.gallery3d.util.GalleryUtils;
60 import com.android.gallery3d.util.MediaSetUtils;
63 public class AlbumPage extends ActivityState implements GalleryActionBar.ClusterRunner,
64 SelectionManager.SelectionListener, MediaSet.SyncListener, GalleryActionBar.OnAlbumModeSelectedListener {
65 @SuppressWarnings("unused")
66 private static final String TAG = "AlbumPage";
68 public static final String KEY_MEDIA_PATH = "media-path";
69 public static final String KEY_PARENT_MEDIA_PATH = "parent-media-path";
70 public static final String KEY_SET_CENTER = "set-center";
71 public static final String KEY_AUTO_SELECT_ALL = "auto-select-all";
72 public static final String KEY_SHOW_CLUSTER_MENU = "cluster-menu";
73 public static final String KEY_EMPTY_ALBUM = "empty-album";
74 public static final String KEY_RESUME_ANIMATION = "resume_animation";
76 private static final int REQUEST_SLIDESHOW = 1;
77 public static final int REQUEST_PHOTO = 2;
78 private static final int REQUEST_DO_ANIMATION = 3;
80 private static final int BIT_LOADING_RELOAD = 1;
81 private static final int BIT_LOADING_SYNC = 2;
83 private static final float USER_DISTANCE_METER = 0.3f;
85 private boolean mIsActive = false;
86 private AlbumSlotRenderer mAlbumView;
87 private Path mMediaSetPath;
88 private String mParentMediaSetString;
89 private SlotView mSlotView;
91 private AlbumDataLoader mAlbumDataAdapter;
93 protected SelectionManager mSelectionManager;
95 private boolean mGetContent;
96 private boolean mShowClusterMenu;
98 private ActionModeHandler mActionModeHandler;
99 private int mFocusIndex = 0;
100 private DetailsHelper mDetailsHelper;
101 private MyDetailsSource mDetailsSource;
102 private MediaSet mMediaSet;
103 private boolean mShowDetails;
104 private float mUserDistance; // in pixel
105 private Future<Integer> mSyncTask = null;
106 private boolean mLaunchedFromPhotoPage;
107 private boolean mInCameraApp;
108 private boolean mInCameraAndWantQuitOnPause;
110 private int mLoadingBits = 0;
111 private boolean mInitialSynced = false;
112 private int mSyncResult;
113 private boolean mLoadingFailed;
114 private RelativePosition mOpenCenter = new RelativePosition();
116 private Handler mHandler;
117 private static final int MSG_PICK_PHOTO = 0;
119 private PhotoFallbackEffect mResumeEffect;
120 private PhotoFallbackEffect.PositionProvider mPositionProvider =
121 new PhotoFallbackEffect.PositionProvider() {
123 public Rect getPosition(int index) {
124 Rect rect = mSlotView.getSlotRect(index);
125 Rect bounds = mSlotView.bounds();
126 rect.offset(bounds.left - mSlotView.getScrollX(),
127 bounds.top - mSlotView.getScrollY());
132 public int getItemIndex(Path path) {
133 int start = mSlotView.getVisibleStart();
134 int end = mSlotView.getVisibleEnd();
135 for (int i = start; i < end; ++i) {
136 MediaItem item = mAlbumDataAdapter.get(i);
137 if (item != null && item.getPath() == path) return i;
144 protected int getBackgroundColorId() {
145 return R.color.album_background;
148 private final GLView mRootPane = new GLView() {
149 private final float mMatrix[] = new float[16];
152 protected void onLayout(
153 boolean changed, int left, int top, int right, int bottom) {
155 int slotViewTop = mActivity.getGalleryActionBar().getHeight();
156 int slotViewBottom = bottom - top;
157 int slotViewRight = right - left;
160 mDetailsHelper.layout(left, slotViewTop, right, bottom);
162 mAlbumView.setHighlightItemPath(null);
165 // Set the mSlotView as a reference point to the open animation
166 mOpenCenter.setReferencePosition(0, slotViewTop);
167 mSlotView.layout(0, slotViewTop, slotViewRight, slotViewBottom);
168 GalleryUtils.setViewPointMatrix(mMatrix,
169 (right - left) / 2, (bottom - top) / 2, -mUserDistance);
173 protected void render(GLCanvas canvas) {
174 canvas.save(GLCanvas.SAVE_FLAG_MATRIX);
175 canvas.multiplyMatrix(mMatrix, 0);
176 super.render(canvas);
178 if (mResumeEffect != null) {
179 boolean more = mResumeEffect.draw(canvas);
181 mResumeEffect = null;
182 mAlbumView.setSlotFilter(null);
184 // We want to render one more time even when no more effect
185 // required. So that the animated thumbnails could be draw
186 // with declarations in super.render().
193 // This are the transitions we want:
195 // +--------+ +------------+ +-------+ +----------+
196 // | Camera |---------->| Fullscreen |--->| Album |--->| AlbumSet |
197 // | View | thumbnail | Photo | up | Page | up | Page |
198 // +--------+ +------------+ +-------+ +----------+
201 // +----------back--------+ +----back----+ +--back-> app
204 protected void onBackPressed() {
207 } else if (mSelectionManager.inSelectionMode()) {
208 mSelectionManager.leaveSelectionMode();
210 if(mLaunchedFromPhotoPage) {
211 mActivity.getTransitionStore().putIfNotPresent(
212 PhotoPage.KEY_ALBUMPAGE_TRANSITION,
213 PhotoPage.MSG_ALBUMPAGE_RESUMED);
215 // TODO: fix this regression
216 // mAlbumView.savePositions(PositionRepository.getInstance(mActivity));
218 super.onBackPressed();
225 private void onUpPressed() {
227 GalleryUtils.startGalleryActivity(mActivity);
228 } else if (mActivity.getStateManager().getStateCount() > 1) {
229 super.onBackPressed();
230 } else if (mParentMediaSetString != null) {
231 Bundle data = new Bundle(getData());
232 data.putString(AlbumSetPage.KEY_MEDIA_PATH, mParentMediaSetString);
233 mActivity.getStateManager().switchState(
234 this, AlbumSetPage.class, data);
238 private void onDown(int index) {
239 mAlbumView.setPressedIndex(index);
242 private void onUp(boolean followedByLongPress) {
243 if (followedByLongPress) {
244 // Avoid showing press-up animations for long-press.
245 mAlbumView.setPressedIndex(-1);
247 mAlbumView.setPressedUp();
251 private void onSingleTapUp(int slotIndex) {
252 if (!mIsActive) return;
254 if (mSelectionManager.inSelectionMode()) {
255 MediaItem item = mAlbumDataAdapter.get(slotIndex);
256 if (item == null) return; // Item not ready yet, ignore the click
257 mSelectionManager.toggle(item.getPath());
258 mSlotView.invalidate();
260 // Render transition in pressed state
261 mAlbumView.setPressedIndex(slotIndex);
262 mAlbumView.setPressedUp();
263 mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_PICK_PHOTO, slotIndex, 0),
264 FadeTexture.DURATION);
268 private void pickPhoto(int slotIndex) {
269 pickPhoto(slotIndex, false);
272 private void pickPhoto(int slotIndex, boolean startInFilmstrip) {
273 if (!mIsActive) return;
275 if (!startInFilmstrip) {
276 // Launch photos in lights out mode
277 mActivity.getGLRoot().setLightsOutMode(true);
280 MediaItem item = mAlbumDataAdapter.get(slotIndex);
281 if (item == null) return; // Item not ready yet, ignore the click
284 } else if (mLaunchedFromPhotoPage) {
285 TransitionStore transitions = mActivity.getTransitionStore();
287 PhotoPage.KEY_ALBUMPAGE_TRANSITION,
288 PhotoPage.MSG_ALBUMPAGE_PICKED);
289 transitions.put(PhotoPage.KEY_INDEX_HINT, slotIndex);
292 // Get into the PhotoPage.
293 // mAlbumView.savePositions(PositionRepository.getInstance(mActivity));
294 Bundle data = new Bundle();
295 data.putInt(PhotoPage.KEY_INDEX_HINT, slotIndex);
296 data.putParcelable(PhotoPage.KEY_OPEN_ANIMATION_RECT,
297 mSlotView.getSlotRect(slotIndex, mRootPane));
298 data.putString(PhotoPage.KEY_MEDIA_SET_PATH,
299 mMediaSetPath.toString());
300 data.putString(PhotoPage.KEY_MEDIA_ITEM_PATH,
301 item.getPath().toString());
302 data.putInt(PhotoPage.KEY_ALBUMPAGE_TRANSITION,
303 PhotoPage.MSG_ALBUMPAGE_STARTED);
304 data.putBoolean(PhotoPage.KEY_START_IN_FILMSTRIP,
306 data.putBoolean(PhotoPage.KEY_IN_CAMERA_ROLL, mMediaSet.isCameraRoll());
307 if (startInFilmstrip) {
308 mActivity.getStateManager().switchState(this, FilmstripPage.class, data);
310 mActivity.getStateManager().startStateForResult(
311 SinglePhotoPage.class, REQUEST_PHOTO, data);
316 private void onGetContent(final MediaItem item) {
317 DataManager dm = mActivity.getDataManager();
318 Activity activity = mActivity;
319 if (mData.getString(GalleryActivity.EXTRA_CROP) != null) {
320 Uri uri = dm.getContentUri(item.getPath());
321 Intent intent = new Intent(CropActivity.CROP_ACTION, uri)
322 .addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT)
323 .putExtras(getData());
324 if (mData.getParcelable(MediaStore.EXTRA_OUTPUT) == null) {
325 intent.putExtra(CropExtras.KEY_RETURN_DATA, true);
327 activity.startActivity(intent);
330 Intent intent = new Intent(null, item.getContentUri())
331 .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
332 activity.setResult(Activity.RESULT_OK, intent);
337 public void onLongTap(int slotIndex) {
338 if (mGetContent) return;
339 MediaItem item = mAlbumDataAdapter.get(slotIndex);
340 if (item == null) return;
341 mSelectionManager.setAutoLeaveSelectionMode(true);
342 mSelectionManager.toggle(item.getPath());
343 mSlotView.invalidate();
347 public void doCluster(int clusterType) {
348 String basePath = mMediaSet.getPath().toString();
349 String newPath = FilterUtils.newClusterPath(basePath, clusterType);
350 Bundle data = new Bundle(getData());
351 data.putString(AlbumSetPage.KEY_MEDIA_PATH, newPath);
352 if (mShowClusterMenu) {
353 Context context = mActivity.getAndroidContext();
354 data.putString(AlbumSetPage.KEY_SET_TITLE, mMediaSet.getName());
355 data.putString(AlbumSetPage.KEY_SET_SUBTITLE,
356 GalleryActionBar.getClusterByTypeString(context, clusterType));
359 // mAlbumView.savePositions(PositionRepository.getInstance(mActivity));
360 mActivity.getStateManager().startStateForResult(
361 AlbumSetPage.class, REQUEST_DO_ANIMATION, data);
365 protected void onCreate(Bundle data, Bundle restoreState) {
366 super.onCreate(data, restoreState);
367 mUserDistance = GalleryUtils.meterToPixel(USER_DISTANCE_METER);
369 initializeData(data);
370 mGetContent = data.getBoolean(GalleryActivity.KEY_GET_CONTENT, false);
371 mShowClusterMenu = data.getBoolean(KEY_SHOW_CLUSTER_MENU, false);
372 mDetailsSource = new MyDetailsSource();
373 Context context = mActivity.getAndroidContext();
375 if (data.getBoolean(KEY_AUTO_SELECT_ALL)) {
376 mSelectionManager.selectAll();
379 mLaunchedFromPhotoPage =
380 mActivity.getStateManager().hasStateClass(FilmstripPage.class);
381 mInCameraApp = data.getBoolean(PhotoPage.KEY_APP_BRIDGE, false);
383 mHandler = new SynchronizedHandler(mActivity.getGLRoot()) {
385 public void handleMessage(Message message) {
386 switch (message.what) {
387 case MSG_PICK_PHOTO: {
388 pickPhoto(message.arg1);
392 throw new AssertionError(message.what);
399 protected void onResume() {
403 mResumeEffect = mActivity.getTransitionStore().get(KEY_RESUME_ANIMATION);
404 if (mResumeEffect != null) {
405 mAlbumView.setSlotFilter(mResumeEffect);
406 mResumeEffect.setPositionProvider(mPositionProvider);
407 mResumeEffect.start();
410 setContentPane(mRootPane);
412 boolean enableHomeButton = (mActivity.getStateManager().getStateCount() > 1) |
413 mParentMediaSetString != null;
414 GalleryActionBar actionBar = mActivity.getGalleryActionBar();
415 actionBar.setDisplayOptions(enableHomeButton, false);
417 actionBar.enableAlbumModeMenu(GalleryActionBar.ALBUM_GRID_MODE_SELECTED, this);
420 // Set the reload bit here to prevent it exit this page in clearLoadingBit().
421 setLoadingBit(BIT_LOADING_RELOAD);
422 mLoadingFailed = false;
423 mAlbumDataAdapter.resume();
426 mAlbumView.setPressedIndex(-1);
427 mActionModeHandler.resume();
428 if (!mInitialSynced) {
429 setLoadingBit(BIT_LOADING_SYNC);
430 mSyncTask = mMediaSet.requestSync(this);
432 mInCameraAndWantQuitOnPause = mInCameraApp;
436 protected void onPause() {
440 if (mSelectionManager.inSelectionMode()) {
441 mSelectionManager.leaveSelectionMode();
443 mAlbumView.setSlotFilter(null);
444 mActionModeHandler.pause();
445 mAlbumDataAdapter.pause();
447 DetailsHelper.pause();
449 mActivity.getGalleryActionBar().disableAlbumModeMenu(true);
452 if (mSyncTask != null) {
455 clearLoadingBit(BIT_LOADING_SYNC);
460 protected void onDestroy() {
462 if (mAlbumDataAdapter != null) {
463 mAlbumDataAdapter.setLoadingListener(null);
465 mActionModeHandler.destroy();
468 private void initializeViews() {
469 mSelectionManager = new SelectionManager(mActivity, false);
470 mSelectionManager.setSelectionListener(this);
471 Config.AlbumPage config = Config.AlbumPage.get(mActivity);
472 mSlotView = new SlotView(mActivity, config.slotViewSpec);
473 mAlbumView = new AlbumSlotRenderer(mActivity, mSlotView,
474 mSelectionManager, config.placeholderColor);
475 mSlotView.setSlotRenderer(mAlbumView);
476 mRootPane.addComponent(mSlotView);
477 mSlotView.setListener(new SlotView.SimpleListener() {
479 public void onDown(int index) {
480 AlbumPage.this.onDown(index);
484 public void onUp(boolean followedByLongPress) {
485 AlbumPage.this.onUp(followedByLongPress);
489 public void onSingleTapUp(int slotIndex) {
490 AlbumPage.this.onSingleTapUp(slotIndex);
494 public void onLongTap(int slotIndex) {
495 AlbumPage.this.onLongTap(slotIndex);
498 mActionModeHandler = new ActionModeHandler(mActivity, mSelectionManager);
499 mActionModeHandler.setActionModeListener(new ActionModeListener() {
501 public boolean onActionItemClicked(MenuItem item) {
502 return onItemSelected(item);
507 private void initializeData(Bundle data) {
508 mMediaSetPath = Path.fromString(data.getString(KEY_MEDIA_PATH));
509 mParentMediaSetString = data.getString(KEY_PARENT_MEDIA_PATH);
510 mMediaSet = mActivity.getDataManager().getMediaSet(mMediaSetPath);
511 if (mMediaSet == null) {
512 Utils.fail("MediaSet is null. Path = %s", mMediaSetPath);
514 mSelectionManager.setSourceMediaSet(mMediaSet);
515 mAlbumDataAdapter = new AlbumDataLoader(mActivity, mMediaSet);
516 mAlbumDataAdapter.setLoadingListener(new MyLoadingListener());
517 mAlbumView.setModel(mAlbumDataAdapter);
520 private void showDetails() {
522 if (mDetailsHelper == null) {
523 mDetailsHelper = new DetailsHelper(mActivity, mRootPane, mDetailsSource);
524 mDetailsHelper.setCloseListener(new CloseListener() {
526 public void onClose() {
531 mDetailsHelper.show();
534 private void hideDetails() {
535 mShowDetails = false;
536 mDetailsHelper.hide();
537 mAlbumView.setHighlightItemPath(null);
538 mSlotView.invalidate();
542 protected boolean onCreateActionBar(Menu menu) {
543 GalleryActionBar actionBar = mActivity.getGalleryActionBar();
544 MenuInflater inflator = getSupportMenuInflater();
546 inflator.inflate(R.menu.pickup, menu);
547 int typeBits = mData.getInt(GalleryActivity.KEY_TYPE_BITS,
548 DataManager.INCLUDE_IMAGE);
549 actionBar.setTitle(GalleryUtils.getSelectionModePrompt(typeBits));
551 inflator.inflate(R.menu.album, menu);
552 actionBar.setTitle(mMediaSet.getName());
554 FilterUtils.setupMenuItems(actionBar, mMediaSetPath, true);
556 menu.findItem(R.id.action_group_by).setVisible(mShowClusterMenu);
557 menu.findItem(R.id.action_camera).setVisible(
558 MediaSetUtils.isCameraSource(mMediaSetPath)
559 && GalleryUtils.isCameraAvailable(mActivity));
562 actionBar.setSubtitle(null);
566 private void prepareAnimationBackToFilmstrip(int slotIndex) {
567 if (mAlbumDataAdapter == null || !mAlbumDataAdapter.isActive(slotIndex)) return;
568 MediaItem item = mAlbumDataAdapter.get(slotIndex);
569 if (item == null) return;
570 TransitionStore transitions = mActivity.getTransitionStore();
571 transitions.put(PhotoPage.KEY_INDEX_HINT, slotIndex);
572 transitions.put(PhotoPage.KEY_OPEN_ANIMATION_RECT,
573 mSlotView.getSlotRect(slotIndex, mRootPane));
576 private void switchToFilmstrip() {
577 if (mAlbumDataAdapter.size() < 1) return;
578 int targetPhoto = mSlotView.getVisibleStart();
579 prepareAnimationBackToFilmstrip(targetPhoto);
580 if(mLaunchedFromPhotoPage) {
583 pickPhoto(targetPhoto, true);
588 protected boolean onItemSelected(MenuItem item) {
589 switch (item.getItemId()) {
590 case android.R.id.home: {
594 case R.id.action_cancel:
595 mActivity.getStateManager().finishState(this);
597 case R.id.action_select:
598 mSelectionManager.setAutoLeaveSelectionMode(false);
599 mSelectionManager.enterSelectionMode();
601 case R.id.action_group_by: {
602 mActivity.getGalleryActionBar().showClusterDialog(this);
605 case R.id.action_slideshow: {
606 mInCameraAndWantQuitOnPause = false;
607 Bundle data = new Bundle();
608 data.putString(SlideshowPage.KEY_SET_PATH,
609 mMediaSetPath.toString());
610 data.putBoolean(SlideshowPage.KEY_REPEAT, true);
611 mActivity.getStateManager().startStateForResult(
612 SlideshowPage.class, REQUEST_SLIDESHOW, data);
615 case R.id.action_details: {
623 case R.id.action_camera: {
624 GalleryUtils.startCameraActivity(mActivity);
633 protected void onStateResult(int request, int result, Intent data) {
635 case REQUEST_SLIDESHOW: {
636 // data could be null, if there is no images in the album
637 if (data == null) return;
638 mFocusIndex = data.getIntExtra(SlideshowPage.KEY_PHOTO_INDEX, 0);
639 mSlotView.setCenterIndex(mFocusIndex);
642 case REQUEST_PHOTO: {
643 if (data == null) return;
644 mFocusIndex = data.getIntExtra(PhotoPage.KEY_RETURN_INDEX_HINT, 0);
645 mSlotView.makeSlotVisible(mFocusIndex);
648 case REQUEST_DO_ANIMATION: {
649 mSlotView.startRisingAnimation();
656 public void onSelectionModeChange(int mode) {
658 case SelectionManager.ENTER_SELECTION_MODE: {
659 mActionModeHandler.startActionMode();
660 performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
663 case SelectionManager.LEAVE_SELECTION_MODE: {
664 mActionModeHandler.finishActionMode();
665 mRootPane.invalidate();
668 case SelectionManager.SELECT_ALL_MODE: {
669 mActionModeHandler.updateSupportedOperation();
670 mRootPane.invalidate();
677 public void onSelectionChange(Path path, boolean selected) {
678 int count = mSelectionManager.getSelectedCount();
679 String format = mActivity.getResources().getQuantityString(
680 R.plurals.number_of_items_selected, count);
681 mActionModeHandler.setTitle(String.format(format, count));
682 mActionModeHandler.updateSupportedOperation(path, selected);
686 public void onSyncDone(final MediaSet mediaSet, final int resultCode) {
687 Log.d(TAG, "onSyncDone: " + Utils.maskDebugInfo(mediaSet.getName()) + " result="
689 ((Activity) mActivity).runOnUiThread(new Runnable() {
692 GLRoot root = mActivity.getGLRoot();
693 root.lockRenderThread();
694 mSyncResult = resultCode;
696 if (resultCode == MediaSet.SYNC_RESULT_SUCCESS) {
697 mInitialSynced = true;
699 clearLoadingBit(BIT_LOADING_SYNC);
700 showSyncErrorIfNecessary(mLoadingFailed);
702 root.unlockRenderThread();
708 // Show sync error toast when all the following conditions are met:
709 // (1) both loading and sync are done,
710 // (2) sync result is error,
711 // (3) the page is still active, and
712 // (4) no photo is shown or loading fails.
713 private void showSyncErrorIfNecessary(boolean loadingFailed) {
714 if ((mLoadingBits == 0) && (mSyncResult == MediaSet.SYNC_RESULT_ERROR) && mIsActive
715 && (loadingFailed || (mAlbumDataAdapter.size() == 0))) {
716 Toast.makeText(mActivity, R.string.sync_album_error,
717 Toast.LENGTH_LONG).show();
721 private void setLoadingBit(int loadTaskBit) {
722 mLoadingBits |= loadTaskBit;
725 private void clearLoadingBit(int loadTaskBit) {
726 mLoadingBits &= ~loadTaskBit;
727 if (mLoadingBits == 0 && mIsActive) {
728 if (mAlbumDataAdapter.size() == 0) {
729 Intent result = new Intent();
730 result.putExtra(KEY_EMPTY_ALBUM, true);
731 setStateResult(Activity.RESULT_OK, result);
732 mActivity.getStateManager().finishState(this);
737 private class MyLoadingListener implements LoadingListener {
739 public void onLoadingStarted() {
740 setLoadingBit(BIT_LOADING_RELOAD);
741 mLoadingFailed = false;
745 public void onLoadingFinished(boolean loadingFailed) {
746 clearLoadingBit(BIT_LOADING_RELOAD);
747 mLoadingFailed = loadingFailed;
748 showSyncErrorIfNecessary(loadingFailed);
752 private class MyDetailsSource implements DetailsHelper.DetailsSource {
757 return mAlbumDataAdapter.size();
761 public int setIndex() {
762 Path id = mSelectionManager.getSelected(false).get(0);
763 mIndex = mAlbumDataAdapter.findItem(id);
768 public MediaDetails getDetails() {
769 // this relies on setIndex() being called beforehand
770 MediaObject item = mAlbumDataAdapter.get(mIndex);
772 mAlbumView.setHighlightItemPath(item.getPath());
773 return item.getDetails();
781 public void onAlbumModeSelected(int mode) {
782 if (mode == GalleryActionBar.ALBUM_FILMSTRIP_MODE_SELECTED) {