summaryrefslogtreecommitdiffstats
path: root/src/com/android/gallery3d/app/SinglePhotoDataAdapter.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/gallery3d/app/SinglePhotoDataAdapter.java')
-rw-r--r--src/com/android/gallery3d/app/SinglePhotoDataAdapter.java263
1 files changed, 263 insertions, 0 deletions
diff --git a/src/com/android/gallery3d/app/SinglePhotoDataAdapter.java b/src/com/android/gallery3d/app/SinglePhotoDataAdapter.java
new file mode 100644
index 000000000..00f2fe78f
--- /dev/null
+++ b/src/com/android/gallery3d/app/SinglePhotoDataAdapter.java
@@ -0,0 +1,263 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.gallery3d.app;
+
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.BitmapRegionDecoder;
+import android.graphics.Rect;
+import android.os.Handler;
+import android.os.Message;
+
+import com.android.gallery3d.common.BitmapUtils;
+import com.android.gallery3d.common.Utils;
+import com.android.gallery3d.data.MediaItem;
+import com.android.gallery3d.data.Path;
+import com.android.gallery3d.ui.BitmapScreenNail;
+import com.android.gallery3d.ui.PhotoView;
+import com.android.gallery3d.ui.ScreenNail;
+import com.android.gallery3d.ui.SynchronizedHandler;
+import com.android.gallery3d.ui.TileImageViewAdapter;
+import com.android.gallery3d.util.Future;
+import com.android.gallery3d.util.FutureListener;
+import com.android.gallery3d.util.ThreadPool;
+
+public class SinglePhotoDataAdapter extends TileImageViewAdapter
+ implements PhotoPage.Model {
+
+ private static final String TAG = "SinglePhotoDataAdapter";
+ private static final int SIZE_BACKUP = 1024;
+ private static final int MSG_UPDATE_IMAGE = 1;
+
+ private MediaItem mItem;
+ private boolean mHasFullImage;
+ private Future<?> mTask;
+ private Handler mHandler;
+
+ private PhotoView mPhotoView;
+ private ThreadPool mThreadPool;
+ private int mLoadingState = LOADING_INIT;
+ private BitmapScreenNail mBitmapScreenNail;
+
+ public SinglePhotoDataAdapter(
+ AbstractGalleryActivity activity, PhotoView view, MediaItem item) {
+ mItem = Utils.checkNotNull(item);
+ mHasFullImage = (item.getSupportedOperations() &
+ MediaItem.SUPPORT_FULL_IMAGE) != 0;
+ mPhotoView = Utils.checkNotNull(view);
+ mHandler = new SynchronizedHandler(activity.getGLRoot()) {
+ @Override
+ @SuppressWarnings("unchecked")
+ public void handleMessage(Message message) {
+ Utils.assertTrue(message.what == MSG_UPDATE_IMAGE);
+ if (mHasFullImage) {
+ onDecodeLargeComplete((ImageBundle) message.obj);
+ } else {
+ onDecodeThumbComplete((Future<Bitmap>) message.obj);
+ }
+ }
+ };
+ mThreadPool = activity.getThreadPool();
+ }
+
+ private static class ImageBundle {
+ public final BitmapRegionDecoder decoder;
+ public final Bitmap backupImage;
+
+ public ImageBundle(BitmapRegionDecoder decoder, Bitmap backupImage) {
+ this.decoder = decoder;
+ this.backupImage = backupImage;
+ }
+ }
+
+ private FutureListener<BitmapRegionDecoder> mLargeListener =
+ new FutureListener<BitmapRegionDecoder>() {
+ @Override
+ public void onFutureDone(Future<BitmapRegionDecoder> future) {
+ BitmapRegionDecoder decoder = future.get();
+ if (decoder == null) return;
+ int width = decoder.getWidth();
+ int height = decoder.getHeight();
+ BitmapFactory.Options options = new BitmapFactory.Options();
+ options.inSampleSize = BitmapUtils.computeSampleSize(
+ (float) SIZE_BACKUP / Math.max(width, height));
+ Bitmap bitmap = decoder.decodeRegion(new Rect(0, 0, width, height), options);
+ mHandler.sendMessage(mHandler.obtainMessage(
+ MSG_UPDATE_IMAGE, new ImageBundle(decoder, bitmap)));
+ }
+ };
+
+ private FutureListener<Bitmap> mThumbListener =
+ new FutureListener<Bitmap>() {
+ @Override
+ public void onFutureDone(Future<Bitmap> future) {
+ mHandler.sendMessage(
+ mHandler.obtainMessage(MSG_UPDATE_IMAGE, future));
+ }
+ };
+
+ @Override
+ public boolean isEmpty() {
+ return false;
+ }
+
+ private void setScreenNail(Bitmap bitmap, int width, int height) {
+ mBitmapScreenNail = new BitmapScreenNail(bitmap);
+ setScreenNail(mBitmapScreenNail, width, height);
+ }
+
+ private void onDecodeLargeComplete(ImageBundle bundle) {
+ try {
+ setScreenNail(bundle.backupImage,
+ bundle.decoder.getWidth(), bundle.decoder.getHeight());
+ setRegionDecoder(bundle.decoder);
+ mPhotoView.notifyImageChange(0);
+ } catch (Throwable t) {
+ Log.w(TAG, "fail to decode large", t);
+ }
+ }
+
+ private void onDecodeThumbComplete(Future<Bitmap> future) {
+ try {
+ Bitmap backup = future.get();
+ if (backup == null) {
+ mLoadingState = LOADING_FAIL;
+ return;
+ } else {
+ mLoadingState = LOADING_COMPLETE;
+ }
+ setScreenNail(backup, backup.getWidth(), backup.getHeight());
+ mPhotoView.notifyImageChange(0);
+ } catch (Throwable t) {
+ Log.w(TAG, "fail to decode thumb", t);
+ }
+ }
+
+ @Override
+ public void resume() {
+ if (mTask == null) {
+ if (mHasFullImage) {
+ mTask = mThreadPool.submit(
+ mItem.requestLargeImage(), mLargeListener);
+ } else {
+ mTask = mThreadPool.submit(
+ mItem.requestImage(MediaItem.TYPE_THUMBNAIL),
+ mThumbListener);
+ }
+ }
+ }
+
+ @Override
+ public void pause() {
+ Future<?> task = mTask;
+ task.cancel();
+ task.waitDone();
+ if (task.get() == null) {
+ mTask = null;
+ }
+ if (mBitmapScreenNail != null) {
+ mBitmapScreenNail.recycle();
+ mBitmapScreenNail = null;
+ }
+ }
+
+ @Override
+ public void moveTo(int index) {
+ 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.
+ }
+
+ @Override
+ public boolean isCamera(int offset) {
+ return false;
+ }
+
+ @Override
+ public boolean isPanorama(int offset) {
+ return false;
+ }
+
+ @Override
+ public boolean isStaticCamera(int offset) {
+ return false;
+ }
+
+ @Override
+ public boolean isVideo(int offset) {
+ return mItem.getMediaType() == MediaItem.MEDIA_TYPE_VIDEO;
+ }
+
+ @Override
+ public boolean isDeletable(int offset) {
+ return (mItem.getSupportedOperations() & MediaItem.SUPPORT_DELETE) != 0;
+ }
+
+ @Override
+ public MediaItem getMediaItem(int offset) {
+ return offset == 0 ? mItem : null;
+ }
+
+ @Override
+ public int getCurrentIndex() {
+ return 0;
+ }
+
+ @Override
+ public void setCurrentPhoto(Path path, int indexHint) {
+ // ignore
+ }
+
+ @Override
+ public void setFocusHintDirection(int direction) {
+ // ignore
+ }
+
+ @Override
+ public void setFocusHintPath(Path path) {
+ // ignore
+ }
+
+ @Override
+ public int getLoadingState(int offset) {
+ return mLoadingState;
+ }
+}