diff options
Diffstat (limited to 'src/com/android/gallery3d/app/AlbumPage.java')
-rw-r--r-- | src/com/android/gallery3d/app/AlbumPage.java | 786 |
1 files changed, 786 insertions, 0 deletions
diff --git a/src/com/android/gallery3d/app/AlbumPage.java b/src/com/android/gallery3d/app/AlbumPage.java new file mode 100644 index 000000000..658abbbd4 --- /dev/null +++ b/src/com/android/gallery3d/app/AlbumPage.java @@ -0,0 +1,786 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.gallery3d.app; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.graphics.Rect; +import android.net.Uri; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.provider.MediaStore; +import android.view.HapticFeedbackConstants; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.widget.Toast; + +import com.android.gallery3d.R; +import com.android.gallery3d.common.Utils; +import com.android.gallery3d.data.DataManager; +import com.android.gallery3d.data.MediaDetails; +import com.android.gallery3d.data.MediaItem; +import com.android.gallery3d.data.MediaObject; +import com.android.gallery3d.data.MediaSet; +import com.android.gallery3d.data.Path; +import com.android.gallery3d.filtershow.crop.CropActivity; +import com.android.gallery3d.filtershow.crop.CropExtras; +import com.android.gallery3d.glrenderer.FadeTexture; +import com.android.gallery3d.glrenderer.GLCanvas; +import com.android.gallery3d.ui.ActionModeHandler; +import com.android.gallery3d.ui.ActionModeHandler.ActionModeListener; +import com.android.gallery3d.ui.AlbumSlotRenderer; +import com.android.gallery3d.ui.DetailsHelper; +import com.android.gallery3d.ui.DetailsHelper.CloseListener; +import com.android.gallery3d.ui.GLRoot; +import com.android.gallery3d.ui.GLView; +import com.android.gallery3d.ui.PhotoFallbackEffect; +import com.android.gallery3d.ui.RelativePosition; +import com.android.gallery3d.ui.SelectionManager; +import com.android.gallery3d.ui.SlotView; +import com.android.gallery3d.ui.SynchronizedHandler; +import com.android.gallery3d.util.Future; +import com.android.gallery3d.util.GalleryUtils; +import com.android.gallery3d.util.MediaSetUtils; + + +public class AlbumPage extends ActivityState implements GalleryActionBar.ClusterRunner, + SelectionManager.SelectionListener, MediaSet.SyncListener, GalleryActionBar.OnAlbumModeSelectedListener { + @SuppressWarnings("unused") + private static final String TAG = "AlbumPage"; + + public static final String KEY_MEDIA_PATH = "media-path"; + public static final String KEY_PARENT_MEDIA_PATH = "parent-media-path"; + public static final String KEY_SET_CENTER = "set-center"; + public static final String KEY_AUTO_SELECT_ALL = "auto-select-all"; + public static final String KEY_SHOW_CLUSTER_MENU = "cluster-menu"; + public static final String KEY_EMPTY_ALBUM = "empty-album"; + public static final String KEY_RESUME_ANIMATION = "resume_animation"; + + private static final int REQUEST_SLIDESHOW = 1; + public static final int REQUEST_PHOTO = 2; + private static final int REQUEST_DO_ANIMATION = 3; + + private static final int BIT_LOADING_RELOAD = 1; + private static final int BIT_LOADING_SYNC = 2; + + private static final float USER_DISTANCE_METER = 0.3f; + + private boolean mIsActive = false; + private AlbumSlotRenderer mAlbumView; + private Path mMediaSetPath; + private String mParentMediaSetString; + private SlotView mSlotView; + + private AlbumDataLoader mAlbumDataAdapter; + + protected SelectionManager mSelectionManager; + + private boolean mGetContent; + private boolean mShowClusterMenu; + + private ActionModeHandler mActionModeHandler; + private int mFocusIndex = 0; + private DetailsHelper mDetailsHelper; + private MyDetailsSource mDetailsSource; + private MediaSet mMediaSet; + private boolean mShowDetails; + private float mUserDistance; // in pixel + private Future<Integer> mSyncTask = null; + private boolean mLaunchedFromPhotoPage; + private boolean mInCameraApp; + private boolean mInCameraAndWantQuitOnPause; + + private int mLoadingBits = 0; + private boolean mInitialSynced = false; + private int mSyncResult; + private boolean mLoadingFailed; + private RelativePosition mOpenCenter = new RelativePosition(); + + private Handler mHandler; + private static final int MSG_PICK_PHOTO = 0; + + private PhotoFallbackEffect mResumeEffect; + private PhotoFallbackEffect.PositionProvider mPositionProvider = + new PhotoFallbackEffect.PositionProvider() { + @Override + public Rect getPosition(int index) { + Rect rect = mSlotView.getSlotRect(index); + Rect bounds = mSlotView.bounds(); + rect.offset(bounds.left - mSlotView.getScrollX(), + bounds.top - mSlotView.getScrollY()); + return rect; + } + + @Override + public int getItemIndex(Path path) { + int start = mSlotView.getVisibleStart(); + int end = mSlotView.getVisibleEnd(); + for (int i = start; i < end; ++i) { + MediaItem item = mAlbumDataAdapter.get(i); + if (item != null && item.getPath() == path) return i; + } + return -1; + } + }; + + @Override + protected int getBackgroundColorId() { + return R.color.album_background; + } + + private final GLView mRootPane = new GLView() { + private final float mMatrix[] = new float[16]; + + @Override + protected void onLayout( + boolean changed, int left, int top, int right, int bottom) { + + int slotViewTop = mActivity.getGalleryActionBar().getHeight(); + int slotViewBottom = bottom - top; + int slotViewRight = right - left; + + if (mShowDetails) { + mDetailsHelper.layout(left, slotViewTop, right, bottom); + } else { + mAlbumView.setHighlightItemPath(null); + } + + // Set the mSlotView as a reference point to the open animation + mOpenCenter.setReferencePosition(0, slotViewTop); + mSlotView.layout(0, slotViewTop, slotViewRight, slotViewBottom); + GalleryUtils.setViewPointMatrix(mMatrix, + (right - left) / 2, (bottom - top) / 2, -mUserDistance); + } + + @Override + protected void render(GLCanvas canvas) { + canvas.save(GLCanvas.SAVE_FLAG_MATRIX); + canvas.multiplyMatrix(mMatrix, 0); + super.render(canvas); + + if (mResumeEffect != null) { + boolean more = mResumeEffect.draw(canvas); + if (!more) { + mResumeEffect = null; + mAlbumView.setSlotFilter(null); + } + // We want to render one more time even when no more effect + // required. So that the animated thumbnails could be draw + // with declarations in super.render(). + invalidate(); + } + canvas.restore(); + } + }; + + // This are the transitions we want: + // + // +--------+ +------------+ +-------+ +----------+ + // | Camera |---------->| Fullscreen |--->| Album |--->| AlbumSet | + // | View | thumbnail | Photo | up | Page | up | Page | + // +--------+ +------------+ +-------+ +----------+ + // ^ | | ^ | + // | | | | | close + // +----------back--------+ +----back----+ +--back-> app + // + @Override + protected void onBackPressed() { + if (mShowDetails) { + hideDetails(); + } else if (mSelectionManager.inSelectionMode()) { + mSelectionManager.leaveSelectionMode(); + } else { + if(mLaunchedFromPhotoPage) { + mActivity.getTransitionStore().putIfNotPresent( + PhotoPage.KEY_ALBUMPAGE_TRANSITION, + PhotoPage.MSG_ALBUMPAGE_RESUMED); + } + // TODO: fix this regression + // mAlbumView.savePositions(PositionRepository.getInstance(mActivity)); + if (mInCameraApp) { + super.onBackPressed(); + } else { + onUpPressed(); + } + } + } + + private void onUpPressed() { + if (mInCameraApp) { + GalleryUtils.startGalleryActivity(mActivity); + } else if (mActivity.getStateManager().getStateCount() > 1) { + super.onBackPressed(); + } else if (mParentMediaSetString != null) { + Bundle data = new Bundle(getData()); + data.putString(AlbumSetPage.KEY_MEDIA_PATH, mParentMediaSetString); + mActivity.getStateManager().switchState( + this, AlbumSetPage.class, data); + } + } + + private void onDown(int index) { + mAlbumView.setPressedIndex(index); + } + + private void onUp(boolean followedByLongPress) { + if (followedByLongPress) { + // Avoid showing press-up animations for long-press. + mAlbumView.setPressedIndex(-1); + } else { + mAlbumView.setPressedUp(); + } + } + + private void onSingleTapUp(int slotIndex) { + if (!mIsActive) return; + + if (mSelectionManager.inSelectionMode()) { + MediaItem item = mAlbumDataAdapter.get(slotIndex); + if (item == null) return; // Item not ready yet, ignore the click + mSelectionManager.toggle(item.getPath()); + mSlotView.invalidate(); + } else { + // Render transition in pressed state + mAlbumView.setPressedIndex(slotIndex); + mAlbumView.setPressedUp(); + mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_PICK_PHOTO, slotIndex, 0), + FadeTexture.DURATION); + } + } + + private void pickPhoto(int slotIndex) { + pickPhoto(slotIndex, false); + } + + private void pickPhoto(int slotIndex, boolean startInFilmstrip) { + if (!mIsActive) return; + + if (!startInFilmstrip) { + // Launch photos in lights out mode + mActivity.getGLRoot().setLightsOutMode(true); + } + + MediaItem item = mAlbumDataAdapter.get(slotIndex); + if (item == null) return; // Item not ready yet, ignore the click + if (mGetContent) { + onGetContent(item); + } else if (mLaunchedFromPhotoPage) { + TransitionStore transitions = mActivity.getTransitionStore(); + transitions.put( + PhotoPage.KEY_ALBUMPAGE_TRANSITION, + PhotoPage.MSG_ALBUMPAGE_PICKED); + transitions.put(PhotoPage.KEY_INDEX_HINT, slotIndex); + onBackPressed(); + } else { + // Get into the PhotoPage. + // mAlbumView.savePositions(PositionRepository.getInstance(mActivity)); + Bundle data = new Bundle(); + data.putInt(PhotoPage.KEY_INDEX_HINT, slotIndex); + data.putParcelable(PhotoPage.KEY_OPEN_ANIMATION_RECT, + mSlotView.getSlotRect(slotIndex, mRootPane)); + data.putString(PhotoPage.KEY_MEDIA_SET_PATH, + mMediaSetPath.toString()); + data.putString(PhotoPage.KEY_MEDIA_ITEM_PATH, + item.getPath().toString()); + data.putInt(PhotoPage.KEY_ALBUMPAGE_TRANSITION, + PhotoPage.MSG_ALBUMPAGE_STARTED); + data.putBoolean(PhotoPage.KEY_START_IN_FILMSTRIP, + startInFilmstrip); + data.putBoolean(PhotoPage.KEY_IN_CAMERA_ROLL, mMediaSet.isCameraRoll()); + if (startInFilmstrip) { + mActivity.getStateManager().switchState(this, FilmstripPage.class, data); + } else { + mActivity.getStateManager().startStateForResult( + SinglePhotoPage.class, REQUEST_PHOTO, data); + } + } + } + + private void onGetContent(final MediaItem item) { + DataManager dm = mActivity.getDataManager(); + Activity activity = mActivity; + if (mData.getString(Gallery.EXTRA_CROP) != null) { + Uri uri = dm.getContentUri(item.getPath()); + Intent intent = new Intent(CropActivity.CROP_ACTION, uri) + .addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT) + .putExtras(getData()); + if (mData.getParcelable(MediaStore.EXTRA_OUTPUT) == null) { + intent.putExtra(CropExtras.KEY_RETURN_DATA, true); + } + activity.startActivity(intent); + activity.finish(); + } else { + Intent intent = new Intent(null, item.getContentUri()) + .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + activity.setResult(Activity.RESULT_OK, intent); + activity.finish(); + } + } + + public void onLongTap(int slotIndex) { + if (mGetContent) return; + MediaItem item = mAlbumDataAdapter.get(slotIndex); + if (item == null) return; + mSelectionManager.setAutoLeaveSelectionMode(true); + mSelectionManager.toggle(item.getPath()); + mSlotView.invalidate(); + } + + @Override + public void doCluster(int clusterType) { + String basePath = mMediaSet.getPath().toString(); + String newPath = FilterUtils.newClusterPath(basePath, clusterType); + Bundle data = new Bundle(getData()); + data.putString(AlbumSetPage.KEY_MEDIA_PATH, newPath); + if (mShowClusterMenu) { + Context context = mActivity.getAndroidContext(); + data.putString(AlbumSetPage.KEY_SET_TITLE, mMediaSet.getName()); + data.putString(AlbumSetPage.KEY_SET_SUBTITLE, + GalleryActionBar.getClusterByTypeString(context, clusterType)); + } + + // mAlbumView.savePositions(PositionRepository.getInstance(mActivity)); + mActivity.getStateManager().startStateForResult( + AlbumSetPage.class, REQUEST_DO_ANIMATION, data); + } + + @Override + protected void onCreate(Bundle data, Bundle restoreState) { + super.onCreate(data, restoreState); + mUserDistance = GalleryUtils.meterToPixel(USER_DISTANCE_METER); + initializeViews(); + initializeData(data); + mGetContent = data.getBoolean(Gallery.KEY_GET_CONTENT, false); + mShowClusterMenu = data.getBoolean(KEY_SHOW_CLUSTER_MENU, false); + mDetailsSource = new MyDetailsSource(); + Context context = mActivity.getAndroidContext(); + + if (data.getBoolean(KEY_AUTO_SELECT_ALL)) { + mSelectionManager.selectAll(); + } + + mLaunchedFromPhotoPage = + mActivity.getStateManager().hasStateClass(FilmstripPage.class); + mInCameraApp = data.getBoolean(PhotoPage.KEY_APP_BRIDGE, false); + + mHandler = new SynchronizedHandler(mActivity.getGLRoot()) { + @Override + public void handleMessage(Message message) { + switch (message.what) { + case MSG_PICK_PHOTO: { + pickPhoto(message.arg1); + break; + } + default: + throw new AssertionError(message.what); + } + } + }; + } + + @Override + protected void onResume() { + super.onResume(); + mIsActive = true; + + mResumeEffect = mActivity.getTransitionStore().get(KEY_RESUME_ANIMATION); + if (mResumeEffect != null) { + mAlbumView.setSlotFilter(mResumeEffect); + mResumeEffect.setPositionProvider(mPositionProvider); + mResumeEffect.start(); + } + + setContentPane(mRootPane); + + boolean enableHomeButton = (mActivity.getStateManager().getStateCount() > 1) | + mParentMediaSetString != null; + GalleryActionBar actionBar = mActivity.getGalleryActionBar(); + actionBar.setDisplayOptions(enableHomeButton, false); + if (!mGetContent) { + actionBar.enableAlbumModeMenu(GalleryActionBar.ALBUM_GRID_MODE_SELECTED, this); + } + + // Set the reload bit here to prevent it exit this page in clearLoadingBit(). + setLoadingBit(BIT_LOADING_RELOAD); + mLoadingFailed = false; + mAlbumDataAdapter.resume(); + + mAlbumView.resume(); + mAlbumView.setPressedIndex(-1); + mActionModeHandler.resume(); + if (!mInitialSynced) { + setLoadingBit(BIT_LOADING_SYNC); + mSyncTask = mMediaSet.requestSync(this); + } + mInCameraAndWantQuitOnPause = mInCameraApp; + } + + @Override + protected void onPause() { + super.onPause(); + mIsActive = false; + + if (mSelectionManager.inSelectionMode()) { + mSelectionManager.leaveSelectionMode(); + } + mAlbumView.setSlotFilter(null); + mActionModeHandler.pause(); + mAlbumDataAdapter.pause(); + mAlbumView.pause(); + DetailsHelper.pause(); + if (!mGetContent) { + mActivity.getGalleryActionBar().disableAlbumModeMenu(true); + } + + if (mSyncTask != null) { + mSyncTask.cancel(); + mSyncTask = null; + clearLoadingBit(BIT_LOADING_SYNC); + } + } + + @Override + protected void onDestroy() { + super.onDestroy(); + if (mAlbumDataAdapter != null) { + mAlbumDataAdapter.setLoadingListener(null); + } + mActionModeHandler.destroy(); + } + + private void initializeViews() { + mSelectionManager = new SelectionManager(mActivity, false); + mSelectionManager.setSelectionListener(this); + Config.AlbumPage config = Config.AlbumPage.get(mActivity); + mSlotView = new SlotView(mActivity, config.slotViewSpec); + mAlbumView = new AlbumSlotRenderer(mActivity, mSlotView, + mSelectionManager, config.placeholderColor); + mSlotView.setSlotRenderer(mAlbumView); + mRootPane.addComponent(mSlotView); + mSlotView.setListener(new SlotView.SimpleListener() { + @Override + public void onDown(int index) { + AlbumPage.this.onDown(index); + } + + @Override + public void onUp(boolean followedByLongPress) { + AlbumPage.this.onUp(followedByLongPress); + } + + @Override + public void onSingleTapUp(int slotIndex) { + AlbumPage.this.onSingleTapUp(slotIndex); + } + + @Override + public void onLongTap(int slotIndex) { + AlbumPage.this.onLongTap(slotIndex); + } + }); + mActionModeHandler = new ActionModeHandler(mActivity, mSelectionManager); + mActionModeHandler.setActionModeListener(new ActionModeListener() { + @Override + public boolean onActionItemClicked(MenuItem item) { + return onItemSelected(item); + } + }); + } + + private void initializeData(Bundle data) { + mMediaSetPath = Path.fromString(data.getString(KEY_MEDIA_PATH)); + mParentMediaSetString = data.getString(KEY_PARENT_MEDIA_PATH); + mMediaSet = mActivity.getDataManager().getMediaSet(mMediaSetPath); + if (mMediaSet == null) { + Utils.fail("MediaSet is null. Path = %s", mMediaSetPath); + } + mSelectionManager.setSourceMediaSet(mMediaSet); + mAlbumDataAdapter = new AlbumDataLoader(mActivity, mMediaSet); + mAlbumDataAdapter.setLoadingListener(new MyLoadingListener()); + mAlbumView.setModel(mAlbumDataAdapter); + } + + private void showDetails() { + mShowDetails = true; + if (mDetailsHelper == null) { + mDetailsHelper = new DetailsHelper(mActivity, mRootPane, mDetailsSource); + mDetailsHelper.setCloseListener(new CloseListener() { + @Override + public void onClose() { + hideDetails(); + } + }); + } + mDetailsHelper.show(); + } + + private void hideDetails() { + mShowDetails = false; + mDetailsHelper.hide(); + mAlbumView.setHighlightItemPath(null); + mSlotView.invalidate(); + } + + @Override + protected boolean onCreateActionBar(Menu menu) { + GalleryActionBar actionBar = mActivity.getGalleryActionBar(); + MenuInflater inflator = getSupportMenuInflater(); + if (mGetContent) { + inflator.inflate(R.menu.pickup, menu); + int typeBits = mData.getInt(Gallery.KEY_TYPE_BITS, + DataManager.INCLUDE_IMAGE); + actionBar.setTitle(GalleryUtils.getSelectionModePrompt(typeBits)); + } else { + inflator.inflate(R.menu.album, menu); + actionBar.setTitle(mMediaSet.getName()); + + FilterUtils.setupMenuItems(actionBar, mMediaSetPath, true); + + menu.findItem(R.id.action_group_by).setVisible(mShowClusterMenu); + menu.findItem(R.id.action_camera).setVisible( + MediaSetUtils.isCameraSource(mMediaSetPath) + && GalleryUtils.isCameraAvailable(mActivity)); + + } + actionBar.setSubtitle(null); + return true; + } + + private void prepareAnimationBackToFilmstrip(int slotIndex) { + if (mAlbumDataAdapter == null || !mAlbumDataAdapter.isActive(slotIndex)) return; + MediaItem item = mAlbumDataAdapter.get(slotIndex); + if (item == null) return; + TransitionStore transitions = mActivity.getTransitionStore(); + transitions.put(PhotoPage.KEY_INDEX_HINT, slotIndex); + transitions.put(PhotoPage.KEY_OPEN_ANIMATION_RECT, + mSlotView.getSlotRect(slotIndex, mRootPane)); + } + + private void switchToFilmstrip() { + if (mAlbumDataAdapter.size() < 1) return; + int targetPhoto = mSlotView.getVisibleStart(); + prepareAnimationBackToFilmstrip(targetPhoto); + if(mLaunchedFromPhotoPage) { + onBackPressed(); + } else { + pickPhoto(targetPhoto, true); + } + } + + @Override + protected boolean onItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: { + onUpPressed(); + return true; + } + case R.id.action_cancel: + mActivity.getStateManager().finishState(this); + return true; + case R.id.action_select: + mSelectionManager.setAutoLeaveSelectionMode(false); + mSelectionManager.enterSelectionMode(); + return true; + case R.id.action_group_by: { + mActivity.getGalleryActionBar().showClusterDialog(this); + return true; + } + case R.id.action_slideshow: { + mInCameraAndWantQuitOnPause = false; + Bundle data = new Bundle(); + data.putString(SlideshowPage.KEY_SET_PATH, + mMediaSetPath.toString()); + data.putBoolean(SlideshowPage.KEY_REPEAT, true); + mActivity.getStateManager().startStateForResult( + SlideshowPage.class, REQUEST_SLIDESHOW, data); + return true; + } + case R.id.action_details: { + if (mShowDetails) { + hideDetails(); + } else { + showDetails(); + } + return true; + } + case R.id.action_camera: { + GalleryUtils.startCameraActivity(mActivity); + return true; + } + default: + return false; + } + } + + @Override + protected void onStateResult(int request, int result, Intent data) { + switch (request) { + case REQUEST_SLIDESHOW: { + // data could be null, if there is no images in the album + if (data == null) return; + mFocusIndex = data.getIntExtra(SlideshowPage.KEY_PHOTO_INDEX, 0); + mSlotView.setCenterIndex(mFocusIndex); + break; + } + case REQUEST_PHOTO: { + if (data == null) return; + mFocusIndex = data.getIntExtra(PhotoPage.KEY_RETURN_INDEX_HINT, 0); + mSlotView.makeSlotVisible(mFocusIndex); + break; + } + case REQUEST_DO_ANIMATION: { + mSlotView.startRisingAnimation(); + break; + } + } + } + + @Override + public void onSelectionModeChange(int mode) { + switch (mode) { + case SelectionManager.ENTER_SELECTION_MODE: { + mActionModeHandler.startActionMode(); + performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); + break; + } + case SelectionManager.LEAVE_SELECTION_MODE: { + mActionModeHandler.finishActionMode(); + mRootPane.invalidate(); + break; + } + case SelectionManager.SELECT_ALL_MODE: { + mActionModeHandler.updateSupportedOperation(); + mRootPane.invalidate(); + break; + } + } + } + + @Override + public void onSelectionChange(Path path, boolean selected) { + int count = mSelectionManager.getSelectedCount(); + String format = mActivity.getResources().getQuantityString( + R.plurals.number_of_items_selected, count); + mActionModeHandler.setTitle(String.format(format, count)); + mActionModeHandler.updateSupportedOperation(path, selected); + } + + @Override + public void onSyncDone(final MediaSet mediaSet, final int resultCode) { + Log.d(TAG, "onSyncDone: " + Utils.maskDebugInfo(mediaSet.getName()) + " result=" + + resultCode); + ((Activity) mActivity).runOnUiThread(new Runnable() { + @Override + public void run() { + GLRoot root = mActivity.getGLRoot(); + root.lockRenderThread(); + mSyncResult = resultCode; + try { + if (resultCode == MediaSet.SYNC_RESULT_SUCCESS) { + mInitialSynced = true; + } + clearLoadingBit(BIT_LOADING_SYNC); + showSyncErrorIfNecessary(mLoadingFailed); + } finally { + root.unlockRenderThread(); + } + } + }); + } + + // Show sync error toast when all the following conditions are met: + // (1) both loading and sync are done, + // (2) sync result is error, + // (3) the page is still active, and + // (4) no photo is shown or loading fails. + private void showSyncErrorIfNecessary(boolean loadingFailed) { + if ((mLoadingBits == 0) && (mSyncResult == MediaSet.SYNC_RESULT_ERROR) && mIsActive + && (loadingFailed || (mAlbumDataAdapter.size() == 0))) { + Toast.makeText(mActivity, R.string.sync_album_error, + Toast.LENGTH_LONG).show(); + } + } + + private void setLoadingBit(int loadTaskBit) { + mLoadingBits |= loadTaskBit; + } + + private void clearLoadingBit(int loadTaskBit) { + mLoadingBits &= ~loadTaskBit; + if (mLoadingBits == 0 && mIsActive) { + if (mAlbumDataAdapter.size() == 0) { + Intent result = new Intent(); + result.putExtra(KEY_EMPTY_ALBUM, true); + setStateResult(Activity.RESULT_OK, result); + mActivity.getStateManager().finishState(this); + } + } + } + + private class MyLoadingListener implements LoadingListener { + @Override + public void onLoadingStarted() { + setLoadingBit(BIT_LOADING_RELOAD); + mLoadingFailed = false; + } + + @Override + public void onLoadingFinished(boolean loadingFailed) { + clearLoadingBit(BIT_LOADING_RELOAD); + mLoadingFailed = loadingFailed; + showSyncErrorIfNecessary(loadingFailed); + } + } + + private class MyDetailsSource implements DetailsHelper.DetailsSource { + private int mIndex; + + @Override + public int size() { + return mAlbumDataAdapter.size(); + } + + @Override + public int setIndex() { + Path id = mSelectionManager.getSelected(false).get(0); + mIndex = mAlbumDataAdapter.findItem(id); + return mIndex; + } + + @Override + public MediaDetails getDetails() { + // this relies on setIndex() being called beforehand + MediaObject item = mAlbumDataAdapter.get(mIndex); + if (item != null) { + mAlbumView.setHighlightItemPath(item.getPath()); + return item.getDetails(); + } else { + return null; + } + } + } + + @Override + public void onAlbumModeSelected(int mode) { + if (mode == GalleryActionBar.ALBUM_FILMSTRIP_MODE_SELECTED) { + switchToFilmstrip(); + } + } +} |