diff options
Diffstat (limited to 'src/com/android/gallery3d/app/AlbumPage.java')
-rw-r--r-- | src/com/android/gallery3d/app/AlbumPage.java | 602 |
1 files changed, 602 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..5c09ce2d2 --- /dev/null +++ b/src/com/android/gallery3d/app/AlbumPage.java @@ -0,0 +1,602 @@ +/* + * 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 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.MtpDevice; +import com.android.gallery3d.data.Path; +import com.android.gallery3d.ui.ActionModeHandler; +import com.android.gallery3d.ui.ActionModeHandler.ActionModeListener; +import com.android.gallery3d.ui.AlbumView; +import com.android.gallery3d.ui.DetailsWindow; +import com.android.gallery3d.ui.DetailsWindow.CloseListener; +import com.android.gallery3d.ui.GLCanvas; +import com.android.gallery3d.ui.GLView; +import com.android.gallery3d.ui.GridDrawer; +import com.android.gallery3d.ui.HighlightDrawer; +import com.android.gallery3d.ui.PositionProvider; +import com.android.gallery3d.ui.PositionRepository; +import com.android.gallery3d.ui.PositionRepository.Position; +import com.android.gallery3d.ui.SelectionManager; +import com.android.gallery3d.ui.SlotView; +import com.android.gallery3d.ui.StaticBackground; +import com.android.gallery3d.util.Future; +import com.android.gallery3d.util.GalleryUtils; + +import android.app.Activity; +import android.app.ProgressDialog; +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; +import android.provider.MediaStore; +import android.view.ActionMode; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.View.MeasureSpec; +import android.widget.Toast; + +import java.util.Random; + +public class AlbumPage extends ActivityState implements GalleryActionBar.ClusterRunner, + SelectionManager.SelectionListener { + @SuppressWarnings("unused") + private static final String TAG = "AlbumPage"; + + public static final String KEY_MEDIA_PATH = "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"; + + private static final int REQUEST_SLIDESHOW = 1; + private static final int REQUEST_PHOTO = 2; + private static final int REQUEST_DO_ANIMATION = 3; + + private static final float USER_DISTANCE_METER = 0.3f; + + private boolean mIsActive = false; + private StaticBackground mStaticBackground; + private AlbumView mAlbumView; + private Path mMediaSetPath; + + private AlbumDataAdapter mAlbumDataAdapter; + + protected SelectionManager mSelectionManager; + private GridDrawer mGridDrawer; + private HighlightDrawer mHighlightDrawer; + + private boolean mGetContent; + private boolean mShowClusterMenu; + + private ActionMode mActionMode; + private ActionModeHandler mActionModeHandler; + private int mFocusIndex = 0; + private DetailsWindow mDetailsWindow; + private MediaSet mMediaSet; + private boolean mShowDetails; + private float mUserDistance; // in pixel + + private ProgressDialog mProgressDialog; + private Future<?> mPendingTask; + + private Future<Void> mSyncTask = null; + + private GLView mRootPane = new GLView() { + private float mMatrix[] = new float[16]; + + @Override + protected void onLayout( + boolean changed, int left, int top, int right, int bottom) { + mStaticBackground.layout(0, 0, right - left, bottom - top); + + int slotViewTop = GalleryActionBar.getHeight((Activity) mActivity); + int slotViewBottom = bottom - top; + int slotViewRight = right - left; + + if (mShowDetails) { + mDetailsWindow.measure( + MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED); + int width = mDetailsWindow.getMeasuredWidth(); + int detailLeft = right - left - width; + slotViewRight = detailLeft; + mDetailsWindow.layout(detailLeft, slotViewTop, detailLeft + width, + bottom - top); + } else { + mAlbumView.setSelectionDrawer(mGridDrawer); + } + + mAlbumView.layout(0, slotViewTop, slotViewRight, slotViewBottom); + GalleryUtils.setViewPointMatrix(mMatrix, + (right - left) / 2, (bottom - top) / 2, -mUserDistance); + PositionRepository.getInstance(mActivity).setOffset( + 0, slotViewTop); + } + + @Override + protected void render(GLCanvas canvas) { + canvas.save(GLCanvas.SAVE_FLAG_MATRIX); + canvas.multiplyMatrix(mMatrix, 0); + super.render(canvas); + canvas.restore(); + } + }; + + @Override + protected void onBackPressed() { + if (mShowDetails) { + hideDetails(); + } else if (mSelectionManager.inSelectionMode()) { + mSelectionManager.leaveSelectionMode(); + } else { + mAlbumView.savePositions(PositionRepository.getInstance(mActivity)); + super.onBackPressed(); + } + } + + public void onSingleTapUp(int slotIndex) { + MediaItem item = mAlbumDataAdapter.get(slotIndex); + if (item == null) { + Log.w(TAG, "item not ready yet, ignore the click"); + return; + } + if (mShowDetails) { + mHighlightDrawer.setHighlightItem(item.getPath()); + mDetailsWindow.reloadDetails(slotIndex); + } else if (!mSelectionManager.inSelectionMode()) { + if (mGetContent) { + onGetContent(item); + } else { + boolean playVideo = + (item.getSupportedOperations() & MediaItem.SUPPORT_PLAY) != 0; + if (playVideo) { + // Play the video. + PhotoPage.playVideo((Activity) mActivity, item.getPlayUri(), item.getName()); + } else { + // Get into the PhotoPage. + Bundle data = new Bundle(); + mAlbumView.savePositions(PositionRepository.getInstance(mActivity)); + data.putInt(PhotoPage.KEY_INDEX_HINT, slotIndex); + data.putString(PhotoPage.KEY_MEDIA_SET_PATH, + mMediaSetPath.toString()); + data.putString(PhotoPage.KEY_MEDIA_ITEM_PATH, + item.getPath().toString()); + mActivity.getStateManager().startStateForResult( + PhotoPage.class, REQUEST_PHOTO, data); + } + } + } else { + mSelectionManager.toggle(item.getPath()); + mAlbumView.invalidate(); + } + } + + private void onGetContent(final MediaItem item) { + DataManager dm = mActivity.getDataManager(); + Activity activity = (Activity) mActivity; + if (mData.getString(Gallery.EXTRA_CROP) != null) { + // TODO: Handle MtpImagew + Uri uri = dm.getContentUri(item.getPath()); + Intent intent = new Intent(CropImage.ACTION_CROP, uri) + .addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT) + .putExtras(getData()); + if (mData.getParcelable(MediaStore.EXTRA_OUTPUT) == null) { + intent.putExtra(CropImage.KEY_RETURN_DATA, true); + } + activity.startActivity(intent); + activity.finish(); + } else { + activity.setResult(Activity.RESULT_OK, + new Intent(null, item.getContentUri())); + activity.finish(); + } + } + + public void onLongTap(int slotIndex) { + if (mGetContent) return; + if (mShowDetails) { + onSingleTapUp(slotIndex); + } else { + MediaItem item = mAlbumDataAdapter.get(slotIndex); + if (item == null) return; + mSelectionManager.setAutoLeaveSelectionMode(true); + mSelectionManager.toggle(item.getPath()); + mAlbumView.invalidate(); + } + } + + 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); + } + + public void doFilter(int filterType) { + String basePath = mMediaSet.getPath().toString(); + String newPath = FilterUtils.switchFilterPath(basePath, filterType); + Bundle data = new Bundle(getData()); + data.putString(AlbumPage.KEY_MEDIA_PATH, newPath); + mAlbumView.savePositions(PositionRepository.getInstance(mActivity)); + mActivity.getStateManager().switchState(this, AlbumPage.class, data); + } + + public void onOperationComplete() { + mAlbumView.invalidate(); + // TODO: enable animation + } + + @Override + protected void onCreate(Bundle data, Bundle 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); + + startTransition(data); + + // Enable auto-select-all for mtp album + if (data.getBoolean(KEY_AUTO_SELECT_ALL)) { + mSelectionManager.selectAll(); + } + } + + private void startTransition() { + final PositionRepository repository = + PositionRepository.getInstance(mActivity); + mAlbumView.startTransition(new PositionProvider() { + private Position mTempPosition = new Position(); + public Position getPosition(long identity, Position target) { + Position p = repository.get(identity); + if (p != null) return p; + mTempPosition.set(target); + mTempPosition.z = 128; + return mTempPosition; + } + }); + } + + private void startTransition(Bundle data) { + final PositionRepository repository = + PositionRepository.getInstance(mActivity); + final int[] center = data == null + ? null + : data.getIntArray(KEY_SET_CENTER); + final Random random = new Random(); + mAlbumView.startTransition(new PositionProvider() { + private Position mTempPosition = new Position(); + public Position getPosition(long identity, Position target) { + Position p = repository.get(identity); + if (p != null) return p; + if (center != null) { + random.setSeed(identity); + mTempPosition.set(center[0], center[1], + 0, random.nextInt(60) - 30, 0); + } else { + mTempPosition.set(target); + mTempPosition.z = 128; + } + return mTempPosition; + } + }); + } + + @Override + protected void onResume() { + super.onResume(); + mIsActive = true; + setContentPane(mRootPane); + mAlbumDataAdapter.resume(); + mAlbumView.resume(); + mActionModeHandler.resume(); + } + + @Override + protected void onPause() { + super.onPause(); + mIsActive = false; + mAlbumDataAdapter.pause(); + mAlbumView.pause(); + if (mDetailsWindow != null) { + mDetailsWindow.pause(); + } + Future<?> task = mPendingTask; + if (task != null) { + // cancel on going task + task.cancel(); + task.waitDone(); + if (mProgressDialog != null) { + mProgressDialog.dismiss(); + mProgressDialog = null; + } + } + if (mSyncTask != null) { + mSyncTask.cancel(); + mSyncTask = null; + } + mActionModeHandler.pause(); + } + + @Override + protected void onDestroy() { + if (mAlbumDataAdapter != null) { + mAlbumDataAdapter.setLoadingListener(null); + } + } + + private void initializeViews() { + mStaticBackground = new StaticBackground((Context) mActivity); + mRootPane.addComponent(mStaticBackground); + + mSelectionManager = new SelectionManager(mActivity, false); + mSelectionManager.setSelectionListener(this); + mGridDrawer = new GridDrawer((Context) mActivity, mSelectionManager); + Config.AlbumPage config = Config.AlbumPage.get((Context) mActivity); + mAlbumView = new AlbumView(mActivity, + config.slotWidth, config.slotHeight, config.displayItemSize); + mAlbumView.setSelectionDrawer(mGridDrawer); + mRootPane.addComponent(mAlbumView); + mAlbumView.setListener(new SlotView.SimpleListener() { + @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() { + public boolean onActionItemClicked(MenuItem item) { + return onItemSelected(item); + } + }); + mStaticBackground.setImage(R.drawable.background, + R.drawable.background_portrait); + } + + private void initializeData(Bundle data) { + mMediaSetPath = Path.fromString(data.getString(KEY_MEDIA_PATH)); + mMediaSet = mActivity.getDataManager().getMediaSet(mMediaSetPath); + Utils.assertTrue(mMediaSet != null, + "MediaSet is null. Path = %s", mMediaSetPath); + mSelectionManager.setSourceMediaSet(mMediaSet); + mAlbumDataAdapter = new AlbumDataAdapter(mActivity, mMediaSet); + mAlbumDataAdapter.setLoadingListener(new MyLoadingListener()); + mAlbumView.setModel(mAlbumDataAdapter); + } + + private void showDetails() { + mShowDetails = true; + if (mDetailsWindow == null) { + mHighlightDrawer = new HighlightDrawer(mActivity.getAndroidContext()); + mDetailsWindow = new DetailsWindow(mActivity, new MyDetailsSource()); + mDetailsWindow.setCloseListener(new CloseListener() { + public void onClose() { + hideDetails(); + } + }); + mRootPane.addComponent(mDetailsWindow); + } + mAlbumView.setSelectionDrawer(mHighlightDrawer); + mDetailsWindow.show(); + } + + private void hideDetails() { + mShowDetails = false; + mAlbumView.setSelectionDrawer(mGridDrawer); + mDetailsWindow.hide(); + } + + @Override + protected boolean onCreateActionBar(Menu menu) { + Activity activity = (Activity) mActivity; + GalleryActionBar actionBar = mActivity.getGalleryActionBar(); + MenuInflater inflater = activity.getMenuInflater(); + + if (mGetContent) { + inflater.inflate(R.menu.pickup, menu); + int typeBits = mData.getInt(Gallery.KEY_TYPE_BITS, + DataManager.INCLUDE_IMAGE); + + actionBar.setTitle(GalleryUtils.getSelectionModePrompt(typeBits)); + } else { + inflater.inflate(R.menu.album, menu); + actionBar.setTitle(mMediaSet.getName()); + if (mMediaSet instanceof MtpDevice) { + menu.findItem(R.id.action_slideshow).setVisible(false); + } else { + menu.findItem(R.id.action_slideshow).setVisible(true); + } + + MenuItem groupBy = menu.findItem(R.id.action_group_by); + FilterUtils.setupMenuItems(actionBar, mMediaSetPath, true); + + if (groupBy != null) { + groupBy.setVisible(mShowClusterMenu); + } + + actionBar.setTitle(mMediaSet.getName()); + } + actionBar.setSubtitle(null); + + return true; + } + + @Override + protected boolean onItemSelected(MenuItem item) { + switch (item.getItemId()) { + 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: { + 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; + } + 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); + mAlbumView.setCenterIndex(mFocusIndex); + break; + } + case REQUEST_PHOTO: { + if (data == null) return; + mFocusIndex = data.getIntExtra(PhotoPage.KEY_INDEX_HINT, 0); + mAlbumView.setCenterIndex(mFocusIndex); + startTransition(); + break; + } + case REQUEST_DO_ANIMATION: { + startTransition(null); + break; + } + } + } + + public void onSelectionModeChange(int mode) { + switch (mode) { + case SelectionManager.ENTER_SELECTION_MODE: { + mActionMode = mActionModeHandler.startActionMode(); + break; + } + case SelectionManager.LEAVE_SELECTION_MODE: { + mActionMode.finish(); + mRootPane.invalidate(); + break; + } + case SelectionManager.SELECT_ALL_MODE: { + int count = mSelectionManager.getSelectedCount(); + String format = mActivity.getResources().getQuantityString( + R.plurals.number_of_items_selected, count); + mActionModeHandler.setTitle(String.format(format, count)); + mActionModeHandler.updateSupportedOperation(); + mRootPane.invalidate(); + break; + } + } + } + + public void onSelectionChange(Path path, boolean selected) { + Utils.assertTrue(mActionMode != null); + 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); + } + + private class MyLoadingListener implements LoadingListener { + @Override + public void onLoadingStarted() { + GalleryUtils.setSpinnerVisibility((Activity) mActivity, true); + } + + @Override + public void onLoadingFinished() { + if (!mIsActive) return; + if (mAlbumDataAdapter.size() == 0) { + if (mSyncTask == null) { + mSyncTask = mMediaSet.requestSync(); + } + if (mSyncTask.isDone()){ + Toast.makeText((Context) mActivity, + R.string.empty_album, Toast.LENGTH_LONG).show(); + mActivity.getStateManager().finishState(AlbumPage.this); + } + } + if (mSyncTask == null || mSyncTask.isDone()) { + GalleryUtils.setSpinnerVisibility((Activity) mActivity, false); + } + } + } + + private class MyDetailsSource implements DetailsWindow.DetailsSource { + private int mIndex; + public int size() { + return mAlbumDataAdapter.size(); + } + + // If requested index is out of active window, suggest a valid index. + // If there is no valid index available, return -1. + public int findIndex(int indexHint) { + if (mAlbumDataAdapter.isActive(indexHint)) { + mIndex = indexHint; + } else { + mIndex = mAlbumDataAdapter.getActiveStart(); + if (!mAlbumDataAdapter.isActive(mIndex)) { + return -1; + } + } + return mIndex; + } + + public MediaDetails getDetails() { + MediaObject item = mAlbumDataAdapter.get(mIndex); + if (item != null) { + mHighlightDrawer.setHighlightItem(item.getPath()); + return item.getDetails(); + } else { + return null; + } + } + } +} |