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.os.Vibrator;
import android.provider.MediaStore;
import android.view.ActionMode;
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.AlbumSlotRenderer;
import com.android.gallery3d.ui.DetailsHelper;
import com.android.gallery3d.ui.DetailsHelper.CloseListener;
+import com.android.gallery3d.ui.FadeTexture;
import com.android.gallery3d.ui.GLCanvas;
+import com.android.gallery3d.ui.GLRoot;
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.RelativePosition;
import com.android.gallery3d.ui.SelectionManager;
import com.android.gallery3d.ui.SlotView;
-import com.android.gallery3d.ui.StaticBackground;
+import com.android.gallery3d.ui.SynchronizedHandler;
import com.android.gallery3d.util.Future;
import com.android.gallery3d.util.GalleryUtils;
-
-import java.util.Random;
+import com.android.gallery3d.util.MediaSetUtils;
public class AlbumPage extends ActivityState implements GalleryActionBar.ClusterRunner,
SelectionManager.SelectionListener, MediaSet.SyncListener {
@SuppressWarnings("unused")
private static final String TAG = "AlbumPage";
+ private static final int MSG_PICK_PHOTO = 1;
+
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";
private static final float USER_DISTANCE_METER = 0.3f;
private boolean mIsActive = false;
- private StaticBackground mStaticBackground;
- private AlbumView mAlbumView;
+ private AlbumSlotRenderer mAlbumView;
private Path mMediaSetPath;
+ private String mParentMediaSetString;
+ private SlotView mSlotView;
- private AlbumDataAdapter mAlbumDataAdapter;
+ private AlbumDataLoader mAlbumDataAdapter;
protected SelectionManager mSelectionManager;
private Vibrator mVibrator;
- private GridDrawer mGridDrawer;
- private HighlightDrawer mHighlightDrawer;
private boolean mGetContent;
private boolean mShowClusterMenu;
private MediaSet mMediaSet;
private boolean mShowDetails;
private float mUserDistance; // in pixel
+ private Handler mHandler;
private Future<Integer> mSyncTask = null;
private int mLoadingBits = 0;
private boolean mInitialSynced = false;
+ private RelativePosition mOpenCenter = new RelativePosition();
private final GLView mRootPane = new GLView() {
private final float mMatrix[] = new float[16];
@Override
+ protected void renderBackground(GLCanvas view) {
+ view.clearBuffer();
+ }
+
+ @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 slotViewTop = mActivity.getGalleryActionBar().getHeight();
int slotViewBottom = bottom - top;
int slotViewRight = right - left;
if (mShowDetails) {
mDetailsHelper.layout(left, slotViewTop, right, bottom);
} else {
- mAlbumView.setSelectionDrawer(mGridDrawer);
+ mAlbumView.setHighlightItemPath(null);
}
- mAlbumView.layout(0, slotViewTop, slotViewRight, slotViewBottom);
+ // 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);
- PositionRepository.getInstance(mActivity).setOffset(
- 0, slotViewTop);
}
@Override
}
};
+ // 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) {
} else if (mSelectionManager.inSelectionMode()) {
mSelectionManager.leaveSelectionMode();
} else {
- mAlbumView.savePositions(PositionRepository.getInstance(mActivity));
+ // TODO: fix this regression
+ // mAlbumView.savePositions(PositionRepository.getInstance(mActivity));
+ onUpPressed();
+ }
+ }
+
+ private void onUpPressed() {
+ 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) {
- MediaItem item = mAlbumDataAdapter.get(index);
- Path path = (item == null) ? null : item.getPath();
- mSelectionManager.setPressedPath(path);
- mAlbumView.invalidate();
+ mAlbumView.setPressedIndex(index);
}
- private void onUp() {
- mSelectionManager.setPressedPath(null);
- mAlbumView.invalidate();
+ private void onUp(boolean followedByLongPress) {
+ if (followedByLongPress) {
+ // Avoid showing press-up animations for long-press.
+ mAlbumView.setPressedIndex(-1);
+ } else {
+ mAlbumView.setPressedUp();
+ }
}
- public void onSingleTapUp(int slotIndex) {
- MediaItem item = mAlbumDataAdapter.get(slotIndex);
- if (item == null) {
- Log.w(TAG, "item not ready yet, ignore the click");
- return;
+ 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 {
+ // Show pressed-up animation for the single-tap.
+ mAlbumView.setPressedIndex(slotIndex);
+ mAlbumView.setPressedUp();
+ mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_PICK_PHOTO, slotIndex, 0),
+ FadeTexture.DURATION);
}
- if (mShowDetails) {
- mHighlightDrawer.setHighlightItem(item.getPath());
- mDetailsHelper.reloadDetails(slotIndex);
- } else if (!mSelectionManager.inSelectionMode()) {
- if (mGetContent) {
- onGetContent(item);
- } 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);
- }
+ }
+
+ private void pickPhoto(int slotIndex) {
+ if (!mIsActive) return;
+
+ MediaItem item = mAlbumDataAdapter.get(slotIndex);
+ if (item == null) return; // Item not ready yet, ignore the click
+ if (mGetContent) {
+ onGetContent(item);
} else {
- mSelectionManager.toggle(item.getPath());
- mDetailsSource.findIndex(slotIndex);
- mAlbumView.invalidate();
+ // 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,
+ getSlotRect(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);
}
}
+ private Rect getSlotRect(int slotIndex) {
+ // Get slot rectangle relative to this root pane.
+ Rect offset = new Rect();
+ mRootPane.getBoundsOf(mSlotView, offset);
+ Rect r = mSlotView.getSlotRect(slotIndex);
+ r.offset(offset.left - mSlotView.getScrollX(),
+ offset.top - mSlotView.getScrollY());
+ return r;
+ }
+
private void onGetContent(final MediaItem item) {
DataManager dm = mActivity.getDataManager();
Activity activity = (Activity) mActivity;
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());
- mDetailsSource.findIndex(slotIndex);
- mAlbumView.invalidate();
- }
+ 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);
GalleryActionBar.getClusterByTypeString(context, clusterType));
}
- mAlbumView.savePositions(PositionRepository.getInstance(mActivity));
+ // 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);
Context context = mActivity.getAndroidContext();
mVibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
- 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 final Position mTempPosition = new Position();
- public Position getPosition(int identity, Position target) {
- Position p = repository.get(identity);
- if (p != null) return p;
- mTempPosition.set(target);
- mTempPosition.z = 128;
- return mTempPosition;
+ // Don't show animation if it is restored
+ if (restoreState == null && data != null) {
+ int[] center = data.getIntArray(KEY_SET_CENTER);
+ if (center != null) {
+ mOpenCenter.setAbsolutePosition(center[0], center[1]);
+ mSlotView.startScatteringAnimation(mOpenCenter);
}
- });
- }
+ }
- 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 final Position mTempPosition = new Position();
- public Position getPosition(int 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;
+ 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);
}
- return mTempPosition;
}
- });
+ };
}
@Override
mIsActive = true;
setContentPane(mRootPane);
+ Path path = mMediaSet.getPath();
+ boolean enableHomeButton = (mActivity.getStateManager().getStateCount() > 1) |
+ mParentMediaSetString != null;
+ mActivity.getGalleryActionBar().setDisplayOptions(enableHomeButton, true);
+
// Set the reload bit here to prevent it exit this page in clearLoadingBit().
setLoadingBit(BIT_LOADING_RELOAD);
mAlbumDataAdapter.resume();
}
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.slotViewSpec,
- 0 /* don't cache thumbnail */);
- mAlbumView.setSelectionDrawer(mGridDrawer);
- mRootPane.addComponent(mAlbumView);
- mAlbumView.setListener(new SlotView.SimpleListener() {
+ mSlotView = new SlotView(mActivity, config.slotViewSpec);
+ mAlbumView = new AlbumSlotRenderer(mActivity, mSlotView, mSelectionManager);
+ 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() {
- AlbumPage.this.onUp();
+ public void onUp(boolean followedByLongPress) {
+ AlbumPage.this.onUp(followedByLongPress);
}
@Override
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));
+ mParentMediaSetString = data.getString(KEY_PARENT_MEDIA_PATH);
mMediaSet = mActivity.getDataManager().getMediaSet(mMediaSetPath);
- Utils.assertTrue(mMediaSet != null,
- "MediaSet is null. Path = %s", mMediaSetPath);
+ if (mMediaSet == null) {
+ Utils.fail("MediaSet is null. Path = %s", mMediaSetPath);
+ }
mSelectionManager.setSourceMediaSet(mMediaSet);
- mAlbumDataAdapter = new AlbumDataAdapter(mActivity, mMediaSet);
+ mAlbumDataAdapter = new AlbumDataLoader(mActivity, mMediaSet);
mAlbumDataAdapter.setLoadingListener(new MyLoadingListener());
mAlbumView.setModel(mAlbumDataAdapter);
}
private void showDetails() {
mShowDetails = true;
if (mDetailsHelper == null) {
- mHighlightDrawer = new HighlightDrawer(mActivity.getAndroidContext(),
- mSelectionManager);
mDetailsHelper = new DetailsHelper(mActivity, mRootPane, mDetailsSource);
mDetailsHelper.setCloseListener(new CloseListener() {
public void onClose() {
}
});
}
- mAlbumView.setSelectionDrawer(mHighlightDrawer);
mDetailsHelper.show();
}
private void hideDetails() {
mShowDetails = false;
mDetailsHelper.hide();
- mAlbumView.setSelectionDrawer(mGridDrawer);
- mAlbumView.invalidate();
+ mAlbumView.setHighlightItemPath(null);
+ mSlotView.invalidate();
}
@Override
menu.findItem(R.id.action_slideshow).setVisible(true);
}
- MenuItem groupBy = menu.findItem(R.id.action_group_by);
FilterUtils.setupMenuItems(actionBar, mMediaSetPath, true);
+ MenuItem groupBy = menu.findItem(R.id.action_group_by);
if (groupBy != null) {
groupBy.setVisible(mShowClusterMenu);
}
+ MenuItem switchCamera = menu.findItem(R.id.action_camera);
+ if (switchCamera != null) {
+ switchCamera.setVisible(
+ MediaSetUtils.isCameraSource(mMediaSetPath)
+ && GalleryUtils.isCameraAvailable(activity));
+ }
+
actionBar.setTitle(mMediaSet.getName());
}
actionBar.setSubtitle(null);
@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;
}
return true;
}
+ case R.id.action_camera: {
+ GalleryUtils.startCameraActivity((Activity) mActivity);
+ return true;
+ }
default:
return false;
}
// 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);
+ mSlotView.setCenterIndex(mFocusIndex);
break;
}
case REQUEST_PHOTO: {
if (data == null) return;
- mFocusIndex = data.getIntExtra(PhotoPage.KEY_INDEX_HINT, 0);
- mAlbumView.setCenterIndex(mFocusIndex);
- startTransition();
+ mFocusIndex = data.getIntExtra(PhotoPage.KEY_RETURN_INDEX_HINT, 0);
+ mSlotView.makeSlotVisible(mFocusIndex);
+ mSlotView.startRestoringAnimation(mFocusIndex);
break;
}
case REQUEST_DO_ANIMATION: {
- startTransition(null);
+ mSlotView.startRisingAnimation();
break;
}
}
((Activity) mActivity).runOnUiThread(new Runnable() {
@Override
public void run() {
- if (resultCode == MediaSet.SYNC_RESULT_SUCCESS) {
- mInitialSynced = true;
- }
- clearLoadingBit(BIT_LOADING_SYNC);
- if (resultCode == MediaSet.SYNC_RESULT_ERROR && mIsActive) {
- Toast.makeText((Context) mActivity, R.string.sync_album_error,
- Toast.LENGTH_LONG).show();
+ GLRoot root = mActivity.getGLRoot();
+ root.lockRenderThread();
+ try {
+ if (resultCode == MediaSet.SYNC_RESULT_SUCCESS) {
+ mInitialSynced = true;
+ }
+ clearLoadingBit(BIT_LOADING_SYNC);
+ if (resultCode == MediaSet.SYNC_RESULT_ERROR && mIsActive) {
+ Toast.makeText((Context) mActivity, R.string.sync_album_error,
+ Toast.LENGTH_LONG).show();
+ }
+ } finally {
+ root.unlockRenderThread();
}
}
});
public MediaDetails getDetails() {
MediaObject item = mAlbumDataAdapter.get(mIndex);
if (item != null) {
- mHighlightDrawer.setHighlightItem(item.getPath());
+ mAlbumView.setHighlightItemPath(item.getPath());
return item.getDetails();
} else {
return null;