From b79bbd85bc1ce26a18a2be1100b95dfacbbce5e6 Mon Sep 17 00:00:00 2001 From: Chih-Chung Chang Date: Thu, 19 Apr 2012 20:14:11 +0800 Subject: In filmstrip, show placeholders for pictures not loaded yet. Change-Id: I037f1f054da4a3800045d5b89724341ac22272a5 --- .../android/gallery3d/app/PhotoDataAdapter.java | 58 +++++++++++----- .../gallery3d/app/SinglePhotoDataAdapter.java | 42 ++++++++---- src/com/android/gallery3d/ui/BitmapScreenNail.java | 9 +-- .../android/gallery3d/ui/BitmapTileProvider.java | 2 +- src/com/android/gallery3d/ui/PhotoView.java | 79 ++++++++++++++++------ .../android/gallery3d/ui/PositionController.java | 9 ++- src/com/android/gallery3d/ui/ScreenNail.java | 1 - .../gallery3d/ui/SurfaceTextureScreenNail.java | 5 -- .../android/gallery3d/ui/TileImageViewAdapter.java | 4 +- 9 files changed, 138 insertions(+), 71 deletions(-) (limited to 'src/com/android/gallery3d') diff --git a/src/com/android/gallery3d/app/PhotoDataAdapter.java b/src/com/android/gallery3d/app/PhotoDataAdapter.java index ec59997f4..096e781de 100644 --- a/src/com/android/gallery3d/app/PhotoDataAdapter.java +++ b/src/com/android/gallery3d/app/PhotoDataAdapter.java @@ -210,20 +210,14 @@ public class PhotoDataAdapter implements PhotoPage.Model { for (int i = -SCREEN_NAIL_MAX; i <= SCREEN_NAIL_MAX; ++i) { mChanges[i + SCREEN_NAIL_MAX] = getVersion(mCurrentIndex + i); } - mPhotoView.notifyDataChange(mChanges, mCurrentIndex > 0, - mCurrentIndex < mSize - 1); + mPhotoView.notifyDataChange(mChanges, -mCurrentIndex, + mSize - 1 - mCurrentIndex); } public void setDataListener(DataListener listener) { mDataListener = listener; } - @Override - public void setNeedFullImage(boolean enabled) { - mNeedFullImage = enabled; - mMainHandler.sendEmptyMessage(MSG_UPDATE_IMAGE_REQUESTS); - } - private void updateScreenNail(long version, Future future) { ImageEntry entry = mImageCache.get(version); ScreenNail screenNail = future.get(); @@ -307,8 +301,14 @@ public class PhotoDataAdapter implements PhotoPage.Model { return entry == null ? null : entry.screenNail; } - public ScreenNail getScreenNail(int offset) { - return getImage(mCurrentIndex + offset); + private MediaItem getItem(int index) { + if (index < 0 || index >= mSize || !mIsActive) return null; + Utils.assertTrue(index >= mActiveStart && index < mActiveEnd); + + if (index >= mContentStart && index < mContentEnd) { + return mData[index % DATA_CACHE_SIZE]; + } + return null; } private void updateCurrentIndex(int index) { @@ -329,14 +329,45 @@ public class PhotoDataAdapter implements PhotoPage.Model { fireDataChange(); } + @Override public void next() { updateCurrentIndex(mCurrentIndex + 1); } + @Override public void previous() { updateCurrentIndex(mCurrentIndex - 1); } + @Override + public ScreenNail getScreenNail(int offset) { + return getImage(mCurrentIndex + offset); + } + + @Override + public void getImageSize(int offset, PhotoView.Size size) { + MediaItem item = getItem(mCurrentIndex + offset); + if (item == null) { + size.width = 0; + size.height = 0; + } else { + size.width = item.getWidth(); + size.height = item.getHeight(); + } + } + + @Override + public int getImageRotation(int offset) { + MediaItem item = getItem(mCurrentIndex + offset); + return (item == null) ? 0 : item.getFullImageRotation(); + } + + @Override + public void setNeedFullImage(boolean enabled) { + mNeedFullImage = enabled; + mMainHandler.sendEmptyMessage(MSG_UPDATE_IMAGE_REQUESTS); + } + public ScreenNail getScreenNail() { return mTileProvider.getScreenNail(); } @@ -349,11 +380,6 @@ public class PhotoDataAdapter implements PhotoPage.Model { return mTileProvider.getImageWidth(); } - public int getImageRotation() { - ImageEntry entry = mImageCache.get(getVersion(mCurrentIndex)); - return entry == null ? 0 : entry.rotation; - } - public int getLevelCount() { return mTileProvider.getLevelCount(); } @@ -505,7 +531,7 @@ public class PhotoDataAdapter implements PhotoPage.Model { bitmap = BitmapUtils.rotateBitmap(bitmap, mItem.getRotation() - mItem.getFullImageRotation(), true); } - return new BitmapScreenNail(bitmap, mItem.getFullImageRotation()); + return new BitmapScreenNail(bitmap); } } diff --git a/src/com/android/gallery3d/app/SinglePhotoDataAdapter.java b/src/com/android/gallery3d/app/SinglePhotoDataAdapter.java index 59959cf4a..47f6acba9 100644 --- a/src/com/android/gallery3d/app/SinglePhotoDataAdapter.java +++ b/src/com/android/gallery3d/app/SinglePhotoDataAdapter.java @@ -109,15 +109,6 @@ public class SinglePhotoDataAdapter extends TileImageViewAdapter return false; } - public int getImageRotation() { - return mItem.getRotation(); - } - - @Override - public void setNeedFullImage(boolean enabled) { - // currently not necessary. - } - private void onDecodeLargeComplete(ImageBundle bundle) { try { setScreenNail(bundle.backupImage, @@ -162,18 +153,43 @@ public class SinglePhotoDataAdapter extends TileImageViewAdapter } } - public ScreenNail getScreenNail(int offset) { - return (offset == 0) ? getScreenNail() : null; - } - + @Override public void next() { throw new UnsupportedOperationException(); } + @Override public void previous() { throw new UnsupportedOperationException(); } + @Override + public void getImageSize(int offset, PhotoView.Size size) { + if (offset == 0) { + size.width = mItem.getWidth(); + size.height = mItem.getHeight(); + } else { + size.width = 0; + size.height = 0; + } + } + + @Override + public int getImageRotation(int offset) { + return (offset == 0) ? mItem.getFullImageRotation() : 0; + } + + @Override + public ScreenNail getScreenNail(int offset) { + return (offset == 0) ? getScreenNail() : null; + } + + @Override + public void setNeedFullImage(boolean enabled) { + // currently not necessary. + } + + public MediaItem getCurrentMediaItem() { return mItem; } diff --git a/src/com/android/gallery3d/ui/BitmapScreenNail.java b/src/com/android/gallery3d/ui/BitmapScreenNail.java index 064e1af0e..7f654058e 100644 --- a/src/com/android/gallery3d/ui/BitmapScreenNail.java +++ b/src/com/android/gallery3d/ui/BitmapScreenNail.java @@ -29,14 +29,12 @@ public class BitmapScreenNail implements ScreenNail { private static final String TAG = "BitmapScreenNail"; private final int mWidth; private final int mHeight; - private final int mRotation; private Bitmap mBitmap; private BitmapTexture mTexture; - public BitmapScreenNail(Bitmap bitmap, int rotation) { + public BitmapScreenNail(Bitmap bitmap) { 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. @@ -52,11 +50,6 @@ public class BitmapScreenNail implements ScreenNail { return mHeight; } - @Override - public int getRotation() { - return mRotation; - } - @Override public void noDraw() { } diff --git a/src/com/android/gallery3d/ui/BitmapTileProvider.java b/src/com/android/gallery3d/ui/BitmapTileProvider.java index 99b64d42e..be05b33ab 100644 --- a/src/com/android/gallery3d/ui/BitmapTileProvider.java +++ b/src/com/android/gallery3d/ui/BitmapTileProvider.java @@ -44,7 +44,7 @@ public class BitmapTileProvider implements TileImageView.Model { list.add(bitmap); } - mScreenNail = new BitmapScreenNail(list.remove(list.size() - 1), 0); + mScreenNail = new BitmapScreenNail(list.remove(list.size() - 1)); mMipmaps = list.toArray(new Bitmap[list.size()]); mConfig = Config.ARGB_8888; } diff --git a/src/com/android/gallery3d/ui/PhotoView.java b/src/com/android/gallery3d/ui/PhotoView.java index 306da81c1..109a5d977 100644 --- a/src/com/android/gallery3d/ui/PhotoView.java +++ b/src/com/android/gallery3d/ui/PhotoView.java @@ -38,20 +38,34 @@ import java.util.Arrays; public class PhotoView extends GLView { @SuppressWarnings("unused") private static final String TAG = "PhotoView"; + private static final int PLACEHOLDER_COLOR = 0xFF222222; public static final int INVALID_SIZE = -1; public static final long INVALID_DATA_VERSION = MediaObject.INVALID_DATA_VERSION; - public static interface Model extends TileImageView.Model { + public static class Size { + public int width; + public int height; + } + + public interface Model extends TileImageView.Model { public void next(); public void previous(); - public int getImageRotation(); + + // Returns the size for the specified picture. If the size information is + // not avaiable, width = height = 0. + public void getImageSize(int offset, Size size); + + // Returns the rotation for the specified picture. + public int getImageRotation(int offset); // This amends the getScreenNail() method of TileImageView.Model to get // ScreenNail at previous (negative offset) or next (positive offset) // positions. Returns null if the specified ScreenNail is unavailable. public ScreenNail getScreenNail(int offset); + + // Set this to true if we need the model to provide full images. public void setNeedFullImage(boolean enabled); } @@ -119,6 +133,13 @@ public class PhotoView extends GLView { private boolean mCancelExtraScalingPending; private boolean mFilmMode = false; + // [mPrevBound, mNextBound] is the range of index for all pictures in the + // model, if we assume the index of current focused picture is 0. So if + // there are some previous pictures, mPrevBound < 0, and if there are some + // next pictures, mNextBound > 0. + private int mPrevBound; + private int mNextBound; + public PhotoView(GalleryActivity activity) { mTileView = new TileImageView(activity); addComponent(mTileView); @@ -232,8 +253,10 @@ public class PhotoView extends GLView { // Data/Image change notifications //////////////////////////////////////////////////////////////////////////// - public void notifyDataChange(long[] versions, boolean hasPrev, - boolean hasNext) { + public void notifyDataChange(long[] versions, int prevBound, int nextBound) { + mPrevBound = prevBound; + mNextBound = nextBound; + // Check if the data version actually changed. boolean changed = false; int N = 2 * SCREEN_NAIL_MAX + 1; @@ -270,7 +293,7 @@ public class PhotoView extends GLView { } // Move the boxes - mPositionController.moveBox(mFromIndex, hasPrev, hasNext); + mPositionController.moveBox(mFromIndex, mPrevBound < 0, mNextBound > 0); // Update the ScreenNails. for (int i = -SCREEN_NAIL_MAX; i <= SCREEN_NAIL_MAX; i++) { @@ -312,18 +335,14 @@ public class PhotoView extends GLView { mTileView.notifyModelInvalidated(); if (CARD_EFFECT) mTileView.setAlpha(1.0f); - if (mModel == null) { - mRotation = 0; - mPositionController.setImageSize(0, 0, 0); - } else { - mRotation = mModel.getImageRotation(); - int w = mTileView.mImageWidth; - int h = mTileView.mImageHeight; - mPositionController.setImageSize(0, - getRotated(mRotation, w, h), - getRotated(mRotation, h, w)); - } - setScreenNail(mModel == null ? null : mModel.getScreenNail(0)); + mRotation = mModel.getImageRotation(0); + int w = mTileView.mImageWidth; + int h = mTileView.mImageHeight; + mPositionController.setImageSize(0, + getRotated(mRotation, w, h), + getRotated(mRotation, h, w)); + + setScreenNail(mModel.getScreenNail(0)); updateLoadingState(); } @@ -447,6 +466,7 @@ public class PhotoView extends GLView { private boolean mEnabled; private int mRotation; private ScreenNail mScreenNail; + private Size mSize = new Size(); public ScreenNailPicture(int index) { mIndex = index; @@ -454,12 +474,18 @@ public class PhotoView extends GLView { @Override public void reload() { - setScreenNail(mModel == null ? null : mModel.getScreenNail(mIndex)); + setScreenNail(mModel.getScreenNail(mIndex)); } @Override public void draw(GLCanvas canvas, Rect r) { if (mScreenNail == null) { + // Draw a placeholder rectange if there will be a picture in + // this position. + if (mIndex >= mPrevBound && mIndex <= mNextBound) { + canvas.fillRect(r.left, r.top, r.width(), r.height(), + PLACEHOLDER_COLOR); + } return; } if (r.left >= getWidth() || r.right <= 0 || @@ -501,12 +527,21 @@ public class PhotoView extends GLView { mEnabled = (s != null); if (mScreenNail == s) return; mScreenNail = s; + mRotation = mModel.getImageRotation(mIndex); + + int w = 0, h = 0; if (mScreenNail != null) { - mRotation = mScreenNail.getRotation(); + w = s.getWidth(); + h = s.getHeight(); + } else if (mModel != null) { + // If we don't have ScreenNail available, we can still try to + // get the size information of it. + mModel.getImageSize(mIndex, mSize); + w = mSize.width; + h = mSize.height; } - if (mScreenNail != null) { - int w = s.getWidth(); - int h = s.getHeight(); + + if (w != 0 && h != 0) { mPositionController.setImageSize(mIndex, getRotated(mRotation, w, h), getRotated(mRotation, h, w)); diff --git a/src/com/android/gallery3d/ui/PositionController.java b/src/com/android/gallery3d/ui/PositionController.java index f087c6b70..46f01217f 100644 --- a/src/com/android/gallery3d/ui/PositionController.java +++ b/src/com/android/gallery3d/ui/PositionController.java @@ -533,7 +533,10 @@ class PositionController { mFilmScroller.fling(p.mCurrentX, 0, velocityX, 0, Integer.MIN_VALUE, Integer.MAX_VALUE, 0, 0); int targetX = mFilmScroller.getFinalX(); - ANIM_TIME[ANIM_KIND_FLING] = mFilmScroller.getDuration(); + // This value doesn't matter because we use mFilmScroller.isFinished() + // to decide when to stop. We set this to 0 so it's faster for + // Animatable.advanceAnimation() to calculate the progress (always 1). + ANIM_TIME[ANIM_KIND_FLING] = 0; startAnimation(targetX, b.mCurrentY, b.mCurrentScale, ANIM_KIND_FLING); return true; } @@ -1123,8 +1126,8 @@ class PositionController { float scale = Utils.clamp(b.mCurrentScale, scaleMin, scaleMax); int x = mCurrentX; if (mFilmMode) { - if (mHasNext) x = Math.max(x, mViewW / 2); - if (mHasPrev) x = Math.min(x, mViewW / 2); + if (!mHasNext) x = Math.max(x, mViewW / 2); + if (!mHasPrev) x = Math.min(x, mViewW / 2); } else { calculateStableBound(scale, HORIZONTAL_SLACK); x = Utils.clamp(x, mBoundLeft, mBoundRight); diff --git a/src/com/android/gallery3d/ui/ScreenNail.java b/src/com/android/gallery3d/ui/ScreenNail.java index 25adc77da..0a16ab850 100644 --- a/src/com/android/gallery3d/ui/ScreenNail.java +++ b/src/com/android/gallery3d/ui/ScreenNail.java @@ -20,7 +20,6 @@ import android.graphics.RectF; public interface ScreenNail { public int getWidth(); public int getHeight(); - public int getRotation(); public void draw(GLCanvas canvas, int x, int y, int width, int height); // We do not need to draw this ScreenNail in this frame. diff --git a/src/com/android/gallery3d/ui/SurfaceTextureScreenNail.java b/src/com/android/gallery3d/ui/SurfaceTextureScreenNail.java index f8442d059..555def839 100644 --- a/src/com/android/gallery3d/ui/SurfaceTextureScreenNail.java +++ b/src/com/android/gallery3d/ui/SurfaceTextureScreenNail.java @@ -76,11 +76,6 @@ public abstract class SurfaceTextureScreenNail implements ScreenNail, return mHeight; } - @Override - public int getRotation() { - return 0; - } - @Override public void draw(GLCanvas canvas, int x, int y, int width, int height) { synchronized (this) { diff --git a/src/com/android/gallery3d/ui/TileImageViewAdapter.java b/src/com/android/gallery3d/ui/TileImageViewAdapter.java index 8061657fd..f4c6e658a 100644 --- a/src/com/android/gallery3d/ui/TileImageViewAdapter.java +++ b/src/com/android/gallery3d/ui/TileImageViewAdapter.java @@ -41,7 +41,7 @@ public class TileImageViewAdapter implements TileImageView.Model { public TileImageViewAdapter( Bitmap bitmap, BitmapRegionDecoder regionDecoder) { Utils.checkNotNull(bitmap); - updateScreenNail(new BitmapScreenNail(bitmap, 0), true); + updateScreenNail(new BitmapScreenNail(bitmap), true); mRegionDecoder = regionDecoder; mImageWidth = regionDecoder.getWidth(); mImageHeight = regionDecoder.getHeight(); @@ -59,7 +59,7 @@ public class TileImageViewAdapter implements TileImageView.Model { public synchronized void setScreenNail(Bitmap bitmap, int width, int height) { Utils.checkNotNull(bitmap); - updateScreenNail(new BitmapScreenNail(bitmap, 0), true); + updateScreenNail(new BitmapScreenNail(bitmap), true); mImageWidth = width; mImageHeight = height; mRegionDecoder = null; -- cgit v1.2.3