Merge changes I1acef9fc,I53ddb3cd
* changes:
Make top level albums can be loaded concurrently.
Add log to debug loading time.
diff --git a/src/com/android/gallery3d/app/AbstractGalleryActivity.java b/src/com/android/gallery3d/app/AbstractGalleryActivity.java
index 03f522f..9a1d3d3 100644
--- a/src/com/android/gallery3d/app/AbstractGalleryActivity.java
+++ b/src/com/android/gallery3d/app/AbstractGalleryActivity.java
@@ -43,6 +43,7 @@
private static final String TAG = "AbstractGalleryActivity";
private GLRootView mGLRootView;
private StateManager mStateManager;
+ private GalleryActionBar mActionBar;
private AlertDialog mAlertDialog = null;
private BroadcastReceiver mMountReceiver = new BroadcastReceiver() {
@@ -192,7 +193,10 @@
@Override
public GalleryActionBar getGalleryActionBar() {
- return null;
+ if (mActionBar == null) {
+ mActionBar = new GalleryActionBar(this);
+ }
+ return mActionBar;
}
@Override
diff --git a/src/com/android/gallery3d/app/AlbumPage.java b/src/com/android/gallery3d/app/AlbumPage.java
index 411464e..818a2ff 100644
--- a/src/com/android/gallery3d/app/AlbumPage.java
+++ b/src/com/android/gallery3d/app/AlbumPage.java
@@ -19,6 +19,7 @@
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.Vibrator;
@@ -118,7 +119,7 @@
protected void onLayout(
boolean changed, int left, int top, int right, int bottom) {
- int slotViewTop = GalleryActionBar.getHeight((Activity) mActivity);
+ int slotViewTop = mActivity.getGalleryActionBar().getHeight();
int slotViewBottom = bottom - top;
int slotViewRight = right - left;
@@ -131,6 +132,7 @@
mAlbumView.layout(0, slotViewTop, slotViewRight, slotViewBottom);
GalleryUtils.setViewPointMatrix(mMatrix,
(right - left) / 2, (bottom - top) / 2, -mUserDistance);
+ // Reset position offset after the layout is changed.
PositionRepository.getInstance(mActivity).setOffset(
0, slotViewTop);
}
@@ -168,7 +170,7 @@
mAlbumView.invalidate();
}
- public void onSingleTapUp(int slotIndex) {
+ private void onSingleTapUp(int slotIndex) {
MediaItem item = mAlbumDataAdapter.get(slotIndex);
if (item == null) {
Log.w(TAG, "item not ready yet, ignore the click");
@@ -185,6 +187,8 @@
Bundle data = new Bundle();
mAlbumView.savePositions(PositionRepository.getInstance(mActivity));
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,
@@ -199,6 +203,16 @@
}
}
+ private Rect getSlotRect(int slotIndex) {
+ // Get slot rectangle relative to this root pane.
+ Rect offset = new Rect();
+ mRootPane.getBoundsOf(mAlbumView, offset);
+ Rect r = mAlbumView.getSlotRect(slotIndex);
+ r.offset(offset.left - mAlbumView.getScrollX(),
+ offset.top - mAlbumView.getScrollY());
+ return r;
+ }
+
private void onGetContent(final MediaItem item) {
DataManager dm = mActivity.getDataManager();
Activity activity = (Activity) mActivity;
@@ -315,6 +329,9 @@
super.onResume();
mIsActive = true;
setContentPane(mRootPane);
+ // Reset position offset for resuming.
+ PositionRepository.getInstance(mActivity).setOffset(
+ mAlbumView.bounds().left, mAlbumView.bounds().top);
Path path = mMediaSet.getPath();
boolean enableHomeButton = (mActivity.getStateManager().getStateCount() > 1) |
diff --git a/src/com/android/gallery3d/app/AlbumSetPage.java b/src/com/android/gallery3d/app/AlbumSetPage.java
index c52cd8c..d00c03c 100644
--- a/src/com/android/gallery3d/app/AlbumSetPage.java
+++ b/src/com/android/gallery3d/app/AlbumSetPage.java
@@ -79,6 +79,7 @@
private String mTitle;
private String mSubtitle;
private boolean mShowClusterMenu;
+ private GalleryActionBar mActionBar;
private int mSelectedAction;
private Vibrator mVibrator;
@@ -120,7 +121,7 @@
boolean changed, int left, int top, int right, int bottom) {
mEyePosition.resetPosition();
- int slotViewTop = GalleryActionBar.getHeight((Activity) mActivity);
+ int slotViewTop = mActionBar.getHeight();
int slotViewBottom = bottom - top;
int slotViewRight = right - left;
@@ -131,6 +132,7 @@
}
mAlbumSetView.layout(0, slotViewTop, slotViewRight, slotViewBottom);
+ // Reset position offset after the layout is changed.
PositionRepository.getInstance(mActivity).setOffset(
0, slotViewTop);
}
@@ -270,11 +272,9 @@
mEyePosition = new EyePosition(context, this);
mDetailsSource = new MyDetailsSource();
mVibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
- GalleryActionBar actionBar = mActivity.getGalleryActionBar();
- if (actionBar != null) {
- mSelectedAction = data.getInt(
- AlbumSetPage.KEY_SELECTED_CLUSTER_TYPE, FilterUtils.CLUSTER_BY_ALBUM);
- }
+ mActionBar = mActivity.getGalleryActionBar();
+ mSelectedAction = data.getInt(AlbumSetPage.KEY_SELECTED_CLUSTER_TYPE,
+ FilterUtils.CLUSTER_BY_ALBUM);
startTransition();
}
@@ -311,11 +311,10 @@
mAlbumSetView.pause();
mEyePosition.pause();
DetailsHelper.pause();
- GalleryActionBar actionBar = mActivity.getGalleryActionBar();
// Call disableClusterMenu to avoid receiving callback after paused.
// Don't hide menu here otherwise the list menu will disappear earlier than
// the action bar, which is janky and unwanted behavior.
- if (actionBar != null) actionBar.disableClusterMenu(false);
+ mActionBar.disableClusterMenu(false);
if (mSyncTask != null) {
mSyncTask.cancel();
mSyncTask = null;
@@ -329,6 +328,9 @@
super.onResume();
mIsActive = true;
setContentPane(mRootPane);
+ // Reset position offset for resuming.
+ PositionRepository.getInstance(mActivity).setOffset(
+ mAlbumSetView.bounds().left, mAlbumSetView.bounds().top);
// Set the reload bit here to prevent it exit this page in clearLoadingBit().
setLoadingBit(BIT_LOADING_RELOAD);
@@ -337,9 +339,8 @@
mAlbumSetView.resume();
mEyePosition.resume();
mActionModeHandler.resume();
- GalleryActionBar actionBar = mActivity.getGalleryActionBar();
- if (mShowClusterMenu && actionBar != null) {
- actionBar.enableClusterMenu(mSelectedAction, this);
+ if (mShowClusterMenu) {
+ mActionBar.enableClusterMenu(mSelectedAction, this);
}
if (!mInitialSynced) {
setLoadingBit(BIT_LOADING_SYNC);
@@ -399,7 +400,6 @@
@Override
protected boolean onCreateActionBar(Menu menu) {
Activity activity = (Activity) mActivity;
- GalleryActionBar actionBar = mActivity.getGalleryActionBar();
MenuInflater inflater = activity.getMenuInflater();
final boolean inAlbum = mActivity.getStateManager().hasStateClass(
@@ -415,10 +415,10 @@
? R.string.select_video
: R.string.select_item;
}
- actionBar.setTitle(id);
+ mActionBar.setTitle(id);
} else if (mGetAlbum) {
inflater.inflate(R.menu.pickup, menu);
- actionBar.setTitle(R.string.select_album);
+ mActionBar.setTitle(R.string.select_album);
} else {
mShowClusterMenu = !inAlbum;
inflater.inflate(R.menu.albumset, menu);
@@ -426,7 +426,7 @@
if (selectItem != null) {
boolean selectAlbums = !inAlbum &&
- actionBar.getClusterTypeAction() == FilterUtils.CLUSTER_BY_ALBUM;
+ mActionBar.getClusterTypeAction() == FilterUtils.CLUSTER_BY_ALBUM;
if (selectAlbums) {
selectItem.setTitle(R.string.select_album);
} else {
@@ -434,14 +434,14 @@
}
}
- FilterUtils.setupMenuItems(actionBar, mMediaSet.getPath(), false);
+ FilterUtils.setupMenuItems(mActionBar, mMediaSet.getPath(), false);
MenuItem switchCamera = menu.findItem(R.id.action_camera);
if (switchCamera != null) {
switchCamera.setVisible(GalleryUtils.isCameraAvailable(activity));
}
- actionBar.setTitle(mTitle);
- actionBar.setSubtitle(mSubtitle);
+ mActionBar.setTitle(mTitle);
+ mActionBar.setSubtitle(mSubtitle);
}
return true;
}
@@ -525,9 +525,8 @@
}
private String getSelectedString() {
- GalleryActionBar actionBar = mActivity.getGalleryActionBar();
int count = mSelectionManager.getSelectedCount();
- int action = actionBar.getClusterTypeAction();
+ int action = mActionBar.getClusterTypeAction();
int string = action == FilterUtils.CLUSTER_BY_ALBUM
? R.plurals.number_of_albums_selected
: R.plurals.number_of_groups_selected;
@@ -539,7 +538,7 @@
switch (mode) {
case SelectionManager.ENTER_SELECTION_MODE: {
- mActivity.getGalleryActionBar().disableClusterMenu(true);
+ mActionBar.disableClusterMenu(true);
mActionMode = mActionModeHandler.startActionMode();
mVibrator.vibrate(100);
break;
@@ -547,7 +546,7 @@
case SelectionManager.LEAVE_SELECTION_MODE: {
mActionMode.finish();
if (mShowClusterMenu) {
- mActivity.getGalleryActionBar().enableClusterMenu(mSelectedAction, this);
+ mActionBar.enableClusterMenu(mSelectedAction, this);
}
mRootPane.invalidate();
break;
diff --git a/src/com/android/gallery3d/app/CameraView.java b/src/com/android/gallery3d/app/CameraView.java
new file mode 100644
index 0000000..a6c2332
--- /dev/null
+++ b/src/com/android/gallery3d/app/CameraView.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2012 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.content.Context;
+import android.graphics.SurfaceTexture;
+import android.hardware.Camera;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.TextureView;
+import android.view.View;
+
+import java.io.IOException;
+
+// This is a sample View which demos the usage of ScreenNailBridge. It
+// is not intended for production use.
+public class CameraView extends TextureView implements
+ TextureView.SurfaceTextureListener, ScreenNailBridge.Listener {
+ private static final String TAG = "CameraView";
+ private static final int PREVIEW_WIDTH = 960;
+ private static final int PREVIEW_HEIGHT = 720;
+ private Camera mCamera;
+ private ScreenNailBridge mScreenNailBridge;
+
+ public CameraView(Context context) {
+ super(context);
+ init();
+ }
+
+ public CameraView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init();
+ }
+
+ private void init() {
+ setVisibility(View.INVISIBLE);
+ setSurfaceTextureListener(this);
+ }
+
+ public void setScreenNailBridge(ScreenNailBridge s) {
+ mScreenNailBridge = s;
+ }
+
+ @Override
+ public void onMeasure(int widthSpec, int heightSpec) {
+ int width = getDefaultSize(PREVIEW_WIDTH, widthSpec);
+ int height = getDefaultSize(PREVIEW_HEIGHT, heightSpec);
+ // Keep aspect ratio
+ if (width * PREVIEW_HEIGHT > PREVIEW_WIDTH * height) {
+ width = PREVIEW_WIDTH * height / PREVIEW_HEIGHT;
+ } else {
+ height = PREVIEW_HEIGHT * width / PREVIEW_WIDTH;
+ }
+ setMeasuredDimension(width, height);
+ }
+
+ @Override
+ public void onSizeChanged(int w, int h, int oldw, int oldh) {
+ mScreenNailBridge.setSize(w, h);
+ }
+
+ @Override
+ public void updateView(boolean visible, int x, int y, int w, int h) {
+ if (!visible) {
+ setVisibility(View.INVISIBLE);
+ } else {
+ setVisibility(View.VISIBLE);
+ setTranslationX(x);
+ setTranslationY(y);
+ }
+ }
+
+ @Override
+ public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
+ try {
+ mCamera = Camera.open();
+
+ Camera.Parameters param = mCamera.getParameters();
+ param.setPreviewSize(PREVIEW_WIDTH, PREVIEW_HEIGHT);
+ mCamera.setParameters(param);
+
+ mCamera.setPreviewTexture(surface);
+ mCamera.startPreview();
+ } catch (Throwable ex) {
+ Log.e(TAG, "failed to open camera", ex);
+ }
+ }
+
+ @Override
+ public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
+ mCamera.stopPreview();
+ mCamera.release();
+ return true;
+ }
+
+ @Override
+ public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
+ }
+
+ @Override
+ public void onSurfaceTextureUpdated(SurfaceTexture surface) {
+ }
+}
diff --git a/src/com/android/gallery3d/app/Gallery.java b/src/com/android/gallery3d/app/Gallery.java
index cd93c45..e3937bc 100644
--- a/src/com/android/gallery3d/app/Gallery.java
+++ b/src/com/android/gallery3d/app/Gallery.java
@@ -52,7 +52,6 @@
public static final String KEY_MEDIA_TYPES = "mediaTypes";
private static final String TAG = "Gallery";
- private GalleryActionBar mActionBar;
private Dialog mVersionCheckDialog;
@Override
@@ -63,7 +62,6 @@
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
setContentView(R.layout.main);
- mActionBar = new GalleryActionBar(this);
if (savedInstanceState != null) {
getStateManager().restoreFromState(savedInstanceState);
@@ -276,11 +274,6 @@
}
@Override
- public GalleryActionBar getGalleryActionBar() {
- return mActionBar;
- }
-
- @Override
public void onCancel(DialogInterface dialog) {
if (dialog == mVersionCheckDialog) {
mVersionCheckDialog = null;
diff --git a/src/com/android/gallery3d/app/GalleryActionBar.java b/src/com/android/gallery3d/app/GalleryActionBar.java
index 35cb8b4..c99cd60 100644
--- a/src/com/android/gallery3d/app/GalleryActionBar.java
+++ b/src/com/android/gallery3d/app/GalleryActionBar.java
@@ -19,6 +19,7 @@
import android.app.ActionBar;
import android.app.Activity;
import android.app.AlertDialog;
+import android.app.ActionBar.OnMenuVisibilityListener;
import android.content.Context;
import android.content.DialogInterface;
import android.view.LayoutInflater;
@@ -37,6 +38,16 @@
public class GalleryActionBar implements ActionBar.OnNavigationListener {
private static final String TAG = "GalleryActionBar";
+ private ClusterRunner mClusterRunner;
+ private CharSequence[] mTitles;
+ private ArrayList<Integer> mActions;
+ private Context mContext;
+ private LayoutInflater mInflater;
+ private GalleryActivity mActivity;
+ private ActionBar mActionBar;
+ private int mCurrentIndex;
+ private ClusterAdapter mAdapter = new ClusterAdapter();
+
public interface ClusterRunner {
public void doCluster(int id);
}
@@ -103,15 +114,23 @@
}
}
- private ClusterRunner mClusterRunner;
- private CharSequence[] mTitles;
- private ArrayList<Integer> mActions;
- private Context mContext;
- private LayoutInflater mInflater;
- private GalleryActivity mActivity;
- private ActionBar mActionBar;
- private int mCurrentIndex;
- private ClusterAdapter mAdapter = new ClusterAdapter();
+ public static String getClusterByTypeString(Context context, int type) {
+ for (ActionItem item : sClusterItems) {
+ if (item.action == type) {
+ return context.getString(item.clusterBy);
+ }
+ }
+ return null;
+ }
+
+ public static ShareActionProvider initializeShareActionProvider(Menu menu) {
+ MenuItem item = menu.findItem(R.id.action_share);
+ ShareActionProvider shareActionProvider = null;
+ if (item != null) {
+ shareActionProvider = (ShareActionProvider) item.getActionProvider();
+ }
+ return shareActionProvider;
+ }
public GalleryActionBar(GalleryActivity activity) {
mActionBar = ((Activity) activity).getActionBar();
@@ -121,11 +140,6 @@
mCurrentIndex = 0;
}
- public static int getHeight(Activity activity) {
- ActionBar actionBar = activity.getActionBar();
- return actionBar != null ? actionBar.getHeight() : 0;
- }
-
private void createDialogData() {
ArrayList<CharSequence> titles = new ArrayList<CharSequence>();
mActions = new ArrayList<Integer>();
@@ -139,6 +153,10 @@
titles.toArray(mTitles);
}
+ public int getHeight() {
+ return mActionBar != null ? mActionBar.getHeight() : 0;
+ }
+
public void setClusterItemEnabled(int id, boolean enabled) {
for (ActionItem item : sClusterItems) {
if (item.action == id) {
@@ -161,41 +179,26 @@
return sClusterItems[mCurrentIndex].action;
}
- public static String getClusterByTypeString(Context context, int type) {
- for (ActionItem item : sClusterItems) {
- if (item.action == type) {
- return context.getString(item.clusterBy);
- }
- }
- return null;
- }
-
- public static ShareActionProvider initializeShareActionProvider(Menu menu) {
- MenuItem item = menu.findItem(R.id.action_share);
- ShareActionProvider shareActionProvider = null;
- if (item != null) {
- shareActionProvider = (ShareActionProvider) item.getActionProvider();
- }
- return shareActionProvider;
- }
-
public void enableClusterMenu(int action, ClusterRunner runner) {
- Log.v(TAG, "showClusterMenu: runner=" + runner);
- // Don't set cluster runner until action bar is ready.
- mClusterRunner = null;
- mActionBar.setListNavigationCallbacks(mAdapter, this);
- mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
- setSelectedAction(action);
- mClusterRunner = runner;
+ if (mActionBar != null) {
+ // Don't set cluster runner until action bar is ready.
+ mClusterRunner = null;
+ mActionBar.setListNavigationCallbacks(mAdapter, this);
+ mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
+ setSelectedAction(action);
+ mClusterRunner = runner;
+ }
}
// The only use case not to hideMenu in this method is to ensure
// all elements disappear at the same time when exiting gallery.
// hideMenu should always be true in all other cases.
public void disableClusterMenu(boolean hideMenu) {
- mClusterRunner = null;
- if (hideMenu) {
- mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
+ if (mActionBar != null) {
+ mClusterRunner = null;
+ if (hideMenu) {
+ mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
+ }
}
}
@@ -214,8 +217,7 @@
if (mActionBar != null) {
int options = (displayHomeAsUp ? ActionBar.DISPLAY_HOME_AS_UP : 0) |
(showTitle ? ActionBar.DISPLAY_SHOW_TITLE : 0);
- mActionBar.setDisplayOptions(
- options,
+ mActionBar.setDisplayOptions(options,
ActionBar.DISPLAY_HOME_AS_UP | ActionBar.DISPLAY_SHOW_TITLE);
mActionBar.setHomeButtonEnabled(displayHomeAsUp);
}
@@ -233,7 +235,25 @@
if (mActionBar != null) mActionBar.setSubtitle(title);
}
+ public void show() {
+ if (mActionBar != null) mActionBar.show();
+ }
+
+ public void hide() {
+ if (mActionBar != null) mActionBar.hide();
+ }
+
+ public void addOnMenuVisibilityListener(OnMenuVisibilityListener listener) {
+ if (mActionBar != null) mActionBar.addOnMenuVisibilityListener(listener);
+ }
+
+ public void removeOnMenuVisibilityListener(OnMenuVisibilityListener listener) {
+ if (mActionBar != null) mActionBar.removeOnMenuVisibilityListener(listener);
+ }
+
public boolean setSelectedAction(int type) {
+ if (mActionBar == null) return false;
+
for (int i = 0, n = sClusterItems.length; i < n; i++) {
ActionItem item = sClusterItems[i];
if (item.action == type) {
diff --git a/src/com/android/gallery3d/app/ManageCachePage.java b/src/com/android/gallery3d/app/ManageCachePage.java
index 4134e32..124eb7bf 100644
--- a/src/com/android/gallery3d/app/ManageCachePage.java
+++ b/src/com/android/gallery3d/app/ManageCachePage.java
@@ -112,7 +112,7 @@
mEyePosition.resetPosition();
Activity activity = (Activity) mActivity;
- int slotViewTop = GalleryActionBar.getHeight(activity);
+ int slotViewTop = mActivity.getGalleryActionBar().getHeight();
int slotViewBottom = bottom - top;
View footer = activity.findViewById(R.id.footer);
diff --git a/src/com/android/gallery3d/app/PhotoDataAdapter.java b/src/com/android/gallery3d/app/PhotoDataAdapter.java
index 0b544b9..82225d9 100644
--- a/src/com/android/gallery3d/app/PhotoDataAdapter.java
+++ b/src/com/android/gallery3d/app/PhotoDataAdapter.java
@@ -29,8 +29,9 @@
import com.android.gallery3d.data.MediaObject;
import com.android.gallery3d.data.MediaSet;
import com.android.gallery3d.data.Path;
+import com.android.gallery3d.ui.BitmapScreenNail;
import com.android.gallery3d.ui.PhotoView;
-import com.android.gallery3d.ui.PhotoView.ImageData;
+import com.android.gallery3d.ui.ScreenNail;
import com.android.gallery3d.ui.SynchronizedHandler;
import com.android.gallery3d.ui.TileImageViewAdapter;
import com.android.gallery3d.util.Future;
@@ -215,20 +216,22 @@
mDataListener = listener;
}
- private void updateScreenNail(long version, Future<Bitmap> future) {
+ private void updateScreenNail(long version, Future<ScreenNail> future) {
ImageEntry entry = mImageCache.get(version);
+ ScreenNail screenNail = future.get();
+
if (entry == null || entry.screenNailTask != future) {
- Bitmap screenNail = future.get();
if (screenNail != null) screenNail.recycle();
return;
}
entry.screenNailTask = null;
- entry.screenNail = future.get();
+ entry.screenNail = screenNail;
- if (entry.screenNail == null) {
+ if (screenNail == null) {
entry.failToLoad = true;
}
+
if (mDataListener != null) {
mDataListener.onPhotoAvailable(version, false);
}
@@ -291,24 +294,19 @@
mTileProvider.clear();
}
- private ImageData getImage(int index) {
+ private ScreenNail getImage(int index) {
if (index < 0 || index >= mSize || !mIsActive) return null;
Utils.assertTrue(index >= mActiveStart && index < mActiveEnd);
ImageEntry entry = mImageCache.get(getVersion(index));
- Bitmap screennail = entry == null ? null : entry.screenNail;
- if (screennail != null) {
- return new ImageData(screennail, entry.rotation);
- } else {
- return new ImageData(null, 0);
- }
+ return entry == null ? null : entry.screenNail;
}
- public ImageData getPreviousImage() {
+ public ScreenNail getPrevScreenNail() {
return getImage(mCurrentIndex - 1);
}
- public ImageData getNextImage() {
+ public ScreenNail getNextScreenNail() {
return getImage(mCurrentIndex + 1);
}
@@ -343,8 +341,8 @@
updateCurrentIndex(index);
}
- public Bitmap getBackupImage() {
- return mTileProvider.getBackupImage();
+ public ScreenNail getScreenNail() {
+ return mTileProvider.getScreenNail();
}
public int getImageHeight() {
@@ -409,17 +407,17 @@
}
private void updateTileProvider(ImageEntry entry) {
- Bitmap screenNail = entry.screenNail;
+ ScreenNail screenNail = entry.screenNail;
BitmapRegionDecoder fullImage = entry.fullImage;
if (screenNail != null) {
if (fullImage != null) {
- mTileProvider.setBackupImage(screenNail,
+ mTileProvider.setScreenNail(screenNail,
fullImage.getWidth(), fullImage.getHeight());
mTileProvider.setRegionDecoder(fullImage);
} else {
int width = screenNail.getWidth();
int height = screenNail.getHeight();
- mTileProvider.setBackupImage(screenNail, width, height);
+ mTileProvider.setScreenNail(screenNail, width, height);
}
} else {
mTileProvider.clear();
@@ -489,7 +487,7 @@
}
}
- private static class ScreenNailJob implements Job<Bitmap> {
+ private static class ScreenNailJob implements Job<ScreenNail> {
private MediaItem mItem;
public ScreenNailJob(MediaItem item) {
@@ -497,14 +495,19 @@
}
@Override
- public Bitmap run(JobContext jc) {
+ public ScreenNail run(JobContext jc) {
+ // We try to get a ScreenNail first, if it fails, we fallback to get
+ // a Bitmap and then wrap it in a BitmapScreenNail instead.
+ ScreenNail s = mItem.getScreenNail();
+ if (s != null) return s;
+
Bitmap bitmap = mItem.requestImage(MediaItem.TYPE_THUMBNAIL).run(jc);
if (jc.isCancelled()) return null;
if (bitmap != null) {
bitmap = BitmapUtils.rotateBitmap(bitmap,
mItem.getRotation() - mItem.getFullImageRotation(), true);
}
- return bitmap;
+ return new BitmapScreenNail(bitmap, mItem.getFullImageRotation());
}
}
@@ -604,16 +607,16 @@
}
private class ScreenNailListener
- implements Runnable, FutureListener<Bitmap> {
+ implements Runnable, FutureListener<ScreenNail> {
private final long mVersion;
- private Future<Bitmap> mFuture;
+ private Future<ScreenNail> mFuture;
public ScreenNailListener(long version) {
mVersion = version;
}
@Override
- public void onFutureDone(Future<Bitmap> future) {
+ public void onFutureDone(Future<ScreenNail> future) {
mFuture = future;
mMainHandler.sendMessage(
mMainHandler.obtainMessage(MSG_RUN_OBJECT, this));
@@ -629,8 +632,8 @@
public int requestedBits = 0;
public int rotation;
public BitmapRegionDecoder fullImage;
- public Bitmap screenNail;
- public Future<Bitmap> screenNailTask;
+ public ScreenNail screenNail;
+ public Future<ScreenNail> screenNailTask;
public Future<BitmapRegionDecoder> fullImageTask;
public boolean failToLoad = false;
}
diff --git a/src/com/android/gallery3d/app/PhotoPage.java b/src/com/android/gallery3d/app/PhotoPage.java
index 8040a2f..7daf5df 100644
--- a/src/com/android/gallery3d/app/PhotoPage.java
+++ b/src/com/android/gallery3d/app/PhotoPage.java
@@ -16,13 +16,13 @@
package com.android.gallery3d.app;
-import android.app.ActionBar;
import android.app.ActionBar.OnMenuVisibilityListener;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
+import android.graphics.Rect;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
@@ -31,6 +31,7 @@
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
+import android.view.ViewGroup;
import android.view.View.MeasureSpec;
import android.view.WindowManager;
import android.widget.ShareActionProvider;
@@ -44,6 +45,7 @@
import com.android.gallery3d.data.MediaSet;
import com.android.gallery3d.data.MtpDevice;
import com.android.gallery3d.data.Path;
+import com.android.gallery3d.data.SnailSource;
import com.android.gallery3d.picasasource.PicasaSource;
import com.android.gallery3d.ui.DetailsHelper;
import com.android.gallery3d.ui.DetailsHelper.CloseListener;
@@ -77,6 +79,7 @@
public static final String KEY_MEDIA_SET_PATH = "media-set-path";
public static final String KEY_MEDIA_ITEM_PATH = "media-item-path";
public static final String KEY_INDEX_HINT = "index-hint";
+ public static final String KEY_OPEN_ANIMATION_RECT = "open-animation-rect";
private GalleryApp mApplication;
private SelectionManager mSelectionManager;
@@ -97,7 +100,7 @@
private int mCurrentIndex = 0;
private Handler mHandler;
private boolean mShowBars = true;
- private ActionBar mActionBar;
+ private GalleryActionBar mActionBar;
private MyMenuVisibilityListener mMenuVisibilityListener;
private boolean mIsMenuVisible;
private boolean mIsInteracting;
@@ -107,6 +110,11 @@
private ShareActionProvider mShareActionProvider;
private String mSetPathString;
+ // This is for testing only. It should be removed once we have the real
+ // Camera view.
+ private CameraView mCameraView;
+ private ScreenNailBridge mScreenNail;
+
public static interface Model extends PhotoView.Model {
public void resume();
public void pause();
@@ -134,6 +142,7 @@
protected void onLayout(
boolean changed, int left, int top, int right, int bottom) {
mPhotoView.layout(0, 0, right - left, bottom - top);
+ // Reset position offset after the layout is changed.
PositionRepository.getInstance(mActivity).setOffset(0, 0);
int filmStripHeight = 0;
if (mFilmStripView != null) {
@@ -145,8 +154,7 @@
right - left, bottom - top);
}
if (mShowDetails) {
- mDetailsHelper.layout(left, GalleryActionBar.getHeight((Activity) mActivity),
- right, bottom);
+ mDetailsHelper.layout(left, mActionBar.getHeight(), right, bottom);
}
}
};
@@ -169,7 +177,7 @@
@Override
public void onCreate(Bundle data, Bundle restoreState) {
- mActionBar = ((Activity) mActivity).getActionBar();
+ mActionBar = mActivity.getGalleryActionBar();
mSelectionManager = new SelectionManager(mActivity, false);
mMenuExecutor = new MenuExecutor(mActivity, mSelectionManager);
@@ -182,6 +190,14 @@
Path itemPath = Path.fromString(data.getString(KEY_MEDIA_ITEM_PATH));
if (mSetPathString != null) {
+ // Uncomment the block below to test camera screennail.
+ /*
+ Path cameraScreenNailSetPath = addCameraScreenNail();
+
+ // Combine the original MediaSet with the one for camera ScreenNail.
+ mSetPathString = "/combo/item/{" + cameraScreenNailSetPath + "," +
+ mSetPathString + "}";
+ */
mMediaSet = mActivity.getDataManager().getMediaSet(mSetPathString);
mCurrentIndex = data.getInt(KEY_INDEX_HINT, 0);
mMediaSet = (MediaSet)
@@ -257,8 +273,38 @@
}
};
- // start the opening animation
- mPhotoView.setOpenedItem(itemPath);
+ // start the opening animation only if it's not restored.
+ if (restoreState == null) {
+ mPhotoView.setOpenAnimationRect((Rect) data.getParcelable(KEY_OPEN_ANIMATION_RECT));
+ }
+ }
+
+ // We create a Camera View and a ScreenNail. The two work together
+ // to present the view together with other pictures. Returns the
+ // Path of the MediaItem hosting the ScreenNail.
+ private Path addCameraScreenNail() {
+ // Create a camera view and add it to the root.
+ Activity activity = (Activity) mActivity;
+ mCameraView = new CameraView(activity);
+ ViewGroup galleryRoot = (ViewGroup) activity.findViewById(R.id.gallery_root);
+ galleryRoot.addView(mCameraView);
+
+ // Create a ScreenNail and register it.
+ mScreenNail = new ScreenNailBridge(mCameraView);
+ mCameraView.setScreenNailBridge(mScreenNail);
+ return SnailSource.registerScreenNail(mScreenNail);
+ }
+
+ private void removeCameraScreenNail() {
+ if (mCameraView == null) return;
+
+ // Remove the camera view.
+ ((ViewGroup) mCameraView.getParent()).removeView(mCameraView);
+ mCameraView = null;
+
+ // Unregister the ScreenNail.
+ SnailSource.unregisterScreenNail(mScreenNail);
+ mScreenNail = null;
}
private void updateShareURI(Path path) {
@@ -298,7 +344,9 @@
mPhotoView.showVideoPlayIcon(
photo.getMediaType() == MediaObject.MEDIA_TYPE_VIDEO);
- updateShareURI(photo.getPath());
+ if ((photo.getSupportedOperations() & MediaItem.SUPPORT_SHARE) != 0) {
+ updateShareURI(photo.getPath());
+ }
}
private void updateMenuOperations() {
@@ -622,6 +670,10 @@
super.onResume();
mIsActive = true;
setContentPane(mRootPane);
+ // Reset position offset for resuming.
+ PositionRepository.getInstance(mActivity).setOffset(
+ mPhotoView.bounds().left, mPhotoView.bounds().top);
+
mModel.resume();
mPhotoView.resume();
if (mFilmStripView != null) {
@@ -630,12 +682,17 @@
if (mMenuVisibilityListener == null) {
mMenuVisibilityListener = new MyMenuVisibilityListener();
}
- mActivity.getGalleryActionBar().setDisplayOptions(mSetPathString != null, true);
-
+ mActionBar.setDisplayOptions(mSetPathString != null, true);
mActionBar.addOnMenuVisibilityListener(mMenuVisibilityListener);
onUserInteraction();
}
+ @Override
+ protected void onDestroy() {
+ removeCameraScreenNail();
+ super.onDestroy();
+ }
+
private class MyDetailsSource implements DetailsSource {
private int mIndex;
diff --git a/src/com/android/gallery3d/app/PickerActivity.java b/src/com/android/gallery3d/app/PickerActivity.java
index 855a0ce..d63e237 100644
--- a/src/com/android/gallery3d/app/PickerActivity.java
+++ b/src/com/android/gallery3d/app/PickerActivity.java
@@ -33,8 +33,6 @@
public static final String KEY_ALBUM_PATH = "album-path";
- private GalleryActionBar mActionBar;
-
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -46,7 +44,6 @@
if (!isDialog) {
requestWindowFeature(Window.FEATURE_ACTION_BAR);
requestWindowFeature(Window.FEATURE_ACTION_BAR_OVERLAY);
- mActionBar = new GalleryActionBar(this);
}
setContentView(R.layout.dialog_picker);
@@ -96,9 +93,4 @@
public void onClick(View v) {
if (v.getId() == R.id.cancel) finish();
}
-
- @Override
- public GalleryActionBar getGalleryActionBar() {
- return mActionBar;
- }
}
diff --git a/src/com/android/gallery3d/app/ScreenNailBridge.java b/src/com/android/gallery3d/app/ScreenNailBridge.java
new file mode 100644
index 0000000..9da197d
--- /dev/null
+++ b/src/com/android/gallery3d/app/ScreenNailBridge.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2012 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.graphics.RectF;
+import android.os.Handler;
+import android.util.Log;
+
+import com.android.gallery3d.ui.GLCanvas;
+import com.android.gallery3d.ui.ScreenNail;
+
+// This is a ScreenNail whose actually display is done by an foreign component.
+// The foreign component tells the ScreenNail its size by setSize(). The
+// ScreenNail tells the foreign component the position to display by
+// updateView().
+class ScreenNailBridge implements ScreenNail {
+ private static final String TAG = "ScreenNailBridge";
+ private int mWidth, mHeight;
+ private boolean mVisible = false;
+ private int mDrawX, mDrawY, mDrawWidth, mDrawHeight;
+ private Listener mListener;
+ private Handler mMainHandler;
+
+ public interface Listener {
+ // This is called from the main thread.
+ void updateView(boolean visible, int x, int y, int width, int height);
+ };
+
+ // The constructor should be called from the main thread.
+ public ScreenNailBridge(Listener listener) {
+ mListener = listener;
+ mMainHandler = new Handler();
+ }
+
+ // This can be called from any thread. (We expect it to be called from the
+ // main thread).
+ public synchronized void setSize(int w, int h) {
+ mWidth = w;
+ mHeight = h;
+ }
+
+ // This can be called from any thread. (We expect it to be called from GL
+ // thread)
+ @Override
+ public synchronized int getWidth() {
+ return mWidth;
+ }
+
+ // This can be called from any thread. (We expect it to be called from GL
+ // thread)
+ @Override
+ public synchronized int getHeight() {
+ return mHeight;
+ }
+
+ @Override
+ public int getRotation() {
+ return 0;
+ }
+
+ // This is run in the main thread.
+ private Runnable mUpdateViewRunnable = new Runnable() {
+ public void run() {
+ boolean v;
+ int x, y, width, height;
+ synchronized (ScreenNailBridge.this) {
+ v = mVisible;
+ x = mDrawX;
+ y = mDrawY;
+ width = mDrawWidth;
+ height = mDrawHeight;
+ }
+ mListener.updateView(v, x, y, width, height);
+ }
+ };
+
+ @Override
+ public synchronized void draw(GLCanvas canvas, int x, int y, int width, int height) {
+ if (mVisible && mDrawX == x && mDrawY == y && mDrawWidth == width &&
+ mDrawHeight == height) {
+ return;
+ }
+ mVisible = true;
+ mDrawX = x;
+ mDrawY = y;
+ mDrawWidth = width;
+ mDrawHeight = height;
+ mMainHandler.post(mUpdateViewRunnable);
+ }
+
+ @Override
+ public synchronized void disableDraw() {
+ if (!mVisible) return;
+ mVisible = false;
+ mMainHandler.post(mUpdateViewRunnable);
+ }
+
+ @Override
+ public void recycle() {
+ // Make sure we will not draw anymore.
+ disableDraw();
+ }
+
+ @Override
+ public void draw(GLCanvas canvas, RectF source, RectF dest) {
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/src/com/android/gallery3d/app/SinglePhotoDataAdapter.java b/src/com/android/gallery3d/app/SinglePhotoDataAdapter.java
index adad8fd..66e7c20 100644
--- a/src/com/android/gallery3d/app/SinglePhotoDataAdapter.java
+++ b/src/com/android/gallery3d/app/SinglePhotoDataAdapter.java
@@ -28,7 +28,7 @@
import com.android.gallery3d.data.MediaItem;
import com.android.gallery3d.data.Path;
import com.android.gallery3d.ui.PhotoView;
-import com.android.gallery3d.ui.PhotoView.ImageData;
+import com.android.gallery3d.ui.ScreenNail;
import com.android.gallery3d.ui.SynchronizedHandler;
import com.android.gallery3d.ui.TileImageViewAdapter;
import com.android.gallery3d.util.Future;
@@ -115,7 +115,7 @@
private void onDecodeLargeComplete(ImageBundle bundle) {
try {
- setBackupImage(bundle.backupImage,
+ setScreenNail(bundle.backupImage,
bundle.decoder.getWidth(), bundle.decoder.getHeight());
setRegionDecoder(bundle.decoder);
mPhotoView.notifyImageInvalidated(0);
@@ -128,7 +128,7 @@
try {
Bitmap backup = future.get();
if (backup == null) return;
- setBackupImage(backup, backup.getWidth(), backup.getHeight());
+ setScreenNail(backup, backup.getWidth(), backup.getHeight());
mPhotoView.notifyOnNewImage();
mPhotoView.notifyImageInvalidated(0); // the current image
} catch (Throwable t) {
@@ -158,11 +158,11 @@
}
}
- public ImageData getNextImage() {
+ public ScreenNail getNextScreenNail() {
return null;
}
- public ImageData getPreviousImage() {
+ public ScreenNail getPrevScreenNail() {
return null;
}
diff --git a/src/com/android/gallery3d/data/DataManager.java b/src/com/android/gallery3d/data/DataManager.java
index e6e97e9..1da3b76 100644
--- a/src/com/android/gallery3d/data/DataManager.java
+++ b/src/com/android/gallery3d/data/DataManager.java
@@ -115,6 +115,7 @@
addSource(new ClusterSource(mApplication));
addSource(new FilterSource(mApplication));
addSource(new UriSource(mApplication));
+ addSource(new SnailSource(mApplication));
if (mActiveCount > 0) {
for (MediaSource source : mSourceMap.values()) {
diff --git a/src/com/android/gallery3d/data/MediaItem.java b/src/com/android/gallery3d/data/MediaItem.java
index b682c2d..b2632f1 100644
--- a/src/com/android/gallery3d/data/MediaItem.java
+++ b/src/com/android/gallery3d/data/MediaItem.java
@@ -20,6 +20,7 @@
import android.graphics.BitmapRegionDecoder;
import com.android.gallery3d.util.ThreadPool.Job;
+import com.android.gallery3d.ui.ScreenNail;
// MediaItem represents an image or a video item.
public abstract class MediaItem extends MediaObject {
@@ -90,6 +91,12 @@
public abstract int getWidth();
public abstract int getHeight();
+ // This is an alternative for requestImage() in PhotoPage. If this
+ // is implemented, you don't need to implement requestImage().
+ public ScreenNail getScreenNail() {
+ return null;
+ }
+
public static int getTargetSize(int type) {
switch (type) {
case TYPE_THUMBNAIL:
diff --git a/src/com/android/gallery3d/data/SnailAlbum.java b/src/com/android/gallery3d/data/SnailAlbum.java
new file mode 100644
index 0000000..39467bb
--- /dev/null
+++ b/src/com/android/gallery3d/data/SnailAlbum.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2012 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.data;
+
+import java.util.ArrayList;
+
+// This is a simple MediaSet which contains only one MediaItem -- a SnailItem.
+public class SnailAlbum extends MediaSet {
+
+ private MediaItem mItem;
+
+ public SnailAlbum(Path path, MediaItem item) {
+ super(path, nextVersionNumber());
+ mItem = item;
+ }
+
+ @Override
+ public int getMediaItemCount() {
+ return 1;
+ }
+
+ @Override
+ public ArrayList<MediaItem> getMediaItem(int start, int count) {
+ ArrayList<MediaItem> result = new ArrayList<MediaItem>();
+
+ // If [start, start+count) contains the index 0, return the item.
+ if (start <= 0 && start + count > 0) {
+ result.add(mItem);
+ }
+
+ return result;
+ }
+
+ @Override
+ public boolean isLeafAlbum() {
+ return true;
+ }
+
+ @Override
+ public String getName() {
+ return "SnailAlbum";
+ }
+
+ @Override
+ public long reload() {
+ return mDataVersion;
+ }
+}
diff --git a/src/com/android/gallery3d/data/SnailItem.java b/src/com/android/gallery3d/data/SnailItem.java
new file mode 100644
index 0000000..2836a19
--- /dev/null
+++ b/src/com/android/gallery3d/data/SnailItem.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2012 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.data;
+
+import android.graphics.Bitmap;
+import android.graphics.BitmapRegionDecoder;
+
+import com.android.gallery3d.ui.ScreenNail;
+import com.android.gallery3d.util.ThreadPool.Job;
+import com.android.gallery3d.util.ThreadPool.JobContext;
+
+// SnailItem is a MediaItem which can provide a ScreenNail. This is
+// used so we can show an foreign component (like an
+// android.view.View) instead of a Bitmap.
+public class SnailItem extends MediaItem {
+ private ScreenNail mScreenNail;
+
+ public SnailItem(Path path, ScreenNail screenNail) {
+ super(path, nextVersionNumber());
+ mScreenNail = screenNail;
+ }
+
+ @Override
+ public Job<Bitmap> requestImage(int type) {
+ // nothing to return
+ return new Job<Bitmap>() {
+ public Bitmap run(JobContext jc) {
+ return null;
+ }
+ };
+ }
+
+ @Override
+ public Job<BitmapRegionDecoder> requestLargeImage() {
+ // nothing to return
+ return new Job<BitmapRegionDecoder>() {
+ public BitmapRegionDecoder run(JobContext jc) {
+ return null;
+ }
+ };
+ }
+
+ // We do not provide requestImage or requestLargeImage, instead we
+ // provide a ScreenNail.
+ @Override
+ public ScreenNail getScreenNail() {
+ return mScreenNail;
+ }
+
+ @Override
+ public String getMimeType() {
+ return "";
+ }
+
+ // Returns width and height of the media item.
+ // Returns 0, 0 if the information is not available.
+ @Override
+ public int getWidth() {
+ return 0;
+ }
+
+ @Override
+ public int getHeight() {
+ return 0;
+ }
+}
diff --git a/src/com/android/gallery3d/data/SnailSource.java b/src/com/android/gallery3d/data/SnailSource.java
new file mode 100644
index 0000000..17b899d
--- /dev/null
+++ b/src/com/android/gallery3d/data/SnailSource.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2012 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.data;
+
+import android.util.SparseArray;
+import com.android.gallery3d.app.GalleryApp;
+import com.android.gallery3d.ui.ScreenNail;
+
+public class SnailSource extends MediaSource {
+ private static final String TAG = "SnailSource";
+ private static final int SNAIL_ALBUM = 0;
+ private static final int SNAIL_ITEM = 1;
+
+ private GalleryApp mApplication;
+ private PathMatcher mMatcher;
+ private static int sNextId;
+ private static SparseArray<ScreenNail> sRegistry = new SparseArray<ScreenNail>();
+
+ public SnailSource(GalleryApp application) {
+ super("snail");
+ mApplication = application;
+ mMatcher = new PathMatcher();
+ mMatcher.add("/snail/set/*", SNAIL_ALBUM);
+ mMatcher.add("/snail/item/*", SNAIL_ITEM);
+ }
+
+ // The only path we accept is "/snail/set/id" and "/snail/item/id"
+ @Override
+ public MediaObject createMediaObject(Path path) {
+ DataManager dataManager = mApplication.getDataManager();
+ switch (mMatcher.match(path)) {
+ case SNAIL_ALBUM:
+ String itemPath = "/snail/item/" + mMatcher.getVar(0);
+ MediaItem item =
+ (MediaItem) dataManager.getMediaObject(itemPath);
+ return new SnailAlbum(path, item);
+ case SNAIL_ITEM: {
+ int id = mMatcher.getIntVar(0);
+ return new SnailItem(path, lookupScreenNail(id));
+ }
+ }
+ return null;
+ }
+
+ // Register a ScreenNail. Returns the Path of the MediaSet
+ // containing the MediaItem associated with the ScreenNail.
+ public static synchronized Path registerScreenNail(ScreenNail s) {
+ int id = sNextId++;
+ sRegistry.put(id, s);
+ return Path.fromString("/snail/set").getChild(id);
+ }
+
+ public static synchronized void unregisterScreenNail(ScreenNail s) {
+ int index = sRegistry.indexOfValue(s);
+ sRegistry.removeAt(index);
+ }
+
+ private static synchronized ScreenNail lookupScreenNail(int id) {
+ return sRegistry.get(id);
+ }
+}
diff --git a/src/com/android/gallery3d/ui/BitmapScreenNail.java b/src/com/android/gallery3d/ui/BitmapScreenNail.java
new file mode 100644
index 0000000..117a9ac
--- /dev/null
+++ b/src/com/android/gallery3d/ui/BitmapScreenNail.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2012 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.ui;
+
+import android.graphics.Bitmap;
+import android.graphics.RectF;
+import android.util.Log;
+
+// This is a ScreenNail wraps a Bitmap. It also includes the rotation
+// information. The getWidth() and getHeight() methods return the width/height
+// before rotation.
+public class BitmapScreenNail implements ScreenNail {
+ private static final String TAG = "BitmapScreenNail";
+ private final int mWidth;
+ private final int mHeight;
+ private final int mRotation;
+ private final Bitmap mBitmap;
+ private BitmapTexture mTexture;
+
+ public BitmapScreenNail(Bitmap bitmap, int rotation) {
+ mWidth = bitmap.getWidth();
+ mHeight = bitmap.getHeight();
+ mRotation = rotation;
+ mBitmap = bitmap;
+ // We create mTexture lazily, so we don't incur the cost if we don't
+ // actually need it.
+ }
+
+ @Override
+ public int getWidth() {
+ return mWidth;
+ }
+
+ @Override
+ public int getHeight() {
+ return mHeight;
+ }
+
+ @Override
+ public int getRotation() {
+ return mRotation;
+ }
+
+ @Override
+ public void recycle() {
+ if (mTexture != null) {
+ mTexture.recycle();
+ }
+ }
+
+ @Override
+ public void draw(GLCanvas canvas, int x, int y, int width, int height) {
+ if (mTexture == null) {
+ mTexture = new BitmapTexture(mBitmap);
+ }
+ mTexture.draw(canvas, x, y, width, height);
+ }
+
+ @Override
+ public void disableDraw() {
+ }
+
+ @Override
+ public void draw(GLCanvas canvas, RectF source, RectF dest) {
+ if (mTexture == null) {
+ mTexture = new BitmapTexture(mBitmap);
+ }
+ canvas.drawTexture(mTexture, source, dest);
+ }
+}
diff --git a/src/com/android/gallery3d/ui/BitmapTileProvider.java b/src/com/android/gallery3d/ui/BitmapTileProvider.java
index ec2f97f..a031b85 100644
--- a/src/com/android/gallery3d/ui/BitmapTileProvider.java
+++ b/src/com/android/gallery3d/ui/BitmapTileProvider.java
@@ -25,7 +25,7 @@
import java.util.ArrayList;
public class BitmapTileProvider implements TileImageView.Model {
- private final Bitmap mBackup;
+ private final ScreenNail mScreenNail;
private final Bitmap[] mMipmaps;
private final Config mConfig;
private final int mImageWidth;
@@ -44,13 +44,13 @@
list.add(bitmap);
}
- mBackup = list.remove(list.size() - 1);
+ mScreenNail = new BitmapScreenNail(list.remove(list.size() - 1), 0);
mMipmaps = list.toArray(new Bitmap[list.size()]);
mConfig = Config.ARGB_8888;
}
- public Bitmap getBackupImage() {
- return mBackup;
+ public ScreenNail getScreenNail() {
+ return mScreenNail;
}
public int getImageHeight() {
@@ -78,7 +78,9 @@
for (Bitmap bitmap : mMipmaps) {
BitmapUtils.recycleSilently(bitmap);
}
- BitmapUtils.recycleSilently(mBackup);
+ if (mScreenNail != null) {
+ mScreenNail.recycle();
+ }
}
public boolean isFailedToLoad() {
diff --git a/src/com/android/gallery3d/ui/PhotoView.java b/src/com/android/gallery3d/ui/PhotoView.java
index 31e41bf..3ec245f 100644
--- a/src/com/android/gallery3d/ui/PhotoView.java
+++ b/src/com/android/gallery3d/ui/PhotoView.java
@@ -19,14 +19,13 @@
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Color;
+import android.graphics.Rect;
import android.graphics.RectF;
import android.os.Message;
import android.view.MotionEvent;
import com.android.gallery3d.R;
import com.android.gallery3d.app.GalleryActivity;
-import com.android.gallery3d.data.Path;
-import com.android.gallery3d.ui.PositionRepository.Position;
public class PhotoView extends GLView {
@SuppressWarnings("unused")
@@ -91,11 +90,9 @@
private int mImageRotation;
- private Path mOpenedItemPath;
- private GalleryActivity mActivity;
+ private Rect mOpenAnimationRect;
public PhotoView(GalleryActivity activity) {
- mActivity = activity;
mTileView = new TileImageView(activity);
addComponent(mTileView);
Context context = activity.getAndroidContext();
@@ -120,7 +117,7 @@
case MSG_SHOW_LOADING: {
if (mLoadingState == LOADING_INIT) {
// We don't need the opening animation
- mOpenedItemPath = null;
+ mOpenAnimationRect = null;
mLoadingSpinner.startAnimation();
mLoadingState = LOADING_TIMEOUT;
@@ -176,18 +173,14 @@
}
}
- private void updateScreenNailEntry(int which, ImageData data) {
+ private void updateScreenNailEntry(int which, ScreenNail screenNail) {
if (mTransitionMode == TRANS_SWITCH_NEXT
|| mTransitionMode == TRANS_SWITCH_PREVIOUS) {
// ignore screen nail updating during switching
return;
}
ScreenNailEntry entry = mScreenNails[which];
- if (data == null) {
- entry.set(false, null, 0);
- } else {
- entry.set(true, data.bitmap, data.rotation);
- }
+ entry.set(screenNail);
}
// -1 previous, 0 current, 1 next
@@ -195,13 +188,13 @@
switch (which) {
case -1: {
updateScreenNailEntry(
- ENTRY_PREVIOUS, mModel.getPreviousImage());
+ ENTRY_PREVIOUS, mModel.getPrevScreenNail());
layoutScreenNails();
invalidate();
break;
}
case 1: {
- updateScreenNailEntry(ENTRY_NEXT, mModel.getNextImage());
+ updateScreenNailEntry(ENTRY_NEXT, mModel.getNextScreenNail());
layoutScreenNails();
invalidate();
break;
@@ -230,14 +223,14 @@
// TIMEOUT --> COMPLETE, FAIL, INIT
// COMPLETE --> INIT
// FAIL --> INIT
- if (mModel.getLevelCount() != 0 || mModel.getBackupImage() != null) {
+ if (mModel.getLevelCount() != 0 || mModel.getScreenNail() != null) {
mHandler.removeMessages(MSG_SHOW_LOADING);
mLoadingState = LOADING_COMPLETE;
} else if (mModel.isFailedToLoad()) {
mHandler.removeMessages(MSG_SHOW_LOADING);
mLoadingState = LOADING_FAIL;
// We don't want the opening animation after loading failure
- mOpenedItemPath = null;
+ mOpenAnimationRect = null;
} else if (mLoadingState != LOADING_INIT) {
mLoadingState = LOADING_INIT;
mHandler.removeMessages(MSG_SHOW_LOADING);
@@ -251,8 +244,8 @@
updateScreenNailEntry(ENTRY_PREVIOUS, null);
updateScreenNailEntry(ENTRY_NEXT, null);
} else {
- updateScreenNailEntry(ENTRY_PREVIOUS, mModel.getPreviousImage());
- updateScreenNailEntry(ENTRY_NEXT, mModel.getNextImage());
+ updateScreenNailEntry(ENTRY_PREVIOUS, mModel.getPrevScreenNail());
+ updateScreenNailEntry(ENTRY_NEXT, mModel.getNextScreenNail());
}
layoutScreenNails();
@@ -344,8 +337,8 @@
ScreenNailEntry prevNail = mScreenNails[ENTRY_PREVIOUS];
ScreenNailEntry nextNail = mScreenNails[ENTRY_NEXT];
- if (prevNail.mVisible) prevNail.draw(canvas);
- if (nextNail.mVisible) nextNail.draw(canvas);
+ prevNail.draw(canvas);
+ nextNail.draw(canvas);
}
// Draw the progress spinner and the text below it
@@ -581,10 +574,10 @@
ScreenNailEntry prevNail = mScreenNails[ENTRY_PREVIOUS];
ScreenNailEntry nextNail = mScreenNails[ENTRY_NEXT];
mTileView.invalidateTiles();
- if (prevNail.mTexture != null) prevNail.mTexture.recycle();
- prevNail.mTexture = mTileView.mBackupImage;
- mTileView.mBackupImage = nextNail.mTexture;
- nextNail.mTexture = null;
+ if (prevNail.mScreenNail != null) prevNail.mScreenNail.recycle();
+ prevNail.set(mTileView.mScreenNail);
+ mTileView.updateScreenNail(nextNail.mScreenNail);
+ nextNail.set(null);
mModel.next();
}
@@ -593,10 +586,10 @@
ScreenNailEntry prevNail = mScreenNails[ENTRY_PREVIOUS];
ScreenNailEntry nextNail = mScreenNails[ENTRY_NEXT];
mTileView.invalidateTiles();
- if (nextNail.mTexture != null) nextNail.mTexture.recycle();
- nextNail.mTexture = mTileView.mBackupImage;
- mTileView.mBackupImage = prevNail.mTexture;
- nextNail.mTexture = null;
+ if (nextNail.mScreenNail != null) nextNail.mScreenNail.recycle();
+ nextNail.set(mTileView.mScreenNail);
+ mTileView.updateScreenNail(prevNail.mScreenNail);
+ nextNail.set(null);
mModel.previous();
}
@@ -627,18 +620,8 @@
public int getImageRotation();
// Return null if the specified image is unavailable.
- public ImageData getNextImage();
- public ImageData getPreviousImage();
- }
-
- public static class ImageData {
- public int rotation;
- public Bitmap bitmap;
-
- public ImageData(Bitmap bitmap, int rotation) {
- this.bitmap = bitmap;
- this.rotation = rotation;
- }
+ public ScreenNail getNextScreenNail();
+ public ScreenNail getPrevScreenNail();
}
private static int getRotated(int degree, int original, int theother) {
@@ -649,28 +632,20 @@
private boolean mVisible;
private boolean mEnabled;
- private int mRotation;
private int mDrawWidth;
private int mDrawHeight;
private int mOffsetX;
+ private int mRotation;
- private BitmapTexture mTexture;
+ private ScreenNail mScreenNail;
- public void set(boolean enabled, Bitmap bitmap, int rotation) {
- mEnabled = enabled;
- mRotation = rotation;
- if (bitmap == null) {
- if (mTexture != null) mTexture.recycle();
- mTexture = null;
- } else {
- if (mTexture != null) {
- if (mTexture.getBitmap() != bitmap) {
- mTexture.recycle();
- mTexture = new BitmapTexture(bitmap);
- }
- } else {
- mTexture = new BitmapTexture(bitmap);
- }
+ public void set(ScreenNail screenNail) {
+ mEnabled = (screenNail != null);
+ if (mScreenNail == screenNail) return;
+ if (mScreenNail != null) mScreenNail.recycle();
+ mScreenNail = screenNail;
+ if (mScreenNail != null) {
+ mRotation = mScreenNail.getRotation();
updateDrawingSize();
}
}
@@ -689,15 +664,15 @@
public int gapToSide() {
return ((mRotation / 90) & 1) != 0
- ? PhotoView.gapToSide(mDrawHeight, getWidth())
- : PhotoView.gapToSide(mDrawWidth, getWidth());
+ ? PhotoView.gapToSide(mDrawHeight, getWidth())
+ : PhotoView.gapToSide(mDrawWidth, getWidth());
}
public void updateDrawingSize() {
- if (mTexture == null) return;
+ if (mScreenNail == null) return;
- int width = mTexture.getWidth();
- int height = mTexture.getHeight();
+ int width = mScreenNail.getWidth();
+ int height = mScreenNail.getHeight();
// Calculate the initial scale that will used by PositionController
// (usually fit-to-screen)
@@ -714,21 +689,27 @@
}
public void draw(GLCanvas canvas) {
+ if (mScreenNail == null) return;
+ if (!mVisible) {
+ mScreenNail.disableDraw();
+ return;
+ }
+
int x = mOffsetX;
int y = getHeight() / 2;
- if (mTexture != null) {
- if (mRotation != 0) {
- canvas.save(GLCanvas.SAVE_FLAG_MATRIX);
- canvas.translate(x, y);
- canvas.rotate(mRotation, 0, 0, 1); //mRotation
- canvas.translate(-x, -y);
- }
- mTexture.draw(canvas, x - mDrawWidth / 2, y - mDrawHeight / 2,
- mDrawWidth, mDrawHeight);
- if (mRotation != 0) {
- canvas.restore();
- }
+ if (mRotation != 0) {
+ canvas.save(GLCanvas.SAVE_FLAG_MATRIX);
+ canvas.translate(x, y);
+ canvas.rotate(mRotation, 0, 0, 1);
+ canvas.translate(-x, -y);
+ }
+
+ mScreenNail.draw(canvas, x - mDrawWidth / 2, y - mDrawHeight / 2,
+ mDrawWidth, mDrawHeight);
+
+ if (mRotation != 0) {
+ canvas.restore();
}
}
}
@@ -738,7 +719,7 @@
mTransitionMode = TRANS_NONE;
mTileView.freeTextures();
for (ScreenNailEntry entry : mScreenNails) {
- entry.set(false, null, 0);
+ entry.set(null);
}
}
@@ -746,24 +727,19 @@
mTileView.prepareTextures();
}
- public void setOpenedItem(Path itemPath) {
- mOpenedItemPath = itemPath;
+ public void setOpenAnimationRect(Rect rect) {
+ mOpenAnimationRect = rect;
}
public void showVideoPlayIcon(boolean show) {
mShowVideoPlayIcon = show;
}
- // Returns the position saved by the previous page.
- public Position retrieveSavedPosition() {
- if (mOpenedItemPath != null) {
- Position position = PositionRepository
- .getInstance(mActivity).get(
- System.identityHashCode(mOpenedItemPath));
- mOpenedItemPath = null;
- return position;
- }
- return null;
+ // Returns the opening animation rectangle saved by the previous page.
+ public Rect retrieveOpenAnimationRect() {
+ Rect r = mOpenAnimationRect;
+ mOpenAnimationRect = null;
+ return r;
}
public void openAnimationStarted() {
diff --git a/src/com/android/gallery3d/ui/PositionController.java b/src/com/android/gallery3d/ui/PositionController.java
index 1c9aba8..09fbc17 100644
--- a/src/com/android/gallery3d/ui/PositionController.java
+++ b/src/com/android/gallery3d/ui/PositionController.java
@@ -17,11 +17,12 @@
package com.android.gallery3d.ui;
import android.content.Context;
+import android.graphics.Rect;
import android.graphics.RectF;
import android.util.FloatMath;
import com.android.gallery3d.common.Utils;
-import com.android.gallery3d.ui.PositionRepository.Position;
+import com.android.gallery3d.data.MediaItem;
import com.android.gallery3d.util.GalleryUtils;
class PositionController {
@@ -140,14 +141,20 @@
mScaleMin = getMinimalScale(mImageW, mImageH);
- // Start animation from the saved position if we have one.
- Position position = mViewer.retrieveSavedPosition();
- if (position != null) {
- // The animation starts from 240 pixels and centers at the image
- // at the saved position.
- float scale = 240f / Math.min(width, height);
- mCurrentX = Math.round((mViewW / 2f - position.x) / scale) + mImageW / 2;
- mCurrentY = Math.round((mViewH / 2f - position.y) / scale) + mImageH / 2;
+ // Start animation from the saved rectangle if we have one.
+ Rect r = mViewer.retrieveOpenAnimationRect();
+ if (r != null) {
+ // The animation starts from the specified rectangle; the image
+ // should be scaled and centered as the thumbnail shown in the
+ // rectangle to minimize janky opening animation. Note: The below
+ // implementation depends on how thumbnails are drawn and placed.
+ float size = MediaItem.getTargetSize(
+ MediaItem.TYPE_MICROTHUMBNAIL);
+ float scale = (size / Math.min(width, height)) * Math.min(
+ r.width() / size, r.height() / size);
+
+ mCurrentX = Math.round((mViewW / 2f - r.centerX()) / scale) + mImageW / 2;
+ mCurrentY = Math.round((mViewH / 2f - r.centerY()) / scale) + mImageH / 2;
mCurrentScale = scale;
mViewer.openAnimationStarted();
startSnapback();
diff --git a/src/com/android/gallery3d/ui/ScreenNail.java b/src/com/android/gallery3d/ui/ScreenNail.java
new file mode 100644
index 0000000..a2377fe
--- /dev/null
+++ b/src/com/android/gallery3d/ui/ScreenNail.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2012 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.ui;
+
+import android.graphics.RectF;
+
+public interface ScreenNail {
+ public int getWidth();
+ public int getHeight();
+ public int getRotation();
+ public void recycle();
+ public void draw(GLCanvas canvas, int x, int y, int width, int height);
+
+ // We need this method to tell ScreenNail to stop displaying.
+ public void disableDraw();
+
+ // This is only used by TileImageView to back up the tiles not yet loaded.
+ public void draw(GLCanvas canvas, RectF source, RectF dest);
+}
diff --git a/src/com/android/gallery3d/ui/TileImageView.java b/src/com/android/gallery3d/ui/TileImageView.java
index 7ad5546..d81244d 100644
--- a/src/com/android/gallery3d/ui/TileImageView.java
+++ b/src/com/android/gallery3d/ui/TileImageView.java
@@ -70,7 +70,7 @@
private static final int STATE_RECYCLED = 0x40;
private Model mModel;
- protected BitmapTexture mBackupImage;
+ protected ScreenNail mScreenNail;
protected int mLevelCount; // cache the value of mScaledBitmaps.length
// The mLevel variable indicates which level of bitmap we should use.
@@ -78,7 +78,7 @@
// a smaller scaled bitmap (The width and height of each scaled bitmap is
// half size of the previous one). If the value is in [0, mLevelCount), we
// use the bitmap in mScaledBitmaps[mLevel] for display, otherwise the value
- // is mLevelCount, and that means we use mBackupTexture for display.
+ // is mLevelCount, and that means we use mScreenNail for display.
private int mLevel = 0;
// The offsets of the (left, top) of the upper-left tile to the (left, top)
@@ -120,7 +120,7 @@
public static interface Model {
public int getLevelCount();
- public Bitmap getBackupImage();
+ public ScreenNail getScreenNail();
public int getImageWidth();
public int getImageHeight();
@@ -139,31 +139,21 @@
if (model != null) notifyModelInvalidated();
}
- private void updateBackupTexture(Bitmap backup) {
- if (backup == null) {
- if (mBackupImage != null) mBackupImage.recycle();
- mBackupImage = null;
- } else {
- if (mBackupImage != null) {
- if (mBackupImage.getBitmap() != backup) {
- mBackupImage.recycle();
- mBackupImage = new BitmapTexture(backup);
- }
- } else {
- mBackupImage = new BitmapTexture(backup);
- }
- }
+ public void updateScreenNail(ScreenNail s) {
+ if (mScreenNail == s) return;
+ if (mScreenNail != null) mScreenNail.recycle();
+ mScreenNail = s;
}
public void notifyModelInvalidated() {
invalidateTiles();
if (mModel == null) {
- mBackupImage = null;
+ mScreenNail = null;
mImageWidth = 0;
mImageHeight = 0;
mLevelCount = 0;
} else {
- updateBackupTexture(mModel.getBackupImage());
+ updateScreenNail(mModel.getScreenNail());
mImageWidth = mModel.getImageWidth();
mImageHeight = mModel.getImageHeight();
mLevelCount = mModel.getLevelCount();
@@ -348,7 +338,7 @@
tile = mRecycledQueue.pop();
}
}
- updateBackupTexture(null);
+ updateScreenNail(null);
}
public void prepareTextures() {
@@ -358,7 +348,7 @@
if (mIsTextureFreed) {
layoutTiles(mCenterX, mCenterY, mScale, mRotation);
mIsTextureFreed = false;
- updateBackupTexture(mModel != null ? mModel.getBackupImage() : null);
+ updateScreenNail(mModel != null ? mModel.getScreenNail() : null);
}
}
@@ -379,6 +369,10 @@
}
try {
if (level != mLevelCount) {
+ if (mScreenNail != null) {
+ mScreenNail.disableDraw();
+ }
+
int size = (TILE_SIZE << level);
float length = size * mScale;
Rect r = mTileRange;
@@ -390,8 +384,8 @@
drawTile(canvas, tx, ty, level, x, y, length);
}
}
- } else if (mBackupImage != null) {
- mBackupImage.draw(canvas, mOffsetX, mOffsetY,
+ } else if (mScreenNail != null) {
+ mScreenNail.draw(canvas, mOffsetX, mOffsetY,
Math.round(mImageWidth * mScale),
Math.round(mImageHeight * mScale));
}
@@ -542,14 +536,13 @@
}
if (drawTile(tile, canvas, source, target)) return;
}
- if (mBackupImage != null) {
- BasicTexture backup = mBackupImage;
+ if (mScreenNail != null) {
int size = TILE_SIZE << level;
- float scaleX = (float) backup.getWidth() / mImageWidth;
- float scaleY = (float) backup.getHeight() / mImageHeight;
+ float scaleX = (float) mScreenNail.getWidth() / mImageWidth;
+ float scaleY = (float) mScreenNail.getHeight() / mImageHeight;
source.set(tx * scaleX, ty * scaleY, (tx + size) * scaleX,
(ty + size) * scaleY);
- canvas.drawTexture(backup, source, target);
+ mScreenNail.draw(canvas, source, target);
}
}
diff --git a/src/com/android/gallery3d/ui/TileImageViewAdapter.java b/src/com/android/gallery3d/ui/TileImageViewAdapter.java
index 63bb0b2..475184e 100644
--- a/src/com/android/gallery3d/ui/TileImageViewAdapter.java
+++ b/src/com/android/gallery3d/ui/TileImageViewAdapter.java
@@ -27,10 +27,10 @@
public class TileImageViewAdapter implements TileImageView.Model {
private static final String TAG = "TileImageViewAdapter";
+ protected ScreenNail mScreenNail;
protected BitmapRegionDecoder mRegionDecoder;
protected int mImageWidth;
protected int mImageHeight;
- protected Bitmap mBackupImage;
protected int mLevelCount;
protected boolean mFailedToLoad;
@@ -40,8 +40,8 @@
public TileImageViewAdapter() {
}
- public TileImageViewAdapter(Bitmap backup, BitmapRegionDecoder regionDecoder) {
- mBackupImage = Utils.checkNotNull(backup);
+ public TileImageViewAdapter(Bitmap bitmap, BitmapRegionDecoder regionDecoder) {
+ mScreenNail = new BitmapScreenNail(Utils.checkNotNull(bitmap), 0);
mRegionDecoder = regionDecoder;
mImageWidth = regionDecoder.getWidth();
mImageHeight = regionDecoder.getHeight();
@@ -49,7 +49,7 @@
}
public synchronized void clear() {
- mBackupImage = null;
+ mScreenNail = null;
mImageWidth = 0;
mImageHeight = 0;
mLevelCount = 0;
@@ -57,8 +57,18 @@
mFailedToLoad = false;
}
- public synchronized void setBackupImage(Bitmap backup, int width, int height) {
- mBackupImage = Utils.checkNotNull(backup);
+ public synchronized void setScreenNail(Bitmap bitmap, int width, int height) {
+ mScreenNail = new BitmapScreenNail(Utils.checkNotNull(bitmap), 0);
+ mImageWidth = width;
+ mImageHeight = height;
+ mRegionDecoder = null;
+ mLevelCount = 0;
+ mFailedToLoad = false;
+ }
+
+ public synchronized void setScreenNail(
+ ScreenNail screenNail, int width, int height) {
+ mScreenNail = Utils.checkNotNull(screenNail);
mImageWidth = width;
mImageHeight = height;
mRegionDecoder = null;
@@ -76,7 +86,7 @@
private int calculateLevelCount() {
return Math.max(0, Utils.ceilLog2(
- (float) mImageWidth / mBackupImage.getWidth()));
+ (float) mImageWidth / mScreenNail.getWidth()));
}
@Override
@@ -122,8 +132,8 @@
}
@Override
- public Bitmap getBackupImage() {
- return mBackupImage;
+ public ScreenNail getScreenNail() {
+ return mScreenNail;
}
@Override