summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--AndroidManifest.xml12
-rw-r--r--res/layout/view_gif_image.xml17
-rw-r--r--src/com/android/gallery3d/app/MovieControllerOverlay.java50
-rwxr-xr-xsrc/com/android/gallery3d/app/MoviePlayer.java5
-rwxr-xr-xsrc/com/android/gallery3d/app/PhotoDataAdapter.java232
-rw-r--r--src/com/android/gallery3d/app/PhotoPage.java13
-rw-r--r--[-rwxr-xr-x]src/com/android/gallery3d/app/TimeLineDataLoader.java40
-rw-r--r--[-rwxr-xr-x]src/com/android/gallery3d/app/TimeLinePage.java0
-rw-r--r--src/com/android/gallery3d/data/ClusterAlbumSet.java16
-rw-r--r--src/com/android/gallery3d/ui/PhotoView.java4
-rw-r--r--src/com/android/gallery3d/ui/TimeLineSlidingWindow.java17
-rw-r--r--src/com/android/gallery3d/ui/TimeLineSlotRenderer.java13
-rw-r--r--src/com/android/gallery3d/ui/TimeLineSlotView.java375
-rw-r--r--src/com/android/gallery3d/util/GIFView.java234
-rwxr-xr-xsrc/com/android/gallery3d/util/GifDecoder.java22
-rwxr-xr-xsrc/com/android/gallery3d/util/GifRequest.java78
-rwxr-xr-xsrc/com/android/gallery3d/util/ViewGifImage.java67
-rw-r--r--src/org/codeaurora/gallery3d/ext/IContrllerOverlayExt.java5
18 files changed, 529 insertions, 671 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 08ca742e0..1eda90bf7 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (c) 2010-2014, The Linux Foundation. All rights reserved.
+<!-- Copyright (c) 2010-2014, 2016, The Linux Foundation. All rights reserved.
Not a Contribution.
Copyright (C) 2007 The Android Open Source Project
@@ -328,16 +328,6 @@
android:theme="@style/Theme.Gallery"
android:configChanges="orientation|keyboardHidden|screenSize" />
- <activity android:name="com.android.gallery3d.util.ViewGifImage"
- android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen"
- android:configChanges="orientation|keyboardHidden|screenSize|keyboard|navigation">
- <intent-filter>
- <action android:name="com.android.gallery3d.VIEW_GIF" />
- <data android:mimeType="image/gif" />
- <category android:name="android.intent.category.DEFAULT" />
- </intent-filter>
- </activity>
-
<provider android:name="com.android.gallery3d.provider.GalleryProvider"
android:syncable="false"
android:grantUriPermissions="true"
diff --git a/res/layout/view_gif_image.xml b/res/layout/view_gif_image.xml
deleted file mode 100644
index 976549a6b..000000000
--- a/res/layout/view_gif_image.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <LinearLayout
- android:id="@+id/image_absoluteLayout"
- android:layout_height="match_parent"
- android:layout_width="match_parent">
- <ImageView android:id="@+id/image_display_area"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:clickable="true">
- </ImageView>
- </LinearLayout>
-
-</RelativeLayout>
diff --git a/src/com/android/gallery3d/app/MovieControllerOverlay.java b/src/com/android/gallery3d/app/MovieControllerOverlay.java
index b2851e020..72b95fd38 100644
--- a/src/com/android/gallery3d/app/MovieControllerOverlay.java
+++ b/src/com/android/gallery3d/app/MovieControllerOverlay.java
@@ -22,6 +22,7 @@ import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.Rect;
import android.graphics.drawable.VectorDrawable;
+import android.media.MediaPlayer;
import android.os.Handler;
import android.text.TextUtils;
import android.util.DisplayMetrics;
@@ -442,6 +443,18 @@ public class MovieControllerOverlay extends CommonControllerOverlay implements
mScreenModeManager.setScreenMode(ScreenModeManager.SCREENMODE_BIGSCREEN);
}
+ private void updateBackgroundColor() {
+ switch (mState) {
+ case PAUSED:
+ case PLAYING:
+ case BUFFERING:
+ setBackgroundColor(Color.TRANSPARENT);
+ break;
+ default:
+ setBackgroundColor(Color.BLACK);
+ }
+ }
+
public IContrllerOverlayExt getOverlayExt() {
return mOverlayExt;
}
@@ -463,31 +476,16 @@ public class MovieControllerOverlay extends CommonControllerOverlay implements
private boolean mAlwaysShowBottom;
@Override
- public void showBuffering(boolean fullBuffer, int percent) {
- if (LOG) {
- Log.v(TAG, "showBuffering(" + fullBuffer + ", " + percent
- + ") " + "lastState=" + mLastState + ", state=" + mState);
- }
- if (fullBuffer) {
- // do not show text and loading
- mTimeBar.setSecondaryProgress(percent);
- return;
- }
+ public void showBuffering(int what) {
if (mState == State.PAUSED || mState == State.PLAYING) {
mLastState = mState;
}
- if (percent >= 0 && percent < 100) { // valid value
+ if (what == MediaPlayer.MEDIA_INFO_BUFFERING_START) {
mState = State.BUFFERING;
- String text = "media controller buffering";
- mTimeBar.setInfo(text);
showMainView(mLoadingView);
- } else if (percent == 100) {
- mState = mLastState;
- mTimeBar.setInfo(null);
- showMainView(mPlayPauseReplayView);// restore play pause state
- } else { // here to restore old state
+ } else if (what == MediaPlayer.MEDIA_INFO_BUFFERING_END || what == TimeBar.UNKNOWN) {
mState = mLastState;
- mTimeBar.setInfo(null);
+ showMainView(mPlayPauseReplayView);
}
}
@@ -497,7 +495,7 @@ public class MovieControllerOverlay extends CommonControllerOverlay implements
Log.v(TAG, "clearBuffering()");
}
mTimeBar.setSecondaryProgress(TimeBar.UNKNOWN);
- showBuffering(false, TimeBar.UNKNOWN);
+ showBuffering(TimeBar.UNKNOWN);
}
public void showReconnecting(int times) {
@@ -558,11 +556,7 @@ public class MovieControllerOverlay extends CommonControllerOverlay implements
mAlwaysShowBottom = alwaysShow;
if (!alwaysShow) { // clear background
setBackgroundDrawable(null);
- if (mState == State.PAUSED || mState == State.PLAYING) {
- setBackgroundColor(Color.TRANSPARENT);
- }else {
- setBackgroundColor(Color.BLACK);
- }
+ updateBackgroundColor();
} else {
setBackgroundResource(R.drawable.media_default_bkg);
if (foreShow) {
@@ -879,11 +873,7 @@ public class MovieControllerOverlay extends CommonControllerOverlay implements
public void onShow() {
Log.v(TAG, "ControllerRewindAndForwardExt onShow: "+mState);
mContollerButtons.setVisibility(View.VISIBLE);
- if (mState == State.PAUSED || mState == State.PLAYING) {
- setBackgroundColor(Color.TRANSPARENT);
- } else {
- setBackgroundColor(Color.BLACK);
- }
+ updateBackgroundColor();
}
public void onLayout(int l, int r, int b) {
diff --git a/src/com/android/gallery3d/app/MoviePlayer.java b/src/com/android/gallery3d/app/MoviePlayer.java
index e1b8709b3..0ecc8bf20 100755
--- a/src/com/android/gallery3d/app/MoviePlayer.java
+++ b/src/com/android/gallery3d/app/MoviePlayer.java
@@ -810,6 +810,9 @@ public class MoviePlayer implements
} else if (what == MediaPlayer.MEDIA_INFO_METADATA_UPDATE && mServerTimeoutExt != null) {
Log.e(TAG, "setServerTimeout " + extra);
mServerTimeoutExt.setTimeout(extra * 1000);
+ } else if ((what == MediaPlayer.MEDIA_INFO_BUFFERING_START
+ || what == MediaPlayer.MEDIA_INFO_BUFFERING_END) && mOverlayExt != null) {
+ mOverlayExt.showBuffering(what);
}
if (mRetryExt.onInfo(mp, what, extra)) {
return true;
@@ -819,8 +822,6 @@ public class MoviePlayer implements
@Override
public void onBufferingUpdate(MediaPlayer mp, int percent) {
- boolean fullBuffer = isFullBuffer();
- mOverlayExt.showBuffering(fullBuffer, percent);
}
@Override
diff --git a/src/com/android/gallery3d/app/PhotoDataAdapter.java b/src/com/android/gallery3d/app/PhotoDataAdapter.java
index aa28b5557..d65c0d1c8 100755
--- a/src/com/android/gallery3d/app/PhotoDataAdapter.java
+++ b/src/com/android/gallery3d/app/PhotoDataAdapter.java
@@ -34,6 +34,7 @@ import com.android.gallery3d.data.MediaSet;
import com.android.gallery3d.data.Path;
import com.android.gallery3d.data.SnailItem;
import com.android.gallery3d.glrenderer.TiledTexture;
+import com.android.gallery3d.ui.BitmapScreenNail;
import com.android.gallery3d.ui.PhotoView;
import com.android.gallery3d.ui.ScreenNail;
import com.android.gallery3d.ui.SynchronizedHandler;
@@ -41,11 +42,14 @@ import com.android.gallery3d.ui.TileImageViewAdapter;
import com.android.gallery3d.ui.TiledScreenNail;
import com.android.gallery3d.util.Future;
import com.android.gallery3d.util.FutureListener;
+import com.android.gallery3d.util.GifDecoder;
+import com.android.gallery3d.util.GifRequest;
import com.android.gallery3d.util.MediaSetUtils;
import com.android.gallery3d.util.ThreadPool;
import com.android.gallery3d.util.ThreadPool.Job;
import com.android.gallery3d.util.ThreadPool.JobContext;
+import java.lang.Exception;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
@@ -71,6 +75,7 @@ public class PhotoDataAdapter implements PhotoPage.Model {
private static final int BIT_SCREEN_NAIL = 1;
private static final int BIT_FULL_IMAGE = 2;
+ private static final int BIT_GIF_ANIMATION = 3;
private static final long NOTIFY_DIRTY_WAIT_TIME = 10;
// sImageFetchSeq is the fetching sequence for images.
@@ -91,7 +96,7 @@ public class PhotoDataAdapter implements PhotoPage.Model {
static {
int k = 0;
- sImageFetchSeq = new ImageFetch[1 + (IMAGE_CACHE_SIZE - 1) * 2 + 3];
+ sImageFetchSeq = new ImageFetch[1 + (IMAGE_CACHE_SIZE - 1) * 2 + 4];
sImageFetchSeq[k++] = new ImageFetch(0, BIT_SCREEN_NAIL);
for (int i = 1; i < IMAGE_CACHE_SIZE; ++i) {
@@ -102,6 +107,7 @@ public class PhotoDataAdapter implements PhotoPage.Model {
sImageFetchSeq[k++] = new ImageFetch(0, BIT_FULL_IMAGE);
sImageFetchSeq[k++] = new ImageFetch(1, BIT_FULL_IMAGE);
sImageFetchSeq[k++] = new ImageFetch(-1, BIT_FULL_IMAGE);
+ sImageFetchSeq[k++] = new ImageFetch(0, BIT_GIF_ANIMATION);
}
private final TileImageViewAdapter mTileProvider = new TileImageViewAdapter();
@@ -160,6 +166,7 @@ public class PhotoDataAdapter implements PhotoPage.Model {
private boolean mNeedFullImage;
private int mFocusHintDirection = FOCUS_HINT_NEXT;
private Path mFocusHintPath = null;
+ private AbstractGalleryActivity mActivity;
// If Bundle is from widget, it's true, otherwise it's false.
private boolean mIsFromWidget = false;
@@ -181,6 +188,7 @@ public class PhotoDataAdapter implements PhotoPage.Model {
public PhotoDataAdapter(AbstractGalleryActivity activity, PhotoView view,
MediaSet mediaSet, Path itemPath, int indexHint, int cameraIndex,
boolean isPanorama, boolean isStaticCamera) {
+ mActivity = activity;
mSource = Utils.checkNotNull(mediaSet);
mPhotoView = Utils.checkNotNull(view);
mItemPath = Utils.checkNotNull(itemPath);
@@ -470,6 +478,8 @@ public class PhotoDataAdapter implements PhotoPage.Model {
ImageEntry entry = mImageCache.get(item.getPath());
if (entry == null) return null;
+ ScreenNail targetScreenNail = getTargetScreenNail(entry);
+ if (targetScreenNail != null) return targetScreenNail;
// Create a default ScreenNail if the real one is not available yet,
// except for camera that a black screen is better than a gray tile.
if (entry.screenNail == null && !isCamera(offset)) {
@@ -631,7 +641,7 @@ public class PhotoDataAdapter implements PhotoPage.Model {
}
private void updateTileProvider(ImageEntry entry) {
- ScreenNail screenNail = entry.screenNail;
+ ScreenNail screenNail = getTargetScreenNail(entry);
BitmapRegionDecoder fullImage = entry.fullImage;
if (screenNail != null) {
if (fullImage != null) {
@@ -648,6 +658,15 @@ public class PhotoDataAdapter implements PhotoPage.Model {
}
}
+
+ private ScreenNail getTargetScreenNail(ImageEntry entry) {
+ if (null == entry) return null;
+ if (null != entry.currentGifFrame){
+ return entry.currentGifFrame;
+ }
+ return entry.screenNail;
+ }
+
private void updateSlidingWindow() {
// 1. Update the image window
int start = Utils.clamp(mCurrentIndex - IMAGE_CACHE_SIZE / 2,
@@ -733,6 +752,12 @@ public class PhotoDataAdapter implements PhotoPage.Model {
entry.fullImageTask = null;
entry.requestedFullImage = MediaObject.INVALID_DATA_VERSION;
}
+
+ if (entry.gifDecoderTask != null && entry.gifDecoderTask != task) {
+ entry.gifDecoderTask.cancel();
+ entry.gifDecoderTask = null;
+ entry.requestedGif = MediaObject.INVALID_DATA_VERSION;
+ }
}
}
@@ -782,6 +807,23 @@ public class PhotoDataAdapter implements PhotoPage.Model {
}
}
+
+ private class GifDecoderJob implements Job<GifDecoder> {
+ private MediaItem mItem;
+
+ public GifDecoderJob(MediaItem item) {
+ mItem = item;
+ }
+
+ @Override
+ public GifDecoder run(JobContext jc) {
+ if (isTemporaryItem(mItem)) {
+ return null;
+ }
+ return new GifRequest(mItem.getContentUri(), mActivity).run(jc);
+ }
+ }
+
// Returns true if we think this is a temporary item created by Camera. A
// temporary item is an image or a video whose data is still being
// processed, but an incomplete entry is created first in MediaProvider, so
@@ -830,6 +872,9 @@ public class PhotoDataAdapter implements PhotoPage.Model {
} else if (which == BIT_FULL_IMAGE && entry.fullImageTask != null
&& entry.requestedFullImage == version) {
return entry.fullImageTask;
+ } else if (which == BIT_GIF_ANIMATION && entry.gifDecoderTask != null
+ && entry.requestedGif == version) {
+ return entry.gifDecoderTask;
}
if (which == BIT_SCREEN_NAIL && entry.requestedScreenNail != version) {
@@ -850,6 +895,18 @@ public class PhotoDataAdapter implements PhotoPage.Model {
// request full image
return entry.fullImageTask;
}
+
+ if (which == BIT_GIF_ANIMATION
+ && (entry.requestedGif != version)
+ && isGif(0)) {
+ entry.requestedGif = version;
+ entry.gifDecoderTask = mThreadPool.submit(
+ new GifDecoderJob(item),
+ new GifDecoderListener(item.getPath()));
+ // request gif decoder
+ return entry.gifDecoderTask;
+ }
+
return null;
}
@@ -879,6 +936,20 @@ public class PhotoDataAdapter implements PhotoPage.Model {
item.getWidth(), item.getHeight());
}
}
+
+ if (Math.abs(i - mCurrentIndex) > 0) {
+ if (entry.gifDecoderTask != null) {
+ entry.gifDecoderTask.cancel();
+ entry.gifDecoderTask = null;
+ }
+ entry.gifDecoder = null;
+ entry.requestedGif = MediaItem.INVALID_DATA_VERSION;
+ if (null != entry.currentGifFrame) {
+ //recycle cached gif frame
+ entry.currentGifFrame.recycle();
+ entry.currentGifFrame = null;
+ }
+ }
} else {
entry = new ImageEntry();
mImageCache.put(path, entry);
@@ -940,6 +1011,158 @@ public class PhotoDataAdapter implements PhotoPage.Model {
}
}
+ private class GifDecoderListener
+ implements Runnable, FutureListener<GifDecoder> {
+ private final Path mPath;
+ private Future<GifDecoder> mFuture;
+
+ public GifDecoderListener(Path path) {
+ mPath = path;
+ }
+
+ @Override
+ public void onFutureDone(Future<GifDecoder> future) {
+ mFuture = future;
+ if (null != mFuture.get()) {
+ mMainHandler.sendMessage(
+ mMainHandler.obtainMessage(MSG_RUN_OBJECT, this));
+ }
+ }
+
+ @Override
+ public void run() {
+ updateGifDecoder(mPath, mFuture);
+ }
+ }
+
+ private void updateGifDecoder(Path path,
+ Future<GifDecoder> future) {
+
+ ImageEntry entry = mImageCache.get(path);
+ if (entry == null || entry.gifDecoderTask != future) {
+ return;
+ }
+
+ entry.gifDecoderTask = null;
+ entry.gifDecoder = future.get();
+
+ playGif(path);
+ updateImageRequests();
+
+ }
+
+ private void playGif(Path path) {
+ ImageEntry entry = mImageCache.get(path);
+ if (null == entry) return;
+ if (entry.gifDecoder != null && entry.gifDecoder.getFrameCount() != 0) {
+ if (entry.gifDecoder.mWidth <= 0 || entry.gifDecoder.mHeight <= 0) {
+ return;
+ }
+
+ int currentIndex = mCurrentIndex;
+ if (path == getPath(currentIndex)) {
+ GifEntry gifEntry = new GifEntry();
+ gifEntry.gifDecoder = entry.gifDecoder;
+ gifEntry.animatedIndex = currentIndex;
+ gifEntry.entry = entry;
+
+ mMainHandler.sendMessage(
+ mMainHandler.obtainMessage(MSG_RUN_OBJECT,
+ new GifRunnable(path, gifEntry)));
+ }
+ }
+ }
+
+ private class GifRunnable implements Runnable {
+
+ private GifEntry mGifEntry;
+ private Path mPath;
+
+ private void free() {
+ if (null != mGifEntry.gifDecoder) {
+ mGifEntry.gifDecoder.free();
+ mGifEntry.gifDecoder = null;
+ }
+
+ if (null != mGifEntry) {
+ mGifEntry = null;
+ }
+ }
+
+ public GifRunnable(Path path, GifEntry gifEntry) {
+ mPath = path;
+ mGifEntry = gifEntry;
+ if (null == mGifEntry || null == mGifEntry.gifDecoder) {
+ free();
+ return;
+ }
+ boolean imageChanged = mGifEntry.animatedIndex != mCurrentIndex;
+ MediaItem item = getMediaItem(0);
+ Path currentPath = (item != null ? item.getPath() : null);
+ imageChanged |= path != currentPath;
+ if (imageChanged) {
+ free();
+ return;
+ }
+ mGifEntry.currentFrame = 0;
+ mGifEntry.totalFrameCount = mGifEntry.gifDecoder.getFrameCount();
+ if (mGifEntry.totalFrameCount <= 1) {
+ free();
+ return;
+ }
+ }
+
+ @Override
+ public void run() {
+ if (!mIsActive) {
+ free();
+ return;
+ }
+
+ if (null == mGifEntry || null == mGifEntry.gifDecoder) {
+ free();
+ return;
+ }
+
+ boolean imageChanged = mGifEntry.animatedIndex != mCurrentIndex;
+ MediaItem item = getMediaItem(0);
+ Path currentPath = (item != null ? item.getPath() : null);
+ imageChanged |= mPath != currentPath;
+ if (imageChanged) {
+ free();
+ return;
+ }
+
+ Bitmap frameBitmap = mGifEntry.gifDecoder.getFrameImage(mGifEntry.currentFrame);
+ if (null == frameBitmap) {
+ free();
+ return;
+ }
+ long delay = (long) mGifEntry.gifDecoder.getDelay(mGifEntry.currentFrame);
+ mGifEntry.currentFrame = (mGifEntry.currentFrame + 1) % mGifEntry.totalFrameCount;
+
+ ScreenNail gifFrame = new BitmapScreenNail(frameBitmap);
+ if (mGifEntry.entry.currentGifFrame != null) {
+ mGifEntry.entry.currentGifFrame.recycle();
+ mGifEntry.entry.currentGifFrame = null;
+ }
+ mGifEntry.entry.currentGifFrame = gifFrame;
+ updateTileProvider(mGifEntry.entry);
+ mPhotoView.notifyImageChange(0);
+ mMainHandler.sendMessageDelayed(
+ mMainHandler.obtainMessage(MSG_RUN_OBJECT, this), delay);
+ }
+ }
+
+
+ private static class GifEntry {
+ public ImageEntry entry;
+ public GifDecoder gifDecoder;
+ public int animatedIndex;
+ public int currentFrame;
+ public int totalFrameCount;
+ }
+
private static class ImageEntry {
public BitmapRegionDecoder fullImage;
public ScreenNail screenNail;
@@ -948,6 +1171,11 @@ public class PhotoDataAdapter implements PhotoPage.Model {
public long requestedScreenNail = MediaObject.INVALID_DATA_VERSION;
public long requestedFullImage = MediaObject.INVALID_DATA_VERSION;
public boolean failToLoad = false;
+
+ public GifDecoder gifDecoder;
+ public Future<GifDecoder> gifDecoderTask;
+ public ScreenNail currentGifFrame;
+ public long requestedGif = MediaObject.INVALID_DATA_VERSION;
}
private class SourceListener implements ContentListener {
diff --git a/src/com/android/gallery3d/app/PhotoPage.java b/src/com/android/gallery3d/app/PhotoPage.java
index deb3b855c..7bda6dc16 100644
--- a/src/com/android/gallery3d/app/PhotoPage.java
+++ b/src/com/android/gallery3d/app/PhotoPage.java
@@ -78,7 +78,6 @@ import com.android.gallery3d.ui.SelectionManager;
import com.android.gallery3d.ui.SynchronizedHandler;
import com.android.gallery3d.util.GalleryUtils;
import com.android.gallery3d.util.UsageStatistics;
-import com.android.gallery3d.util.ViewGifImage;
import java.util.ArrayList;
import java.util.Locale;
@@ -1275,10 +1274,6 @@ public abstract class PhotoPage extends ActivityState implements
// item is not ready or it is camera preview, ignore
return;
}
- if (item.getMimeType().equals(MediaItem.MIME_TYPE_GIF)) {
- viewAnimateGif((Activity) mActivity, item.getContentUri());
- return;
- }
int supported = item.getSupportedOperations();
boolean playVideo = ((supported & MediaItem.SUPPORT_PLAY) != 0);
@@ -1738,12 +1733,4 @@ public abstract class PhotoPage extends ActivityState implements
}
}
- private static void viewAnimateGif(Activity activity, Uri uri) {
- Intent intent = new Intent(ViewGifImage.VIEW_GIF_ACTION, uri);
- String scheme = uri.getScheme();
- if ("file".equals(scheme)) {
- intent.setDataAndType(uri, "image/gif");
- }
- activity.startActivity(intent);
- }
}
diff --git a/src/com/android/gallery3d/app/TimeLineDataLoader.java b/src/com/android/gallery3d/app/TimeLineDataLoader.java
index 7816c2943..bd2193ff9 100755..100644
--- a/src/com/android/gallery3d/app/TimeLineDataLoader.java
+++ b/src/com/android/gallery3d/app/TimeLineDataLoader.java
@@ -39,7 +39,6 @@ public class TimeLineDataLoader {
@SuppressWarnings("unused")
private static final String TAG = "TimeLineDataLoader";
private static final int DATA_CACHE_SIZE = 1000;
- private boolean mNewVersion = false;
private static final int MSG_LOAD_START = 1;
private static final int MSG_LOAD_FINISH = 2;
@@ -54,18 +53,15 @@ public class TimeLineDataLoader {
public static interface DataListener {
public void onContentChanged(int index);
- public void onSizeChanged(int size);
- public void onVersionChanged();
+ public void onSizeChanged();
}
-
private int mActiveStart = 0;
private int mActiveEnd = 0;
private int mContentStart = 0;
private int mContentEnd = 0;
- private ArrayList<MediaItem> mTotalMediaItems;
private final MediaSet mSource;
private long mSourceVersion = MediaObject.INVALID_DATA_VERSION;
@@ -122,9 +118,8 @@ public class TimeLineDataLoader {
mSource.removeContentListener(mSourceListener);
}
-
public MediaSet getMediaSet(int index) {
- MediaSet mediaSet = ((ClusterAlbumSet)mSource).getAlbumFromindex(index);
+ MediaSet mediaSet = ((ClusterAlbumSet)mSource).getAlbumFromindex(index);
return mediaSet;
}
@@ -139,10 +134,6 @@ public class TimeLineDataLoader {
return ((ClusterAlbumSet) mSource).getSubMediaSetCount();
}
- public ArrayList<MediaItem> getAllMediaItems() {
- return mTotalMediaItems;
- }
-
public int getActiveStart() {
return mActiveStart;
}
@@ -155,6 +146,16 @@ public class TimeLineDataLoader {
return mSize;
}
+ public int[] getSubMediaSetCount() {
+ ClusterAlbumSet set = (ClusterAlbumSet) mSource;
+ int albumCount = set.getSubMediaSetCount();
+ int[] counts = new int[albumCount];
+ for (int i = albumCount - 1; i >= 0; --i) {
+ counts[i] = set.getSubMediaSet(i).getSelectableItemCount();
+ }
+ return counts;
+ }
+
// Returns the index of the MediaItem with the given path or
// -1 if the path is not cached
public int findItem(Path id) {
@@ -298,13 +299,10 @@ public class TimeLineDataLoader {
@Override
public Void call() throws Exception {
UpdateInfo info = mUpdateInfo;
- if ( info.version != mSourceVersion) {
- mNewVersion = true;
- }
mSourceVersion = info.version;
if (mSize != info.size) {
mSize = info.size;
- if (mDataListener != null) mDataListener.onSizeChanged(mSize);
+ if (mDataListener != null) mDataListener.onSizeChanged();
if (mContentEnd > mSize) mContentEnd = mSize;
if (mActiveEnd > mSize) mActiveEnd = mSize;
}
@@ -370,12 +368,13 @@ public class TimeLineDataLoader {
@Override
public void run() {
-
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
boolean updateComplete = false;
+ long version = MediaObject.INVALID_DATA_VERSION;
while (mActive) {
synchronized (this) {
- if (mActive && !mDirty && updateComplete) {
+ if (mActive && !mDirty && updateComplete
+ && version != MediaObject.INVALID_DATA_VERSION) {
updateLoading(false);
if (mFailedVersion != MediaObject.INVALID_DATA_VERSION) {
}
@@ -387,7 +386,7 @@ public class TimeLineDataLoader {
mDirty = false;
}
updateLoading(true);
- long version = mSource.reload();
+ version = mSource.reload();
UpdateInfo info = executeAndWait(new GetUpdateInfo(version));
updateComplete = info == null;
if (updateComplete) {
@@ -402,11 +401,6 @@ public class TimeLineDataLoader {
}
executeAndWait(new UpdateContent(info));
- if (mNewVersion) {
- mNewVersion = false;
- mTotalMediaItems = mSource.getMediaItem(0, mSource.getMediaItemCount());
- mDataListener.onVersionChanged();
- }
}
updateLoading(false);
}
diff --git a/src/com/android/gallery3d/app/TimeLinePage.java b/src/com/android/gallery3d/app/TimeLinePage.java
index 618f219f4..618f219f4 100755..100644
--- a/src/com/android/gallery3d/app/TimeLinePage.java
+++ b/src/com/android/gallery3d/app/TimeLinePage.java
diff --git a/src/com/android/gallery3d/data/ClusterAlbumSet.java b/src/com/android/gallery3d/data/ClusterAlbumSet.java
index 4046a1595..33074bea2 100644
--- a/src/com/android/gallery3d/data/ClusterAlbumSet.java
+++ b/src/com/android/gallery3d/data/ClusterAlbumSet.java
@@ -32,6 +32,7 @@ public class ClusterAlbumSet extends MediaSet implements ContentListener {
private static final String TAG = "ClusterAlbumSet";
private GalleryApp mApplication;
private MediaSet mBaseSet;
+ private long mBaseDataVersion;
private int mKind;
private ArrayList<ClusterAlbum> mAlbums = new ArrayList<ClusterAlbum>();
private boolean mFirstReloadDone;
@@ -47,6 +48,7 @@ public class ClusterAlbumSet extends MediaSet implements ContentListener {
super(path, INVALID_DATA_VERSION);
mApplication = application;
mBaseSet = baseSet;
+ mBaseDataVersion = mBaseSet.getDataVersion();
mKind = kind;
baseSet.addContentListener(this);
}
@@ -68,15 +70,12 @@ public class ClusterAlbumSet extends MediaSet implements ContentListener {
@Override
public long reload() {
- synchronized(this){
- if (mBaseSet.reload() > mDataVersion) {
- if (mFirstReloadDone) {
- updateClustersContents();
- } else {
- updateClusters();
- mFirstReloadDone = true;
- }
+ synchronized (this) {
+ if (mBaseSet.reload() > mBaseDataVersion) {
+ updateClusters();
+ mFirstReloadDone = true;
mDataVersion = nextVersionNumber();
+ mBaseDataVersion = mDataVersion;
}
if (mKind == ClusterSource.CLUSTER_ALBUMSET_TIME) {
calculateTotalItemsCount();
@@ -112,7 +111,6 @@ public class ClusterAlbumSet extends MediaSet implements ContentListener {
clustering = new SizeClustering(context);
break;
}
-
clustering.run(mBaseSet);
int n = clustering.getNumberOfClusters();
DataManager dataManager = mApplication.getDataManager();
diff --git a/src/com/android/gallery3d/ui/PhotoView.java b/src/com/android/gallery3d/ui/PhotoView.java
index 6e1c662c4..228229006 100644
--- a/src/com/android/gallery3d/ui/PhotoView.java
+++ b/src/com/android/gallery3d/ui/PhotoView.java
@@ -736,7 +736,7 @@ public class PhotoView extends GLView {
canvas.translate((int) (cx + 0.5f), (int) (cy + 0.5f));
int s = (int) (scale * Math.min(r.width(), r.height()) + 0.5f);
//Full pic locates at index 0 of the array in PhotoDataAdapter
- if (mModel.isVideo(0) || mModel.isGif(0)) {
+ if (mModel.isVideo(0)) {
drawVideoPlayIcon(canvas, s);
}
if (mLoadingState == Model.LOADING_FAIL ) {
@@ -866,7 +866,7 @@ public class PhotoView extends GLView {
invalidate();
}
int s = Math.min(drawW, drawH);
- if (mModel.isVideo(mIndex) || mModel.isGif(mIndex)) {
+ if (mModel.isVideo(mIndex)) {
drawVideoPlayIcon(canvas, s);
}
diff --git a/src/com/android/gallery3d/ui/TimeLineSlidingWindow.java b/src/com/android/gallery3d/ui/TimeLineSlidingWindow.java
index 6fdd34935..5041ba683 100644
--- a/src/com/android/gallery3d/ui/TimeLineSlidingWindow.java
+++ b/src/com/android/gallery3d/ui/TimeLineSlidingWindow.java
@@ -42,9 +42,8 @@ public class TimeLineSlidingWindow implements TimeLineDataLoader.DataListener {
private static final int JOB_LIMIT = 2;
public static interface Listener {
- public void onSizeChanged(int size);
+ public void onSizeChanged(int[] size);
public void onContentChanged();
- public void onVersionChanged();
public int getTitleWidth();
}
@@ -185,10 +184,6 @@ public class TimeLineSlidingWindow implements TimeLineDataLoader.DataListener {
}
}
- public ArrayList<MediaItem> getAllMediaItems() {
- return mSource.getAllMediaItems();
- }
-
private void updateTextureUploadQueue() {
if (!mIsActive) return;
mTileUploader.clear();
@@ -355,10 +350,11 @@ public class TimeLineSlidingWindow implements TimeLineDataLoader.DataListener {
}
@Override
- public void onSizeChanged(int size) {
+ public void onSizeChanged() {
+ int size = mSource.size();
if (mSize != size) {
mSize = size;
- if (mListener != null) mListener.onSizeChanged(mSize);
+ if (mListener != null) mListener.onSizeChanged(mSource.getSubMediaSetCount());
if (mContentEnd > mSize) mContentEnd = mSize;
if (mActiveEnd > mSize) mActiveEnd = mSize;
}
@@ -377,11 +373,6 @@ public class TimeLineSlidingWindow implements TimeLineDataLoader.DataListener {
}
}
- @Override
- public void onVersionChanged() {
- mListener.onVersionChanged();
- }
-
public void resume() {
mIsActive = true;
TiledTexture.prepareResources();
diff --git a/src/com/android/gallery3d/ui/TimeLineSlotRenderer.java b/src/com/android/gallery3d/ui/TimeLineSlotRenderer.java
index adad59c01..b0a8a0cba 100644
--- a/src/com/android/gallery3d/ui/TimeLineSlotRenderer.java
+++ b/src/com/android/gallery3d/ui/TimeLineSlotRenderer.java
@@ -99,10 +99,6 @@ public class TimeLineSlotRenderer extends AbstractSlotRenderer {
: texture;
}
- public ArrayList<MediaItem> getAllMediaItems() {
- return mDataWindow.getAllMediaItems();
- }
-
protected int renderOverlay(GLCanvas canvas, int index,
TimeLineSlidingWindow.AlbumEntry entry, int width, int height) {
int renderRequestFlags = 0;
@@ -133,17 +129,12 @@ public class TimeLineSlotRenderer extends AbstractSlotRenderer {
}
@Override
- public void onSizeChanged(int size) {
+ public void onSizeChanged(int[] size) {
mSlotView.setSlotCount(size);
mSlotView.invalidate();
}
@Override
- public void onVersionChanged() {
- mSlotView.onVersionChanged();
- }
-
- @Override
public int getTitleWidth() {
return mSlotView.getTitleWidth();
}
@@ -184,14 +175,12 @@ public class TimeLineSlotRenderer extends AbstractSlotRenderer {
public void setModel(TimeLineDataLoader model) {
if (mDataWindow != null) {
mDataWindow.setListener(null);
- mSlotView.setSlotCount(0);
mDataWindow = null;
}
if (model != null) {
mDataWindow = new TimeLineSlidingWindow(mActivity, model, CACHE_SIZE, mLabelSpec,
mSelectionManager, mSlotView);
mDataWindow.setListener(new MyDataModelListener());
- mSlotView.setSlotCount(model.size());
}
}
diff --git a/src/com/android/gallery3d/ui/TimeLineSlotView.java b/src/com/android/gallery3d/ui/TimeLineSlotView.java
index dadd5ff25..5c93d31bd 100644
--- a/src/com/android/gallery3d/ui/TimeLineSlotView.java
+++ b/src/com/android/gallery3d/ui/TimeLineSlotView.java
@@ -85,9 +85,6 @@ public class TimeLineSlotView extends GLView {
public static final int OVERSCROLL_3D = 0;
- // to prevent allocating memory
- private final Rect mTempRect = new Rect();
-
// Flag to check whether it is come from Photo Page.
private boolean isFromPhotoPage = false;
@@ -105,18 +102,19 @@ public class TimeLineSlotView extends GLView {
}
public void setCenterIndex(int index) {
- int slotCount = mLayout.mSlotCount;
- if (index < 0 || index >= slotCount) {
+ int size = mLayout.getSlotSize();
+ if (index < 0 || index >= size) {
return;
}
- Rect rect = mLayout.getSlotRect(index, mTempRect);
+ Rect rect = mLayout.getSlotRect(index);
int position = (rect.top + rect.bottom - getHeight()) / 2;
setScrollPosition(position);
}
public void makeSlotVisible(int index) {
- Rect rect = mLayout.getSlotRect(index, mTempRect);
+ Rect rect = mLayout.getSlotRect(index);
+ if (rect == null) return;
int visibleBegin = mScrollY;
int visibleLength = getHeight();
int visibleEnd = visibleBegin + visibleLength;
@@ -146,13 +144,6 @@ public class TimeLineSlotView extends GLView {
public void setScrollPosition(int position) {
- /*if (View.LAYOUT_DIRECTION_RTL == TextUtils
- .getLayoutDirectionFromLocale(Locale.getDefault())
- && position == 0 && !isFromPhotoPage) {
- // If RTL and not from Photo Page, set position to max.
- position = mLayout.getScrollLimit();
- }*/
-
position = Utils.clamp(position, 0, mLayout.getScrollLimit());
mScroller.setPosition(position);
updateScrollPosition(position, false);
@@ -167,7 +158,7 @@ public class TimeLineSlotView extends GLView {
if (!changeSize) return;
mWidth = r - l;
- // Make sure we are still at a resonable scroll position after the size
+ // Make sure we are still at a reasonable scroll position after the size
// is changed (like orientation change). We choose to keep the center
// visible slot still visible. This is arbitrary but reasonable.
int visibleIndex =
@@ -181,13 +172,13 @@ public class TimeLineSlotView extends GLView {
public void startScatteringAnimation(RelativePosition position) {
mAnimation = new ScatteringAnimation(position);
mAnimation.start();
- if (mLayout.mSlotCount != 0) invalidate();
+ if (mLayout.getSlotSize() != 0) invalidate();
}
public void startRisingAnimation() {
mAnimation = new RisingAnimation();
mAnimation.start();
- if (mLayout.mSlotCount != 0) invalidate();
+ if (mLayout.getSlotSize() != 0) invalidate();
}
private void updateScrollPosition(int position, boolean force) {
@@ -203,7 +194,7 @@ public class TimeLineSlotView extends GLView {
}
public Rect getSlotRect(int slotIndex) {
- return mLayout.getSlotRect(slotIndex, new Rect());
+ return mLayout.getSlotRect(slotIndex);
}
@Override
@@ -297,7 +288,7 @@ public class TimeLineSlotView extends GLView {
private int renderItem(
GLCanvas canvas, int index, int pass, boolean paperActive) {
- Rect rect = mLayout.getSlotRect(index, mTempRect);
+ Rect rect = mLayout.getSlotRect(index);
if (rect == null) return 0;
canvas.save(GLCanvas.SAVE_FLAG_ALPHA | GLCanvas.SAVE_FLAG_MATRIX);
canvas.translate(rect.left, rect.top, 0);
@@ -364,10 +355,10 @@ public class TimeLineSlotView extends GLView {
root.lockRenderThread();
try {
if (isDown) return;
- int index = mLayout.getSlotIndexByPosition(e.getX(), e.getY());
- if (index != INDEX_NONE) {
+ Slot slot = mLayout.getSlotByPosition(e.getX(), e.getY());
+ if (slot != null) {
isDown = true;
- mListener.onDown(index);
+ mListener.onDown(slot.index);
}
} finally {
root.unlockRenderThread();
@@ -413,19 +404,11 @@ public class TimeLineSlotView extends GLView {
public boolean onSingleTapUp(MotionEvent e) {
cancelDown(false);
if (mDownInScrolling) return true;
- RectSlot slot = mLayout.getRectSlotByPosition(e.getX(), e.getY());
- if (slot == null) {
- return true;
- }
- int index = slot.slotIndex;
- if (index != INDEX_NONE) {
- if (slot.mediaType == MediaObject.MEDIA_TYPE_TIMELINE_TITLE) {
- mListener.onSingleTapUp(index, true);
- return true;
- }
- mListener.onSingleTapUp(index, false);
- }
- return true;
+ Slot slot = mLayout.getSlotByPosition(e.getX(), e.getY());
+ if (slot != null) {
+ mListener.onSingleTapUp(slot.index, slot.isTitle);
+ }
+ return true;
}
@Override
@@ -434,17 +417,9 @@ public class TimeLineSlotView extends GLView {
if (mDownInScrolling) return;
lockRendering();
try {
- RectSlot slot = mLayout.getRectSlotByPosition(e.getX(), e.getY());
- if (slot == null) return;
-
- int index = slot.slotIndex;
- if (index != INDEX_NONE) {
- if (slot.mediaType == MediaObject.MEDIA_TYPE_TIMELINE_TITLE) {
- mListener.onLongTap(index, true);
-
- } else {
- mListener.onLongTap(index, false);
- }
+ Slot slot = mLayout.getSlotByPosition(e.getX(), e.getY());
+ if (slot != null) {
+ mListener.onLongTap(slot.index, slot.isTitle);
}
} finally {
unlockRendering();
@@ -456,9 +431,8 @@ public class TimeLineSlotView extends GLView {
mStartIndex = index;
}
- // Return true if the layout parameters have been changed
- public boolean setSlotCount(int slotCount) {
- boolean changed = mLayout.setSlotCount(slotCount);
+ public void setSlotCount(int[] count) {
+ mLayout.setSlotCount(count);
// mStartIndex is applied the first time setSlotCount is called.
if (mStartIndex != INDEX_NONE) {
@@ -467,12 +441,6 @@ public class TimeLineSlotView extends GLView {
}
// Reset the scroll position to avoid scrolling over the updated limit.
setScrollPosition(mScrollY);
- return changed;
- }
-
- public void onVersionChanged() {
- mLayout.createSlots();
- invalidate();
}
public int getVisibleStart() {
@@ -522,14 +490,14 @@ public class TimeLineSlotView extends GLView {
}
public class Layout {
-
private int mVisibleStart;
private int mVisibleEnd;
- public int mSlotCount;
+ public int mSlotSize;
private int mSlotWidth;
private int mSlotHeight;
private int mSlotGap;
+ private int[] mSlotCount;
private Spec mSpec;
@@ -540,30 +508,41 @@ public class TimeLineSlotView extends GLView {
private int mContentLength;
private int mScrollPosition;
- private ArrayList<Integer> mHeightList;
- private HashMap<Integer, RectSlot> mMediaSlotMap;
-
public void setSlotSpec(TimeLineSlotView.Spec spec) {
mSpec = spec;
}
- public boolean setSlotCount(int slotCount) {
- if (slotCount == mSlotCount) return false;
- mSlotCount = slotCount;
- initLayoutParameters();
- updateVisibleSlotRange();
- return true;
+ public void setSlotCount(int[] count) {
+ mSlotCount = count;
+ if (mHeight != 0) {
+ initLayoutParameters();
+ createSlots();
+ }
}
- public Rect getSlotRect(int index, Rect rect) {
+ public int getSlotSize() {
+ return mSlotSize;
+ }
+
+ public Rect getSlotRect(int index) {
if (index >= mVisibleStart && index < mVisibleEnd && mVisibleEnd != 0) {
- RectSlot slot = getRectSlot(index);
- if (slot == null) {
- return null;
+ int height = 0, base = 0, top = 0;
+ for (int count : mSlotCount) {
+ if (index == base) {
+ return getSlotRect(getSlot(true, index, index, top));
+ }
+ top += mSpec.titleHeight;
+ ++base;
+
+ if (index >= base && index < base + count) {
+ return getSlotRect(getSlot(false, index, base, top));
+ }
+ int rows = (count + mUnitCount - 1) / mUnitCount;
+ top += mSlotHeight * rows + mSlotGap * (rows > 0 ? rows - 1 : 0);
+ base += count;
}
- return getSlotRect(slot, rect);
}
- return rect;
+ return null;
}
private void initLayoutParameters() {
@@ -577,11 +556,12 @@ public class TimeLineSlotView extends GLView {
}
private void setSize(int width, int height) {
- mWidth = width;
- mHeight = height;
- initLayoutParameters();
- createSlots();
- updateVisibleSlotRange();
+ if (width != mWidth || height != mHeight) {
+ mWidth = width;
+ mHeight = height;
+ initLayoutParameters();
+ createSlots();
+ }
}
public void setScrollPosition(int position) {
@@ -590,57 +570,30 @@ public class TimeLineSlotView extends GLView {
updateVisibleSlotRange();
}
- private Rect getSlotRect(RectSlot slot, Rect rect) {
- if (rect == null) {
- Log.e(TAG, "LAYOUT: null rect passed");
- Utils.assertTrue(false);
- }
- int x = 0;
- int y = 0;
- int w = mSlotWidth;
- int h = 0;
- if (slot.mediaType == MediaObject.MEDIA_TYPE_TIMELINE_TITLE) {
- x = 0;
- y = slot.totalHeight - (mSpec.titleHeight);
- w = mWidth;
- h = mSpec.titleHeight;
+ private Rect getSlotRect(Slot slot) {
+ int x, y, w, h;
+ if (slot.isTitle) {
+ x = 0;
+ y = slot.top;
+ w = mWidth;
+ h = mSpec.titleHeight;
} else {
- x = slot.slotCol * (mSlotWidth + mSlotGap);
- y = slot.totalHeight -(mSlotHeight);
- w = mSlotWidth;
- h = mSlotHeight;
+ x = slot.col * (mSlotWidth + mSlotGap);
+ y = slot.top;
+ w = mSlotWidth;
+ h = mSlotHeight;
}
- rect.set(x, y, x + w, y + h);
- return rect;
+ return new Rect(x, y, x + w, y + h);
}
private synchronized void updateVisibleSlotRange() {
int position = mScrollPosition;
- if(mHeightList!= null && mHeightList.size()>0 ) {
- int indexStart = Arrays.binarySearch(mHeightList.toArray(new Integer[0]), position);
- int indexEnd = Arrays.binarySearch(mHeightList.toArray(new Integer[0]), position+mHeight);
- if(indexStart<0) {
- indexStart = (indexStart * (- 1)) - 1;
- } if (indexEnd<0) {
- indexEnd = (indexEnd * (- 1)) - 1;
+ if (mSlotCount != null) {
+ Slot begin = getSlotByPosition(0, mScrollPosition, true, false),
+ end = getSlotByPosition(0, mScrollPosition + mHeight, true, true);
+ if (begin != null && end != null) {
+ setVisibleRange(begin.index, end.index);
}
-
- if (indexStart > mHeightList.size() - 1) {
- indexStart = mHeightList.size() - 1;
- }
- int startSlotIndex = mHeightList.indexOf(mHeightList.get(indexStart));
- if(indexEnd> mHeightList.size()-1) {
- indexEnd = mHeightList.size()-1;
- }
- int endSlotIndex = mHeightList.lastIndexOf(mHeightList.get(indexEnd));
-
-
- int endSlotIndexStr = mHeightList.indexOf(mHeightList.get(indexEnd));
- if(((endSlotIndex-endSlotIndexStr) % mUnitCount) == (mUnitCount-1) && (startSlotIndex>mUnitCount)) {
- startSlotIndex= startSlotIndex-mUnitCount;
- }
-
- setVisibleRange(startSlotIndex, Math.min(mSlotCount, endSlotIndex + 1));
}
}
@@ -665,133 +618,101 @@ public class TimeLineSlotView extends GLView {
return mVisibleEnd;
}
- public int getSlotIndexByPosition(float x, float y) {
- RectSlot slot = getRectSlotByPosition(x, y);
- if (slot == null) return INDEX_NONE;
-
- return slot.slotIndex;
-
+ private Slot getSlot(boolean isTitle, int index, int indexBase, int top) {
+ if (isTitle) {
+ return new Slot(true, index, 0, top);
+ } else {
+ int row = (index - indexBase) / mUnitCount;
+ return new Slot(false, index, (index - indexBase) % mUnitCount,
+ top + row * (mSlotHeight + mSlotGap));
+ }
}
- public RectSlot getRectSlotByPosition(float x, float y) {
- int absoluteX = Math.round(x);
- int absoluteY = Math.round(y) + mScrollPosition;
-
- if (absoluteX < 0 || absoluteY < 0) {
+ public Slot getSlotByPosition(float x, float y, boolean rowStart, boolean roundUp) {
+ if (x < 0 || y < 0 || mSlotCount == null) {
return null;
}
- if (absoluteY > mContentLength)
- return null;
-
- int columnIdx = absoluteX / (mSlotWidth + mSlotGap);
-
- RectSlot rectSlot;
-
- if (mHeightList != null && mHeightList.size() > 0) {
- int index = Arrays.binarySearch(mHeightList.toArray(new Integer[0]), absoluteY);
- if (index < 0) {
- index = (index * -1) - 1;
- }
- if (index >= mHeightList.size()) {
- index = mHeightList.size() - 1;
- }
- int startIndex = mHeightList.indexOf(mHeightList.get(index));
- int maxIndex = mHeightList.lastIndexOf(mHeightList.get(index));
- if (mMediaSlotMap.get(startIndex).mediaType ==
- MediaObject.MEDIA_TYPE_TIMELINE_TITLE) {
- return mMediaSlotMap.get(startIndex);
+ int pos = (int) y, index = 0, top = 0;
+ for (int count : mSlotCount) {
+ int h = mSpec.titleHeight;
+ if (pos < top + h) {
+ if (roundUp) {
+ return getSlot(false, index + 1, index, top + h);
+ } else {
+ return getSlot(true, index, index, top);
+ }
}
- for (int i = startIndex; (i < startIndex + mUnitCount) && (i <= maxIndex); i++) {
- rectSlot = mMediaSlotMap.get(i);
- if (rectSlot.slotCol == columnIdx) {
- return rectSlot;
+ top += h;
+ ++index;
+
+ int rows = (count + mUnitCount - 1) / mUnitCount;
+ h = mSlotHeight * rows + mSlotGap * (rows > 0 ? rows - 1 : 0);
+ if (pos < top + h) {
+ int row = ((int) pos - top) / (mSlotHeight + mSlotGap);
+ int col = 0;
+ if (roundUp) {
+ int idx = (row + 1) * mUnitCount;
+ if (idx > count)
+ idx = count + 1;
+ return getSlot(false, index + idx, index, top + mSlotHeight);
+ }
+ if (!rowStart) {
+ col = ((int) x) / (mSlotWidth + mSlotGap);
+ if (TextUtils.getLayoutDirectionFromLocale(Locale.getDefault())
+ == View.LAYOUT_DIRECTION_RTL) {
+ col = mUnitCount - col;
+ }
+ if (row * mUnitCount + col >= count) {
+ break;
+ }
}
+ return getSlot(false, index + row * mUnitCount + col, index, top);
}
+ top += h;
+ index += count;
+ }
+ if (roundUp) {
+ return getSlot(false, index, index, top);
}
return null;
}
- public int getScrollLimit() {
- if (mHeightList != null && mHeightList.size() > 0) {
- return Math.max(0, mContentLength -mHeight);
- }
- return 0;
+ public Slot getSlotByPosition(float x, float y) {
+ return getSlotByPosition(x, mScrollPosition + y, false, false);
}
-
+ public int getScrollLimit() {
+ return Math.max(0, mContentLength - mHeight);
+ }
public void createSlots() {
- ArrayList<MediaItem> mediaItemlist = new ArrayList<MediaItem>();
- if (mRenderer != null) {
- mediaItemlist = mRenderer.getAllMediaItems();
- }
- if (mHeightList == null) {
- mHeightList = new ArrayList<Integer>();
- }
- if (mMediaSlotMap == null) {
- mMediaSlotMap = new HashMap<Integer, RectSlot>();
- }
- mHeightList.clear();
- mMediaSlotMap.clear();
- if (mediaItemlist != null && mediaItemlist.size() > 0) {
- boolean isPrevTitle = false;
- int j = 0;
- int col = 0;
- int totalHeight = 0;
- for (int i = 0; i < mediaItemlist.size(); ++i) {
- MediaItem info = mediaItemlist.get(i);
-
- if (info.getMediaType() == MediaObject.MEDIA_TYPE_TIMELINE_TITLE) {
- totalHeight += (mSpec.titleHeight + mSlotGap);
- isPrevTitle = true;
- col = 0;
- } else {
- if (isPrevTitle) {
- j = 0;
- isPrevTitle = false;
- } else {
- ++j;
- }
- if (j % mUnitCount == 0) {
- totalHeight += (mSlotHeight + mSlotGap);
- col = 0;
- } else {
- col = j % mUnitCount;
- }
-
- }
- mHeightList.add(totalHeight);
- if (View.LAYOUT_DIRECTION_RTL == TextUtils
- .getLayoutDirectionFromLocale(Locale.getDefault())) {
- col = mUnitCount - col - 1;
- }
- RectSlot rectslot = new RectSlot(info.getMediaType(), i, col, totalHeight);
- mMediaSlotMap.put(rectslot.slotIndex, rectslot);
+ int height = 0;
+ int size = 0;
+ if (mSlotCount != null) {
+ for (int count : mSlotCount) {
+ int rows = (count + mUnitCount - 1) / mUnitCount;
+ height += mSlotHeight * rows + mSlotGap * (rows > 0 ? rows - 1 : 0);
+ size += 1 + count;
}
- mContentLength = mHeightList.get(mHeightList.size() -1);
- mSlotCount = mediaItemlist.size();
+ height += mSpec.titleHeight * mSlotCount.length;
+ mContentLength = height;
+ mSlotSize = size;
+ updateVisibleSlotRange();
}
- updateVisibleSlotRange();
- }
-
- public RectSlot getRectSlot(int slotIndex) {
- return mMediaSlotMap.get(slotIndex);
}
}
+ private static class Slot {
+ public boolean isTitle;
+ public int index;
+ public int col;
+ public int top;
-
- public static class RectSlot {
- public int mediaType;
- public int slotIndex;
- public int slotCol;
- public int totalHeight;
-
- public RectSlot(int type, int index, int col, int height) {
- mediaType = type;
- slotIndex = index;
- slotCol = col;
- totalHeight = height;
+ public Slot(boolean isTitle, int index, int col, int top) {
+ this.isTitle = isTitle;
+ this.index = index;
+ this.col = col;
+ this.top = top;
}
}
}
diff --git a/src/com/android/gallery3d/util/GIFView.java b/src/com/android/gallery3d/util/GIFView.java
deleted file mode 100644
index 6c6c49b95..000000000
--- a/src/com/android/gallery3d/util/GIFView.java
+++ /dev/null
@@ -1,234 +0,0 @@
-package com.android.gallery3d.util;
-
-import com.android.gallery3d.R;
-
-import android.content.Context;
-import android.content.ContentResolver;
-import android.content.res.AssetManager;
-import android.database.Cursor;
-//import android.drm.DrmHelper;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Rect;
-import android.net.Uri;
-import android.os.Handler;
-import android.os.Message;
-import android.util.Log;
-import android.widget.ImageView;
-import android.widget.Toast;
-
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.InputStream;
-import java.io.IOException;
-
-public class GIFView extends ImageView implements GifAction {
-
- private static final String TAG = "GIFView";
- private static final float SCALE_LIMIT = 4;
- private static final long FRAME_DELAY = 200; //milliseconds
-
- private GifDecoder mGifDecoder = null;
- private Bitmap mCurrentImage = null;
- private DrawThread mDrawThread = null;
-
- private Uri mUri;
- private Context mContext;
-
- public GIFView(Context context) {
- super(context);
- mContext = context;
- }
-
- public boolean setDrawable(Uri uri) {
- if (null == uri) {
- return false;
- }
- mUri = uri;
-
- // Let decode the GIF image from byte stream instead of file stream
-// String filepath = DrmHelper.getFilePath(mContext, mUri);
-// if (DrmHelper.isDrmFile(filepath)) {
-// byte[] bytes = DrmHelper.getDrmImageBytes(filepath);
-// DrmHelper.manageDrmLicense(mContext, this.getHandler(), filepath,
-// "image/gif");
-// if (bytes == null) {
-// return false;
-// }
-// startDecode(bytes);
-// return true;
-// }
-
- InputStream is = getInputStream(uri);
- if (is == null || (getFileSize (is) == 0)) {
- return false;
- }
- startDecode(is);
- return true;
- }
-
- private int getFileSize (InputStream is) {
- if(is == null) return 0;
-
- int size = 0;
- try {
- if (is instanceof FileInputStream) {
- FileInputStream f = (FileInputStream) is;
- size = (int) f.getChannel().size();
- } else {
- while (-1 != is.read()) {
- size++;
- }
- }
-
- } catch (IOException e) {
- Log.e(TAG, "catch exception:" + e);
- }
-
- return size;
-
- }
-
- private InputStream getInputStream (Uri uri) {
- ContentResolver cr = mContext.getContentResolver();
- InputStream input = null;
- try {
- input = cr.openInputStream(uri);
- } catch (IOException e) {
- Log.e(TAG, "catch exception:" + e);
- }
- return input;
- }
-
- private void startDecode(InputStream is) {
- freeGifDecoder();
- mGifDecoder = new GifDecoder(is, this);
- mGifDecoder.start();
- }
-
- private void startDecode(byte[] bytes) {
- freeGifDecoder();
- mGifDecoder = new GifDecoder(bytes, this);
- mGifDecoder.start();
- }
-
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
- if (mGifDecoder == null) {
- return;
- }
-
- if (mCurrentImage == null) {
- mCurrentImage = mGifDecoder.getImage();
- }
- if (mCurrentImage == null) {
- // if this gif can not be displayed, just try to show it as jpg by parsing mUri
- setImageURI(mUri);
- return;
- }
- setImageURI(null);
- int saveCount = canvas.getSaveCount();
- canvas.save();
- canvas.translate(getPaddingLeft(), getPaddingTop());
- Rect sRect = null;
- Rect dRect = null;
-
- int imageHeight = mCurrentImage.getHeight();
- int imageWidth = mCurrentImage.getWidth();
-
- int displayHeight = ViewGifImage.mDM.heightPixels;
- int displayWidth = ViewGifImage.mDM.widthPixels;
-
- int width, height;
- if (imageWidth >= displayWidth || imageHeight >= displayHeight) {
- // scale-down the image
- if (imageWidth * displayHeight > displayWidth * imageHeight) {
- width = displayWidth;
- height = (imageHeight * width) / imageWidth;
- } else {
- height = displayHeight;
- width = (imageWidth * height) / imageHeight;
- }
- } else {
- // scale-up the image
- float scale = Math.min(SCALE_LIMIT, Math.min(displayWidth / (float) imageWidth,
- displayHeight / (float) imageHeight));
- width = (int) (imageWidth * scale);
- height = (int) (imageHeight * scale);
- }
- dRect = new Rect((displayWidth - width) / 2, (displayHeight - height) / 2,
- (displayWidth + width) / 2, (displayHeight + height) / 2);
- canvas.drawBitmap(mCurrentImage, sRect, dRect, null);
- canvas.restoreToCount(saveCount);
- }
-
- public void parseOk(boolean parseStatus, int frameIndex) {
- if (parseStatus) {
- //indicates the start of a new GIF
- if (mGifDecoder != null && frameIndex == -1
- && mGifDecoder.getFrameCount() > 1) {
- if (mDrawThread != null) {
- mDrawThread = null;
- }
- mDrawThread = new DrawThread();
- mDrawThread.start();
- }
- } else {
- Log.e(TAG, "parse error");
- }
- }
-
- private Handler mRedrawHandler = new Handler() {
- public void handleMessage(Message msg) {
- invalidate();
- }
- };
-
- private class DrawThread extends Thread {
- public void run() {
- if (mGifDecoder == null) {
- return;
- }
-
- while (true) {
- if (!isShown() || mRedrawHandler == null) {
- break;
- }
- if (mGifDecoder == null) {
- return;
- }
- GifFrame frame = mGifDecoder.next();
- mCurrentImage = frame.mImage;
-
- Message msg = mRedrawHandler.obtainMessage();
- mRedrawHandler.sendMessage(msg);
- try {
- Thread.sleep(getDelay(frame));
- } catch (InterruptedException e) {
- Log.e(TAG, "catch exception:" + e);
- }
- }
- }
-
- }
-
- private long getDelay (GifFrame frame) {
- //in milliseconds
- return frame.mDelayInMs == 0 ? FRAME_DELAY : frame.mDelayInMs;
- }
-
- private void freeGifDecoder () {
- if (mGifDecoder != null) {
- mGifDecoder.free();
- mGifDecoder = null;
- }
-
- }
-
- public void freeMemory() {
- if (mDrawThread != null) {
- mDrawThread = null;
- }
- freeGifDecoder();
- }
-}
diff --git a/src/com/android/gallery3d/util/GifDecoder.java b/src/com/android/gallery3d/util/GifDecoder.java
index 4235fc5a5..1342355e6 100755
--- a/src/com/android/gallery3d/util/GifDecoder.java
+++ b/src/com/android/gallery3d/util/GifDecoder.java
@@ -7,7 +7,7 @@ import android.util.Log;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
-public class GifDecoder extends Thread {
+public class GifDecoder {
public static final int STATUS_PARSING = 0;
public static final int STATUS_FORMAT_ERROR = 1;
@@ -71,14 +71,16 @@ public class GifDecoder extends Thread {
public GifDecoder(byte[] data, GifAction act) {
mGifData = data;
mGifAction = act;
+ startDecoder();
}
public GifDecoder(InputStream is, GifAction act) {
mIS = is;
mGifAction = act;
+ startDecoder();
}
- public void run() {
+ public void startDecoder() {
if (mIS != null) {
readStream();
} else if (mGifData != null) {
@@ -295,10 +297,14 @@ public class GifDecoder extends Thread {
readContents();
if (mFrameCount < 0) {
mStatus = STATUS_FORMAT_ERROR;
- mGifAction.parseOk(false, -1);
+ if (mGifAction != null) {
+ mGifAction.parseOk(false, -1);
+ }
} else {
mStatus = STATUS_FINISH;
- mGifAction.parseOk(true, -1);
+ if (mGifAction != null) {
+ mGifAction.parseOk(true, -1);
+ }
}
}
try {
@@ -308,7 +314,9 @@ public class GifDecoder extends Thread {
}
} else {
mStatus = STATUS_OPEN_ERROR;
- mGifAction.parseOk(false, -1);
+ if (mGifAction != null) {
+ mGifAction.parseOk(false, -1);
+ }
}
return mStatus;
}
@@ -624,7 +632,9 @@ public class GifDecoder extends Thread {
mAct[mTransIndex] = save;
}
resetFrame();
- mGifAction.parseOk(true, mFrameCount);
+ if (mGifAction != null) {
+ mGifAction.parseOk(true, mFrameCount);
+ }
} catch (OutOfMemoryError e) {
Log.e("GifDecoder", ">>> log : " + e.toString());
e.printStackTrace();
diff --git a/src/com/android/gallery3d/util/GifRequest.java b/src/com/android/gallery3d/util/GifRequest.java
new file mode 100755
index 000000000..ea928ad91
--- /dev/null
+++ b/src/com/android/gallery3d/util/GifRequest.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.android.gallery3d.util;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.net.Uri;
+import android.util.Log;
+
+import com.android.gallery3d.util.ThreadPool.Job;
+import com.android.gallery3d.util.ThreadPool.JobContext;
+
+import java.io.InputStream;
+import java.io.IOException;
+
+
+public class GifRequest implements Job<GifDecoder> {
+
+ private static final String TAG = "GifRequest";
+ Uri itemUri;
+ Context mContext;
+
+ public GifRequest(Uri uri, Context context) {
+ itemUri = uri;
+ mContext = context;
+ }
+
+ private InputStream getInputStream(Uri uri) {
+ ContentResolver cr = mContext.getContentResolver();
+ InputStream input = null;
+ try {
+ input = cr.openInputStream(uri);
+ } catch (IOException e) {
+ Log.e(TAG, "catch exception:" + e);
+ }
+ return input;
+ }
+
+ @Override
+ public GifDecoder run(JobContext jc) {
+ InputStream input = getInputStream(itemUri);
+ if (input != null) {
+ return new GifDecoder(getInputStream(itemUri), null);
+ } else {
+ return null;
+ }
+ }
+
+
+}
+
diff --git a/src/com/android/gallery3d/util/ViewGifImage.java b/src/com/android/gallery3d/util/ViewGifImage.java
deleted file mode 100755
index cdd509280..000000000
--- a/src/com/android/gallery3d/util/ViewGifImage.java
+++ /dev/null
@@ -1,67 +0,0 @@
-package com.android.gallery3d.util;
-
-import com.android.gallery3d.R;
-
-import android.app.Activity;
-import android.content.res.Configuration;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
-import android.util.DisplayMetrics;
-import android.view.ViewGroup.LayoutParams;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-
-public class ViewGifImage extends Activity {
- private static final String TAG = "ViewGifImage";
- public static final String VIEW_GIF_ACTION = "com.android.gallery3d.VIEW_GIF";
-
- public static DisplayMetrics mDM;
-
- private ImageView mGifView;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.view_gif_image);
- mDM = new DisplayMetrics();
- getWindowManager().getDefaultDisplay().getMetrics(mDM);
- if (getIntent().getAction() != null
- && getIntent().getAction().equals(VIEW_GIF_ACTION)) {
- Uri gifUri = getIntent().getData();
- showGifPicture(gifUri);
- }
- }
-
- @Override
- protected void onStop() {
- super.onStop();
- finish();
- }
-
- @Override
- protected void onDestroy() {
- if (mGifView != null && mGifView instanceof GIFView) {
- ((GIFView) mGifView).freeMemory();
- mGifView = null;
- }
- super.onDestroy();
- }
-
- private void showGifPicture(Uri uri) {
- mGifView = new GIFView(this);
- ((LinearLayout) findViewById(R.id.image_absoluteLayout)).addView(mGifView,
- new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
- if (((GIFView) mGifView).setDrawable(uri)) return;
-
- finish();
-
- }
-
- @Override
- public void onConfigurationChanged(Configuration newConfig) {
- getWindowManager().getDefaultDisplay().getMetrics(mDM);
- super.onConfigurationChanged(newConfig);
- }
-}
diff --git a/src/org/codeaurora/gallery3d/ext/IContrllerOverlayExt.java b/src/org/codeaurora/gallery3d/ext/IContrllerOverlayExt.java
index da50cdffc..73bef5e86 100644
--- a/src/org/codeaurora/gallery3d/ext/IContrllerOverlayExt.java
+++ b/src/org/codeaurora/gallery3d/ext/IContrllerOverlayExt.java
@@ -5,10 +5,9 @@ package org.codeaurora.gallery3d.ext;
public interface IContrllerOverlayExt {
/**
* Show buffering state.
- * @param fullBuffer
- * @param percent
+ * @param what
*/
- void showBuffering(boolean fullBuffer, int percent);
+ void showBuffering(int what);
/**
* Clear buffering state.
*/