diff options
author | Chih-Chung Chang <> | 2009-04-02 21:45:14 -0700 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-04-02 21:45:14 -0700 |
commit | 3321d40ad1ad69070478e43c582d9289257cd232 (patch) | |
tree | 175cd7bf1bd6b7ddf39c557ec120f21d89be6ce7 /src | |
parent | ba27b756b9d4e3a7881ecbc110ca146d233b8be3 (diff) | |
download | LegacyCamera-3321d40ad1ad69070478e43c582d9289257cd232.zip LegacyCamera-3321d40ad1ad69070478e43c582d9289257cd232.tar.gz LegacyCamera-3321d40ad1ad69070478e43c582d9289257cd232.tar.bz2 |
AI 144377: Style fix.
Automated import of CL 144377
Diffstat (limited to 'src')
-rw-r--r-- | src/com/android/camera/ViewImage.java | 1031 |
1 files changed, 550 insertions, 481 deletions
diff --git a/src/com/android/camera/ViewImage.java b/src/com/android/camera/ViewImage.java index ff327ff..95402f0 100644 --- a/src/com/android/camera/ViewImage.java +++ b/src/com/android/camera/ViewImage.java @@ -16,8 +16,6 @@ package com.android.camera; -import com.android.camera.ImageManager.IImage; - import android.app.Activity; import android.content.Context; import android.content.Intent; @@ -58,21 +56,21 @@ public class ViewImage extends Activity implements View.OnClickListener { private ImageGetter mGetter; private Uri mSavedUri; - static final boolean sSlideShowHidesStatusBar = true; + static final boolean SLIDE_SHOW_HIDES_STATUS_BAR = true; // Choices for what adjacents to load. - static private final int[] sOrder_adjacents = new int[] { 0, 1, -1 }; - static private final int[] sOrder_slideshow = new int[] { 0 }; + private static final int[] sOrder_adjacents = new int[] {0, 1, -1}; + private static final int[] sOrder_slideshow = new int[] {0}; - private LocalHandler mHandler = new LocalHandler(); + LocalHandler mHandler = new LocalHandler(); private Random mRandom = new Random(System.currentTimeMillis()); private int [] mShuffleOrder; private boolean mUseShuffleOrder = false; private boolean mSlideShowLoop = false; - private static final int MODE_NORMAL = 1; - private static final int MODE_SLIDESHOW = 2; + static final int MODE_NORMAL = 1; + static final int MODE_SLIDESHOW = 2; private int mMode = MODE_NORMAL; private boolean mFullScreenInNormalMode; private boolean mShowActionIcons; @@ -83,7 +81,7 @@ public class ViewImage extends Activity implements View.OnClickListener { private int mSlideShowInterval; private int mLastSlideShowImage; private boolean mFirst = true; - private int mCurrentPosition = 0; + int mCurrentPosition = 0; private boolean mLayoutComplete = false; // represents which style animation to use @@ -99,16 +97,16 @@ public class ViewImage extends Activity implements View.OnClickListener { private Animation mShowNextImageViewAnimation = new AlphaAnimation(0F, 1F); private Animation mShowPrevImageViewAnimation = new AlphaAnimation(0F, 1F); - static final int sPadding = 20; - static final int sHysteresis = sPadding * 2; - static final int sBaseScrollDuration = 1000; // ms + static final int PADDING = 20; + static final int HYSTERESIS = PADDING * 2; + static final int BASE_SCROLL_DURATION = 1000; // ms - private ImageManager.IImageList mAllImages; + ImageManager.IImageList mAllImages; private int mSlideShowImageCurrent = 0; private ImageViewTouch [] mSlideShowImageViews = new ImageViewTouch[2]; - private GestureDetector mGestureDetector; + GestureDetector mGestureDetector; private ZoomButtonsController mZoomButtonsController; // Array of image views. The center view is the one the user is focused @@ -126,7 +124,7 @@ public class ViewImage extends Activity implements View.OnClickListener { private boolean mCameraReviewMode; private void updateNextPrevControls() { - boolean showPrev = mCurrentPosition > 0; + boolean showPrev = mCurrentPosition > 0; boolean showNext = mCurrentPosition < mAllImages.getCount() - 1; boolean prevIsVisible = mPrevImageView.getVisibility() == View.VISIBLE; @@ -190,7 +188,8 @@ public class ViewImage extends Activity implements View.OnClickListener { if (sup == false) { if (mMode == MODE_SLIDESHOW) { - mSlideShowImageViews[mSlideShowImageCurrent].handleTouchEvent(m); + mSlideShowImageViews[mSlideShowImageCurrent] + .handleTouchEvent(m); } else if (mMode == MODE_NORMAL) { mImageViews[1].handleTouchEvent(m); } @@ -252,7 +251,7 @@ public class ViewImage extends Activity implements View.OnClickListener { float distanceX, float distanceY) { ImageViewTouch imageView = mImageViews[1]; if (imageView.getScale() > 1F) { - imageView.postTranslate(-distanceX, -distanceY, sUseBounce); + imageView.postTranslate(-distanceX, -distanceY); imageView.center(true, true, false); } return true; @@ -290,146 +289,14 @@ public class ViewImage extends Activity implements View.OnClickListener { }; } - private boolean isPickIntent() { + boolean isPickIntent() { String action = getIntent().getAction(); - return (Intent.ACTION_PICK.equals(action) || Intent.ACTION_GET_CONTENT.equals(action)); + return (Intent.ACTION_PICK.equals(action) + || Intent.ACTION_GET_CONTENT.equals(action)); } - private static final boolean sUseBounce = false; - private static final boolean sAnimateTransitions = false; - - public static class ImageViewTouch extends ImageViewTouchBase { - private ViewImage mViewImage; - private boolean mEnableTrackballScroll; - - public ImageViewTouch(Context context) { - super(context); - mViewImage = (ViewImage) context; - } - - public ImageViewTouch(Context context, AttributeSet attrs) { - super(context, attrs); - mViewImage = (ViewImage) context; - } - - public void setEnableTrackballScroll(boolean enable) { - mEnableTrackballScroll = enable; - } - - protected void postTranslate(float dx, float dy, boolean bounceOK) { - super.postTranslate(dx, dy); - - if (!sUseBounce) { - center(true, false, false); - } - } - - protected ScrollHandler scrollHandler() { - return mViewImage.mScroller; - } - - public boolean handleTouchEvent(MotionEvent m) { - return mViewImage.mGestureDetector.onTouchEvent(m); - } - - @Override - public boolean onKeyDown(int keyCode, KeyEvent event) { - // Don't respond to arrow keys if trackball scrolling is not enabled - if (!mEnableTrackballScroll) { - if ((keyCode >= KeyEvent.KEYCODE_DPAD_UP) - && (keyCode <= KeyEvent.KEYCODE_DPAD_RIGHT)) { - return super.onKeyDown(keyCode, event); - } - } - - int current = mViewImage.mCurrentPosition; - - int nextImagePos = -2; // default no next image - try { - switch (keyCode) { - case KeyEvent.KEYCODE_DPAD_CENTER: { - if (mViewImage.isPickIntent()) { - ImageManager.IImage img = mViewImage.mAllImages.getImageAt(mViewImage.mCurrentPosition); - mViewImage.setResult(RESULT_OK, - new Intent().setData(img.fullSizeImageUri())); - mViewImage.finish(); - } - break; - } - case KeyEvent.KEYCODE_DPAD_LEFT: { - panBy(PAN_RATE, 0); - int maxOffset = (current == 0) ? 0 : sHysteresis; - if (getScale() <= 1F || isShiftedToNextImage(true, maxOffset)) { - nextImagePos = current - 1; - } else { - center(true, false, true); - } - return true; - } - case KeyEvent.KEYCODE_DPAD_RIGHT: { - panBy(-PAN_RATE, 0); - int maxOffset = (current == mViewImage.mAllImages.getCount() - 1) ? 0 : sHysteresis; - if (getScale() <= 1F || isShiftedToNextImage(false, maxOffset)) { - nextImagePos = current + 1; - } else { - center(true, false, true); - } - return true; - } - case KeyEvent.KEYCODE_DPAD_UP: { - panBy(0, PAN_RATE); - center(true, false, false); - return true; - } - case KeyEvent.KEYCODE_DPAD_DOWN: { - panBy(0, -PAN_RATE); - center(true, false, false); - return true; - } - case KeyEvent.KEYCODE_DEL: - MenuHelper.deletePhoto( - mViewImage, mViewImage.mDeletePhotoRunnable); - break; - } - } finally { - if (nextImagePos >= 0 && nextImagePos < mViewImage.mAllImages.getCount()) { - synchronized (mViewImage) { - mViewImage.setMode(MODE_NORMAL); - mViewImage.setImage(nextImagePos); - } - } else if (nextImagePos != -2) { - center(true, true, false); - } - } - - return super.onKeyDown(keyCode, event); - } - - protected boolean isShiftedToNextImage(boolean left, int maxOffset) { - boolean retval; - Bitmap bitmap = mBitmapDisplayed; - Matrix m = getImageViewMatrix(); - if (left) { - float [] t1 = new float[] { 0, 0 }; - m.mapPoints(t1); - retval = t1[0] > maxOffset; - } else { - int width = bitmap != null ? bitmap.getWidth() : getWidth(); - float [] t1 = new float[] { width, 0 }; - m.mapPoints(t1); - retval = t1[0] + maxOffset < getWidth(); - } - return retval; - } - - protected void scrollX(int deltaX) { - scrollHandler().scrollBy(deltaX, 0); - } + private static final boolean ANIMATE_TRANSITIONS = false; - protected int getScrollOffset() { - return scrollHandler().getScrollX(); - } - } static class ScrollHandler extends LinearLayout { private Runnable mFirstLayoutCompletedCallback = null; @@ -462,7 +329,7 @@ public class ViewImage extends Activity implements View.OnClickListener { int viewWidth = mWidth; int duration = viewWidth > 0 - ? sBaseScrollDuration * Math.abs(deltaX) / viewWidth + ? BASE_SCROLL_DURATION * Math.abs(deltaX) / viewWidth : 0; mScrollerHelper.startScroll(oldX, oldY, deltaX, deltaY, duration); invalidate(); @@ -471,13 +338,15 @@ public class ViewImage extends Activity implements View.OnClickListener { @Override public void computeScroll() { if (mScrollerHelper.computeScrollOffset()) { - scrollTo(mScrollerHelper.getCurrX(), mScrollerHelper.getCurrY()); + scrollTo(mScrollerHelper.getCurrX(), + mScrollerHelper.getCurrY()); postInvalidate(); // So we draw again } } @Override - protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + protected void onLayout(boolean changed, int left, int top, + int right, int bottom) { int width = right - left; int x = 0; for (View v : new View[] { @@ -485,12 +354,13 @@ public class ViewImage extends Activity implements View.OnClickListener { findViewById(R.id.image2), findViewById(R.id.image3) }) { v.layout(x, 0, x + width, bottom); - x += (width + sPadding); + x += (width + PADDING); } - findViewById(R.id.padding1).layout(width, 0, width + sPadding, bottom); - findViewById(R.id.padding2).layout(width + sPadding + width, - 0, width + sPadding + width + sPadding, bottom); + findViewById(R.id.padding1).layout( + width, 0, width + PADDING, bottom); + findViewById(R.id.padding2).layout(width + PADDING + width, + 0, width + PADDING + width + PADDING, bottom); if (changed) { mViewImage.mLayoutComplete = true; @@ -507,9 +377,11 @@ public class ViewImage extends Activity implements View.OnClickListener { public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); - if (! mCameraReviewMode) { - MenuItem item = menu.add(Menu.CATEGORY_SECONDARY, 203, 0, R.string.slide_show); - item.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { + if (!mCameraReviewMode) { + MenuItem item = menu.add(Menu.CATEGORY_SECONDARY, 203, 0, + R.string.slide_show); + item.setOnMenuItemClickListener( + new MenuItem.OnMenuItemClickListener() { public boolean onMenuItemClick(MenuItem item) { setMode(MODE_SLIDESHOW); mLastSlideShowImage = mCurrentPosition; @@ -520,13 +392,15 @@ public class ViewImage extends Activity implements View.OnClickListener { item.setIcon(android.R.drawable.ic_menu_slideshow); } - final SelectedImageGetter selectedImageGetter = new SelectedImageGetter() { + final SelectedImageGetter selectedImageGetter = + new SelectedImageGetter() { public ImageManager.IImage getCurrentImage() { return mAllImages.getImageAt(mCurrentPosition); } public Uri getCurrentImageUri() { - return mAllImages.getImageAt(mCurrentPosition).fullSizeImageUri(); + return mAllImages.getImageAt(mCurrentPosition) + .fullSizeImageUri(); } }; @@ -540,8 +414,9 @@ public class ViewImage extends Activity implements View.OnClickListener { new MenuHelper.MenuInvoker() { public void run(MenuHelper.MenuCallback cb) { setMode(MODE_NORMAL); - cb.run(selectedImageGetter.getCurrentImageUri(), selectedImageGetter.getCurrentImage()); - for (ImageViewTouchBase iv: mImageViews) { + cb.run(selectedImageGetter.getCurrentImageUri(), + selectedImageGetter.getCurrentImage()); + for (ImageViewTouchBase iv : mImageViews) { iv.recycleBitmaps(); iv.setImageBitmap(null, true); } @@ -550,8 +425,10 @@ public class ViewImage extends Activity implements View.OnClickListener { }); if (true) { - MenuItem item = menu.add(Menu.CATEGORY_SECONDARY, 203, 1000, R.string.camerasettings); - item.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { + MenuItem item = menu.add(Menu.CATEGORY_SECONDARY, 203, 1000, + R.string.camerasettings); + item.setOnMenuItemClickListener( + new MenuItem.OnMenuItemClickListener() { public boolean onMenuItemClick(MenuItem item) { Intent preferences = new Intent(); preferences.setClass(ViewImage.this, GallerySettings.class); @@ -564,8 +441,10 @@ public class ViewImage extends Activity implements View.OnClickListener { } // Hidden menu just so the shortcut will bring up the zoom controls - menu.add(Menu.CATEGORY_SECONDARY, 203, 0, R.string.camerasettings) // the string resource is a placeholder - .setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { + // the string resource is a placeholder + menu.add(Menu.CATEGORY_SECONDARY, 203, 0, R.string.camerasettings) + .setOnMenuItemClickListener( + new MenuItem.OnMenuItemClickListener() { public boolean onMenuItemClick(MenuItem item) { showOnScreenControls(); scheduleDismissOnScreenControls(); @@ -589,7 +468,7 @@ public class ViewImage extends Activity implements View.OnClickListener { mCurrentPosition -= 1; } } - for (ImageViewTouchBase iv: mImageViews) { + for (ImageViewTouchBase iv : mImageViews) { iv.setImageBitmapResetBase(null, true, true); } setImage(mCurrentPosition); @@ -602,7 +481,8 @@ public class ViewImage extends Activity implements View.OnClickListener { setMode(MODE_NORMAL); if (mImageMenuRunnable != null) { - mImageMenuRunnable.gettingReadyToOpen(menu, mAllImages.getImageAt(mCurrentPosition)); + mImageMenuRunnable.gettingReadyToOpen(menu, + mAllImages.getImageAt(mCurrentPosition)); } Uri uri = mAllImages.getImageAt(mCurrentPosition).fullSizeImageUri(); @@ -616,7 +496,7 @@ public class ViewImage extends Activity implements View.OnClickListener { if (mGetter == null) return; mDismissOnScreenControlsRunnable.run(); mGetter.cancelCurrent(); - for (ImageViewTouch iv: mImageViews) { + for (ImageViewTouch iv : mImageViews) { iv.clear(); } mFirst = true; @@ -626,244 +506,15 @@ public class ViewImage extends Activity implements View.OnClickListener { @Override public boolean onMenuItemSelected(int featureId, MenuItem item) { boolean b = super.onMenuItemSelected(featureId, item); - if (mImageMenuRunnable != null) - mImageMenuRunnable.aboutToCall(item, mAllImages.getImageAt(mCurrentPosition)); + if (mImageMenuRunnable != null) { + mImageMenuRunnable.aboutToCall(item, + mAllImages.getImageAt(mCurrentPosition)); + } return b; } - /* - * Here's the loading strategy. For any given image, load the thumbnail - * into memory and post a callback to display the resulting bitmap. - * - * Then proceed to load the full image bitmap. Three things can - * happen at this point: - * - * 1. the image fails to load because the UI thread decided - * to move on to a different image. This "cancellation" happens - * by virtue of the UI thread closing the stream containing the - * image being decoded. BitmapFactory.decodeStream returns null - * in this case. - * - * 2. the image loaded successfully. At that point we post - * a callback to the UI thread to actually show the bitmap. - * - * 3. when the post runs it checks to see if the image that was - * loaded is still the one we want. The UI may have moved on - * to some other image and if so we just drop the newly loaded - * bitmap on the floor. - */ - - interface ImageGetterCallback { - public void imageLoaded(int pos, int offset, Bitmap bitmap, boolean isThumb); - public boolean wantsThumbnail(int pos, int offset); - public boolean wantsFullImage(int pos, int offset); - public int fullImageSizeToUse(int pos, int offset); - public void completed(boolean wasCanceled); - public int [] loadOrder(); - } - - class ImageGetter { - // The thread which does the work. - private Thread mGetterThread; - - // The base position that's being retrieved. The actual images retrieved - // are this base plus each of the offets. - private int mCurrentPosition = -1; - - // The callback to invoke for each image. - private ImageGetterCallback mCB; - - // This is the loader cancelable that gets set while we're loading an image. - // If we change position we can cancel the current load using this. - private ImageManager.IGetBitmap_cancelable mLoad; - - // True if we're canceling the current load. - private boolean mCancelCurrent = false; - - // True when the therad should exit. - private boolean mDone = false; - - // True when the loader thread is waiting for work. - private boolean mReady = false; - - private void cancelCurrent() { - synchronized (this) { - if (!mReady) { - mCancelCurrent = true; - ImageManager.IGetBitmap_cancelable load = mLoad; - if (load != null) { - if (Config.LOGV) - Log.v(TAG, "canceling load object"); - load.cancel(); - } - mCancelCurrent = false; - } - } - } - - public ImageGetter() { - mGetterThread = new Thread(new Runnable() { - - private Runnable callback(final int position, final int offset, final boolean isThumb, final Bitmap bitmap) { - return new Runnable() { - public void run() { - // check for inflight callbacks that aren't applicable any longer - // before delivering them - if (!isCanceled() && position == mCurrentPosition) { - mCB.imageLoaded(position, offset, bitmap, isThumb); - } else if (bitmap != null) { - bitmap.recycle(); - } - } - }; - } - - private Runnable completedCallback(final boolean wasCanceled) { - return new Runnable() { - public void run() { - mCB.completed(wasCanceled); - } - }; - } - - public void run() { - int lastPosition = -1; - while (!mDone) { - synchronized (ImageGetter.this) { - mReady = true; - ImageGetter.this.notify(); - - if (mCurrentPosition == -1 || lastPosition == mCurrentPosition) { - try { - ImageGetter.this.wait(); - } catch (InterruptedException ex) { - continue; - } - } - - lastPosition = mCurrentPosition; - mReady = false; - } - - if (lastPosition != -1) { - int imageCount = mAllImages.getCount(); - - int [] order = mCB.loadOrder(); - for (int i = 0; i < order.length; i++) { - int offset = order[i]; - int imageNumber = lastPosition + offset; - if (imageNumber >= 0 && imageNumber < imageCount) { - ImageManager.IImage image = mAllImages.getImageAt(lastPosition + offset); - if (image == null || isCanceled()) { - break; - } - if (mCB.wantsThumbnail(lastPosition, offset)) { - if (Config.LOGV) - Log.v(TAG, "starting THUMBNAIL load at offset " + offset); - Bitmap b = image.thumbBitmap(); - mHandler.postGetterCallback(callback(lastPosition, offset, true, b)); - } - } - } - - for (int i = 0; i < order.length; i++) { - int offset = order[i]; - int imageNumber = lastPosition + offset; - if (imageNumber >= 0 && imageNumber < imageCount) { - ImageManager.IImage image = mAllImages.getImageAt(lastPosition + offset); - if (mCB.wantsFullImage(lastPosition, offset)) { - if (Config.LOGV) - Log.v(TAG, "starting FULL IMAGE load at offset " + offset); - int sizeToUse = mCB.fullImageSizeToUse(lastPosition, offset); - if (image != null && !isCanceled()) { - mLoad = image.fullSizeBitmap_cancelable(sizeToUse); - } - if (mLoad != null) { - long t1; - if (Config.LOGV) t1 = System.currentTimeMillis(); - - // The return value could be null if the - // bitmap is too big, or we cancelled it. - Bitmap b = mLoad.get(); - - if (Config.LOGV && b != null) { - long t2 = System.currentTimeMillis(); - Log.v(TAG, "loading full image for " + image.fullSizeImageUri() - + " with requested size " + sizeToUse - + " took " + (t2 - t1) - + " and returned a bitmap with size " - + b.getWidth() + " / " + b.getHeight()); - } - - mLoad = null; - if (b != null) { - if (isCanceled()) { - b.recycle(); - } else { - mHandler.postGetterCallback(callback(lastPosition, offset, false, b)); - } - } - } - } - } - } - mHandler.postGetterCallback(completedCallback(isCanceled())); - } - } - } - }); - mGetterThread.setName("ImageGettter"); - mGetterThread.start(); - } - - private boolean isCanceled() { - synchronized (this) { - return mCancelCurrent; - } - } - - public void setPosition(int position, ImageGetterCallback cb) { - synchronized (this) { - if (!mReady) { - try { - mCancelCurrent = true; - ImageManager.IGetBitmap_cancelable load = mLoad; - if (load != null) { - load.cancel(); - } - // if the thread is waiting before loading the full size - // image then this will free it up - ImageGetter.this.notify(); - ImageGetter.this.wait(); - mCancelCurrent = false; - } catch (InterruptedException ex) { - // not sure what to do here - } - } - } - - mCurrentPosition = position; - mCB = cb; - - synchronized (this) { - ImageGetter.this.notify(); - } - } - - public void stop() { - synchronized (this) { - mDone = true; - ImageGetter.this.notify(); - } - try { - mGetterThread.join(); - } catch (InterruptedException ex) { - - } - } - } - private void setImage(int pos) { + void setImage(int pos) { if (!mLayoutComplete) return; final boolean left = (pos == mCurrentPosition - 1); @@ -896,21 +547,21 @@ public class ViewImage extends Activity implements View.OnClickListener { ivtb.dump(); } - for (ImageViewTouchBase ivt: mImageViews) { + for (ImageViewTouchBase ivt : mImageViews) { ivt.mIsZooming = false; } int width = mImageViews[1].getWidth(); int from; - int to = width + sPadding; + int to = width + PADDING; if (mFirst) { from = to; mFirst = false; } else { - from = left ? (width + sPadding) + mScroller.getScrollX() - : mScroller.getScrollX() - (width + sPadding); + from = left ? (width + PADDING) + mScroller.getScrollX() + : mScroller.getScrollX() - (width + PADDING); } - if (sAnimateTransitions) { + if (ANIMATE_TRANSITIONS) { mScroller.scrollTo(from, 0); animateScrollTo(to, 0); } else { @@ -943,9 +594,9 @@ public class ViewImage extends Activity implements View.OnClickListener { public int fullImageSizeToUse(int pos, int offset) { // TODO - // this number should be bigger so that we can zoom. we may need to - // get fancier and read in the fuller size image as the user starts - // to zoom. use -1 to get the full full size image. + // this number should be bigger so that we can zoom. we may + // need to get fancier and read in the fuller size image as the + // user starts to zoom. use -1 to get the full full size image. // for now use 480 so we don't run out of memory final int imageViewSize = 480; return imageViewSize; @@ -955,7 +606,8 @@ public class ViewImage extends Activity implements View.OnClickListener { return sOrder_adjacents; } - public void imageLoaded(int pos, int offset, Bitmap bitmap, boolean isThumb) { + public void imageLoaded(int pos, int offset, Bitmap bitmap, + boolean isThumb) { // shouldn't get here after onPause() ImageViewTouchBase ivt = mImageViews[1 + offset]; if (offset == 0) updateZoomButtonsEnabled(); @@ -976,9 +628,12 @@ public class ViewImage extends Activity implements View.OnClickListener { public void onCreate(Bundle instanceState) { super.onCreate(instanceState); Intent intent = getIntent(); - mCameraReviewMode = intent.getBooleanExtra("com.android.camera.ReviewMode", false); - mFullScreenInNormalMode = intent.getBooleanExtra(MediaStore.EXTRA_FULL_SCREEN, true); - mShowActionIcons = intent.getBooleanExtra(MediaStore.EXTRA_SHOW_ACTION_ICONS, false); + mCameraReviewMode = intent.getBooleanExtra( + "com.android.camera.ReviewMode", false); + mFullScreenInNormalMode = intent.getBooleanExtra( + MediaStore.EXTRA_FULL_SCREEN, true); + mShowActionIcons = intent.getBooleanExtra( + MediaStore.EXTRA_SHOW_ACTION_ICONS, false); setRequestedOrientation(); @@ -992,11 +647,11 @@ public class ViewImage extends Activity implements View.OnClickListener { mImageViews[1] = (ImageViewTouch) findViewById(R.id.image2); mImageViews[2] = (ImageViewTouch) findViewById(R.id.image3); - for(ImageViewTouch v : mImageViews) { + for (ImageViewTouch v : mImageViews) { v.setEnableTrackballScroll(!mShowActionIcons); } - mScroller = (ScrollHandler)findViewById(R.id.scroller); + mScroller = (ScrollHandler) findViewById(R.id.scroller); makeGetter(); mAnimationIndex = -1; @@ -1013,8 +668,10 @@ public class ViewImage extends Activity implements View.OnClickListener { makeOutAnimation(R.anim.slide_out_vertical), }; - mSlideShowImageViews[0] = (ImageViewTouch) findViewById(R.id.image1_slideShow); - mSlideShowImageViews[1] = (ImageViewTouch) findViewById(R.id.image2_slideShow); + mSlideShowImageViews[0] = + (ImageViewTouch) findViewById(R.id.image1_slideShow); + mSlideShowImageViews[1] = + (ImageViewTouch) findViewById(R.id.image2_slideShow); for (ImageViewTouch v : mSlideShowImageViews) { v.setImageBitmapResetBase(null, true, true); v.setVisibility(View.INVISIBLE); @@ -1024,17 +681,18 @@ public class ViewImage extends Activity implements View.OnClickListener { mActionIconPanel = findViewById(R.id.action_icon_panel); { int[] pickIds = {R.id.attach, R.id.cancel}; - int[] normalIds = {R.id.gallery, R.id.setas, R.id.share, R.id.discard}; + int[] normalIds = {R.id.gallery, R.id.setas, R.id.share, + R.id.discard}; int[] hideIds = pickIds; int[] connectIds = normalIds; if (isPickIntent()) { hideIds = normalIds; connectIds = pickIds; } - for(int id : hideIds) { + for (int id : hideIds) { mActionIconPanel.findViewById(id).setVisibility(View.GONE); } - for(int id : connectIds) { + for (int id : connectIds) { View view = mActionIconPanel.findViewById(id); view.setOnClickListener(this); Animation animation = new AlphaAnimation(0F, 1F); @@ -1047,8 +705,9 @@ public class ViewImage extends Activity implements View.OnClickListener { Uri uri = getIntent().getData(); - if (Config.LOGV) + if (Config.LOGV) { Log.v(TAG, "uri is " + uri); + } if (instanceState != null) { if (instanceState.containsKey("uri")) { uri = Uri.parse(instanceState.getString("uri")); @@ -1062,13 +721,16 @@ public class ViewImage extends Activity implements View.OnClickListener { Bundle b = getIntent().getExtras(); - boolean slideShow = b != null ? b.getBoolean("slideshow", false) : false; + boolean slideShow = (b != null) + ? b.getBoolean("slideshow", false) + : false; if (slideShow) { setMode(MODE_SLIDESHOW); loadNextImage(mCurrentPosition, 0, true); } else { if (mFullScreenInNormalMode) { - getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); + getWindow().addFlags( + WindowManager.LayoutParams.FLAG_FULLSCREEN); } if (mShowActionIcons) { mActionIconPanel.setVisibility(View.VISIBLE); @@ -1093,7 +755,8 @@ public class ViewImage extends Activity implements View.OnClickListener { private void setRequestedOrientation() { Intent intent = getIntent(); if (intent.hasExtra(MediaStore.EXTRA_SCREEN_ORIENTATION)) { - int orientation = intent.getIntExtra(MediaStore.EXTRA_SCREEN_ORIENTATION, + int orientation = intent.getIntExtra( + MediaStore.EXTRA_SCREEN_ORIENTATION, ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); if (orientation != getRequestedOrientation()) { setRequestedOrientation(orientation); @@ -1113,23 +776,25 @@ public class ViewImage extends Activity implements View.OnClickListener { return outAnimation; } - private void setMode(int mode) { + void setMode(int mode) { if (mMode == mode) { return; } - findViewById(R.id.slideShowContainer).setVisibility(mode == MODE_SLIDESHOW ? View.VISIBLE : View.GONE); - findViewById(R.id.abs) .setVisibility(mode == MODE_NORMAL ? View.VISIBLE : View.GONE); + findViewById(R.id.slideShowContainer).setVisibility( + mode == MODE_SLIDESHOW ? View.VISIBLE : View.GONE); + findViewById(R.id.abs).setVisibility(mode == MODE_NORMAL + ? View.VISIBLE : View.GONE); Window win = getWindow(); mMode = mode; if (mode == MODE_SLIDESHOW) { win.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); - if (sSlideShowHidesStatusBar) { + if (SLIDE_SHOW_HIDES_STATUS_BAR) { win.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); } - for (ImageViewTouchBase ivt: mImageViews) { + for (ImageViewTouchBase ivt : mImageViews) { ivt.clear(); } mActionIconPanel.setVisibility(View.GONE); @@ -1142,16 +807,20 @@ public class ViewImage extends Activity implements View.OnClickListener { } findViewById(R.id.slideShowContainer).getRootView().requestLayout(); - mUseShuffleOrder = mPrefs.getBoolean("pref_gallery_slideshow_shuffle_key", false); - mSlideShowLoop = mPrefs.getBoolean("pref_gallery_slideshow_repeat_key", false); + mUseShuffleOrder = mPrefs.getBoolean( + "pref_gallery_slideshow_shuffle_key", false); + mSlideShowLoop = mPrefs.getBoolean( + "pref_gallery_slideshow_repeat_key", false); try { - mAnimationIndex = Integer.parseInt(mPrefs.getString("pref_gallery_slideshow_transition_key", "0")); + mAnimationIndex = Integer.parseInt(mPrefs.getString( + "pref_gallery_slideshow_transition_key", "0")); } catch (Exception ex) { Log.e(TAG, "couldn't parse preference: " + ex.toString()); mAnimationIndex = 0; } try { - mSlideShowInterval = Integer.parseInt(mPrefs.getString("pref_gallery_slideshow_interval_key", "3")) * 1000; + mSlideShowInterval = Integer.parseInt(mPrefs.getString( + "pref_gallery_slideshow_interval_key", "3")) * 1000; } catch (Exception ex) { Log.e(TAG, "couldn't parse preference: " + ex.toString()); mSlideShowInterval = 3000; @@ -1168,8 +837,10 @@ public class ViewImage extends Activity implements View.OnClickListener { generateShuffleOrder(); } } else { - if (Config.LOGV) - Log.v(TAG, "slide show mode off, mCurrentPosition == " + mCurrentPosition); + if (Config.LOGV) { + Log.v(TAG, "slide show mode off, mCurrentPosition == " + + mCurrentPosition); + } win.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); if (mFullScreenInNormalMode) { win.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); @@ -1177,10 +848,11 @@ public class ViewImage extends Activity implements View.OnClickListener { win.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); } - if (mGetter != null) + if (mGetter != null) { mGetter.cancelCurrent(); + } - if (sSlideShowHidesStatusBar) { + if (SLIDE_SHOW_HIDES_STATUS_BAR) { win.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); } if (mShowActionIcons) { @@ -1192,7 +864,7 @@ public class ViewImage extends Activity implements View.OnClickListener { dst.mLastXTouchPos = -1; dst.mLastYTouchPos = -1; - for (ImageViewTouchBase ivt: mSlideShowImageViews) { + for (ImageViewTouchBase ivt : mSlideShowImageViews) { ivt.clear(); } @@ -1211,7 +883,8 @@ public class ViewImage extends Activity implements View.OnClickListener { } private void generateShuffleOrder() { - if (mShuffleOrder == null || mShuffleOrder.length != mAllImages.getCount()) { + if (mShuffleOrder == null + || mShuffleOrder.length != mAllImages.getCount()) { mShuffleOrder = new int[mAllImages.getCount()]; } @@ -1227,7 +900,8 @@ public class ViewImage extends Activity implements View.OnClickListener { } } - private void loadNextImage(final int requestedPos, final long delay, final boolean firstCall) { + private void loadNextImage(final int requestedPos, final long delay, + final boolean firstCall) { if (firstCall && mUseShuffleOrder) { generateShuffleOrder(); } @@ -1254,27 +928,34 @@ public class ViewImage extends Activity implements View.OnClickListener { return 480; // TODO compute this } - public void imageLoaded(final int pos, final int offset, final Bitmap bitmap, final boolean isThumb) { - long timeRemaining = Math.max(0, targetDisplayTime - System.currentTimeMillis()); + public void imageLoaded(final int pos, final int offset, + final Bitmap bitmap, final boolean isThumb) { + long timeRemaining = Math.max(0, + targetDisplayTime - System.currentTimeMillis()); mHandler.postDelayedGetterCallback(new Runnable() { public void run() { if (mMode == MODE_NORMAL) return; - ImageViewTouchBase oldView = mSlideShowImageViews[mSlideShowImageCurrent]; + ImageViewTouchBase oldView = + mSlideShowImageViews[mSlideShowImageCurrent]; - if (++mSlideShowImageCurrent == mSlideShowImageViews.length) { + if (++mSlideShowImageCurrent + == mSlideShowImageViews.length) { mSlideShowImageCurrent = 0; } - ImageViewTouchBase newView = mSlideShowImageViews[mSlideShowImageCurrent]; + ImageViewTouchBase newView = + mSlideShowImageViews[mSlideShowImageCurrent]; newView.setVisibility(View.VISIBLE); - newView.setImageBitmapResetBase(bitmap, isThumb, isThumb); + newView.setImageBitmapResetBase(bitmap, isThumb, + isThumb); newView.bringToFront(); int animation = 0; if (mAnimationIndex == -1) { - int n = mRandom.nextInt(mSlideShowInAnimation.length); + int n = mRandom.nextInt( + mSlideShowInAnimation.length); animation = n; } else { animation = mAnimationIndex; @@ -1292,7 +973,8 @@ public class ViewImage extends Activity implements View.OnClickListener { mCurrentPosition = requestedPos; - if (mCurrentPosition == mLastSlideShowImage && !firstCall) { + if (mCurrentPosition == mLastSlideShowImage + && !firstCall) { if (mSlideShowLoop) { if (mUseShuffleOrder) { generateShuffleOrder(); @@ -1303,9 +985,13 @@ public class ViewImage extends Activity implements View.OnClickListener { } } - if (Config.LOGV) - Log.v(TAG, "mCurrentPosition is now " + mCurrentPosition); - loadNextImage((mCurrentPosition + 1) % mAllImages.getCount(), mSlideShowInterval, false); + if (Config.LOGV) { + Log.v(TAG, "mCurrentPosition is now " + + mCurrentPosition); + } + loadNextImage( + (mCurrentPosition + 1) % mAllImages.getCount(), + mSlideShowInterval, false); } }, timeRemaining); } @@ -1321,7 +1007,7 @@ public class ViewImage extends Activity implements View.OnClickListener { } private void makeGetter() { - mGetter = new ImageGetter(); + mGetter = new ImageGetter(this); } private boolean desiredSortOrder() { @@ -1338,11 +1024,14 @@ public class ViewImage extends Activity implements View.OnClickListener { } private void init(Uri uri) { - if (uri == null) + if (uri == null) { return; + } mSortAscending = desiredSortOrder(); - int sort = mSortAscending ? ImageManager.SORT_ASCENDING : ImageManager.SORT_DESCENDING; + int sort = mSortAscending + ? ImageManager.SORT_ASCENDING + : ImageManager.SORT_DESCENDING; mAllImages = ImageManager.makeImageList(uri, this, sort); uri = uri.buildUpon().query(null).build(); @@ -1363,11 +1052,14 @@ public class ViewImage extends Activity implements View.OnClickListener { if (image != null){ String bucket = null; uri = image.fullSizeImageUri(); - if(getIntent() != null && getIntent().getData() != null) + if (getIntent() != null && getIntent().getData() != null) { bucket = getIntent().getData().getQueryParameter("bucketId"); + } - if(bucket != null) - uri = uri.buildUpon().appendQueryParameter("bucketId", bucket).build(); + if (bucket != null) { + uri = uri.buildUpon().appendQueryParameter("bucketId", bucket) + .build(); + } } return uri; } @@ -1428,15 +1120,16 @@ public class ViewImage extends Activity implements View.OnClickListener { mAllImages.deactivate(); mDismissOnScreenControlsRunnable.run(); - if (mDismissOnScreenControlsRunnable != null) + if (mDismissOnScreenControlsRunnable != null) { mHandler.removeCallbacks(mDismissOnScreenControlsRunnable); + } - for (ImageViewTouch iv: mImageViews) { + for (ImageViewTouch iv : mImageViews) { iv.recycleBitmaps(); iv.setImageBitmap(null, true); } - for (ImageViewTouch iv: mSlideShowImageViews) { + for (ImageViewTouch iv : mSlideShowImageViews) { iv.recycleBitmaps(); iv.setImageBitmap(null, true); } @@ -1472,9 +1165,11 @@ public class ViewImage extends Activity implements View.OnClickListener { intent.setType("image/jpeg"); intent.putExtra(Intent.EXTRA_STREAM, u); try { - startActivity(Intent.createChooser(intent, getText(R.string.sendImage))); + startActivity(Intent.createChooser( + intent, getText(R.string.sendImage))); } catch (android.content.ActivityNotFoundException ex) { - Toast.makeText(this, R.string.no_way_to_share_image, Toast.LENGTH_SHORT).show(); + Toast.makeText(this, R.string.no_way_to_share_image, + Toast.LENGTH_SHORT).show(); } } break; @@ -1483,9 +1178,11 @@ public class ViewImage extends Activity implements View.OnClickListener { Uri u = mAllImages.getImageAt(mCurrentPosition).fullSizeImageUri(); Intent intent = new Intent(Intent.ACTION_ATTACH_DATA, u); try { - startActivity(Intent.createChooser(intent, getText(R.string.setImage))); + startActivity(Intent.createChooser( + intent, getText(R.string.setImage))); } catch (android.content.ActivityNotFoundException ex) { - Toast.makeText(this, R.string.no_way_to_share_video, Toast.LENGTH_SHORT).show(); + Toast.makeText(this, R.string.no_way_to_share_video, + Toast.LENGTH_SHORT).show(); } } break; @@ -1510,15 +1207,16 @@ public class ViewImage extends Activity implements View.OnClickListener { } @Override - protected void onActivityResult(int requestCode, int resultCode, Intent data) { + protected void onActivityResult(int requestCode, int resultCode, + Intent data) { switch (requestCode) { - case MenuHelper.RESULT_COMMON_MENU_CROP: - if (resultCode == RESULT_OK) { - // The CropImage activity passes back the Uri of the cropped image as - // the Action rather than the Data. - mSavedUri = Uri.parse(data.getAction()); - } - break; + case MenuHelper.RESULT_COMMON_MENU_CROP: + if (resultCode == RESULT_OK) { + // The CropImage activity passes back the Uri of the + // cropped image as the Action rather than the Data. + mSavedUri = Uri.parse(data.getAction()); + } + break; } } @@ -1528,8 +1226,9 @@ public class ViewImage extends Activity implements View.OnClickListener { @Override public void handleMessage(Message message) { switch(message.what) { - case IMAGE_GETTER_CALLBACK: - ((Runnable) message.obj).run(); + case IMAGE_GETTER_CALLBACK: + ((Runnable) message.obj).run(); + break; } } @@ -1550,3 +1249,373 @@ public class ViewImage extends Activity implements View.OnClickListener { } } } + +class ImageViewTouch extends ImageViewTouchBase { + private ViewImage mViewImage; + private boolean mEnableTrackballScroll; + + public ImageViewTouch(Context context) { + super(context); + mViewImage = (ViewImage) context; + } + + public ImageViewTouch(Context context, AttributeSet attrs) { + super(context, attrs); + mViewImage = (ViewImage) context; + } + + public void setEnableTrackballScroll(boolean enable) { + mEnableTrackballScroll = enable; + } + + protected void postTranslate(float dx, float dy) { + super.postTranslate(dx, dy); + center(true, false, false); + } + + public boolean handleTouchEvent(MotionEvent m) { + return mViewImage.mGestureDetector.onTouchEvent(m); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + // Don't respond to arrow keys if trackball scrolling is not enabled + if (!mEnableTrackballScroll) { + if ((keyCode >= KeyEvent.KEYCODE_DPAD_UP) + && (keyCode <= KeyEvent.KEYCODE_DPAD_RIGHT)) { + return super.onKeyDown(keyCode, event); + } + } + + int current = mViewImage.mCurrentPosition; + + int nextImagePos = -2; // default no next image + try { + switch (keyCode) { + case KeyEvent.KEYCODE_DPAD_CENTER: { + if (mViewImage.isPickIntent()) { + ImageManager.IImage img = mViewImage.mAllImages + .getImageAt(mViewImage.mCurrentPosition); + mViewImage.setResult(ViewImage.RESULT_OK, + new Intent().setData(img.fullSizeImageUri())); + mViewImage.finish(); + } + break; + } + case KeyEvent.KEYCODE_DPAD_LEFT: { + panBy(PAN_RATE, 0); + int maxOffset = (current == 0) ? 0 : ViewImage.HYSTERESIS; + if (getScale() <= 1F + || isShiftedToNextImage(true, maxOffset)) { + nextImagePos = current - 1; + } else { + center(true, false, true); + } + return true; + } + case KeyEvent.KEYCODE_DPAD_RIGHT: { + panBy(-PAN_RATE, 0); + int maxOffset = + (current == mViewImage.mAllImages.getCount() - 1) + ? 0 + : ViewImage.HYSTERESIS; + if (getScale() <= 1F + || isShiftedToNextImage(false, maxOffset)) { + nextImagePos = current + 1; + } else { + center(true, false, true); + } + return true; + } + case KeyEvent.KEYCODE_DPAD_UP: { + panBy(0, PAN_RATE); + center(true, false, false); + return true; + } + case KeyEvent.KEYCODE_DPAD_DOWN: { + panBy(0, -PAN_RATE); + center(true, false, false); + return true; + } + case KeyEvent.KEYCODE_DEL: + MenuHelper.deletePhoto( + mViewImage, mViewImage.mDeletePhotoRunnable); + break; + } + } finally { + if (nextImagePos >= 0 + && nextImagePos < mViewImage.mAllImages.getCount()) { + synchronized (mViewImage) { + mViewImage.setMode(ViewImage.MODE_NORMAL); + mViewImage.setImage(nextImagePos); + } + } else if (nextImagePos != -2) { + center(true, true, false); + } + } + + return super.onKeyDown(keyCode, event); + } + + protected boolean isShiftedToNextImage(boolean left, int maxOffset) { + boolean retval; + Bitmap bitmap = mBitmapDisplayed; + Matrix m = getImageViewMatrix(); + if (left) { + float [] t1 = new float[] { 0, 0 }; + m.mapPoints(t1); + retval = t1[0] > maxOffset; + } else { + int width = bitmap != null ? bitmap.getWidth() : getWidth(); + float [] t1 = new float[] { width, 0 }; + m.mapPoints(t1); + retval = t1[0] + maxOffset < getWidth(); + } + return retval; + } +} + +/* + * Here's the loading strategy. For any given image, load the thumbnail + * into memory and post a callback to display the resulting bitmap. + * + * Then proceed to load the full image bitmap. Three things can + * happen at this point: + * + * 1. the image fails to load because the UI thread decided + * to move on to a different image. This "cancellation" happens + * by virtue of the UI thread closing the stream containing the + * image being decoded. BitmapFactory.decodeStream returns null + * in this case. + * + * 2. the image loaded successfully. At that point we post + * a callback to the UI thread to actually show the bitmap. + * + * 3. when the post runs it checks to see if the image that was + * loaded is still the one we want. The UI may have moved on + * to some other image and if so we just drop the newly loaded + * bitmap on the floor. + */ + +interface ImageGetterCallback { + public void imageLoaded(int pos, int offset, Bitmap bitmap, + boolean isThumb); + public boolean wantsThumbnail(int pos, int offset); + public boolean wantsFullImage(int pos, int offset); + public int fullImageSizeToUse(int pos, int offset); + public void completed(boolean wasCanceled); + public int [] loadOrder(); +} + +class ImageGetter { + private static final String TAG = "ImageGetter"; + + // The thread which does the work. + private Thread mGetterThread; + + // The base position that's being retrieved. The actual images retrieved + // are this base plus each of the offets. + private int mCurrentPosition = -1; + + // The callback to invoke for each image. + private ImageGetterCallback mCB; + + // This is the loader cancelable that gets set while we're loading an image. + // If we change position we can cancel the current load using this. + private ImageManager.IGetBitmap_cancelable mLoad; + + // True if we're canceling the current load. + private boolean mCancelCurrent = false; + + // True when the therad should exit. + private boolean mDone = false; + + // True when the loader thread is waiting for work. + private boolean mReady = false; + + // The ViewImage this ImageGetter belongs to + ViewImage mViewImage; + + void cancelCurrent() { + synchronized (this) { + if (!mReady) { + mCancelCurrent = true; + ImageManager.IGetBitmap_cancelable load = mLoad; + if (load != null) { + if (Config.LOGV) { + Log.v(TAG, "canceling load object"); + } + load.cancel(); + } + mCancelCurrent = false; + } + } + } + + private class ImageGetterRunnable implements Runnable { + private Runnable callback(final int position, final int offset, + final boolean isThumb, final Bitmap bitmap) { + return new Runnable() { + public void run() { + // check for inflight callbacks that aren't applicable any longer + // before delivering them + if (!isCanceled() && position == mCurrentPosition) { + mCB.imageLoaded(position, offset, bitmap, isThumb); + } else if (bitmap != null) { + bitmap.recycle(); + } + } + }; + } + + private Runnable completedCallback(final boolean wasCanceled) { + return new Runnable() { + public void run() { + mCB.completed(wasCanceled); + } + }; + } + + public void run() { + int lastPosition = -1; + while (!mDone) { + synchronized (ImageGetter.this) { + mReady = true; + ImageGetter.this.notify(); + + if (mCurrentPosition == -1 || lastPosition == mCurrentPosition) { + try { + ImageGetter.this.wait(); + } catch (InterruptedException ex) { + continue; + } + } + + lastPosition = mCurrentPosition; + mReady = false; + } + + if (lastPosition != -1) { + int imageCount = mViewImage.mAllImages.getCount(); + + int [] order = mCB.loadOrder(); + for (int i = 0; i < order.length; i++) { + int offset = order[i]; + int imageNumber = lastPosition + offset; + if (imageNumber >= 0 && imageNumber < imageCount) { + ImageManager.IImage image = mViewImage.mAllImages.getImageAt(lastPosition + offset); + if (image == null || isCanceled()) { + break; + } + if (mCB.wantsThumbnail(lastPosition, offset)) { + if (Config.LOGV) + Log.v(TAG, "starting THUMBNAIL load at offset " + offset); + Bitmap b = image.thumbBitmap(); + mViewImage.mHandler.postGetterCallback(callback(lastPosition, offset, true, b)); + } + } + } + + for (int i = 0; i < order.length; i++) { + int offset = order[i]; + int imageNumber = lastPosition + offset; + if (imageNumber >= 0 && imageNumber < imageCount) { + ImageManager.IImage image = mViewImage.mAllImages.getImageAt(lastPosition + offset); + if (mCB.wantsFullImage(lastPosition, offset)) { + if (Config.LOGV) { + Log.v(TAG, "starting FULL IMAGE load at offset " + offset); + } + int sizeToUse = mCB.fullImageSizeToUse(lastPosition, offset); + if (image != null && !isCanceled()) { + mLoad = image.fullSizeBitmap_cancelable(sizeToUse); + } + if (mLoad != null) { + long t1; + if (Config.LOGV) t1 = System.currentTimeMillis(); + + // The return value could be null if the + // bitmap is too big, or we cancelled it. + Bitmap b = mLoad.get(); + + if (Config.LOGV && b != null) { + long t2 = System.currentTimeMillis(); + Log.v(TAG, "loading full image for " + image.fullSizeImageUri() + + " with requested size " + sizeToUse + + " took " + (t2 - t1) + + " and returned a bitmap with size " + + b.getWidth() + " / " + b.getHeight()); + } + + mLoad = null; + if (b != null) { + if (isCanceled()) { + b.recycle(); + } else { + Runnable cb = callback(lastPosition, offset, false, b); + mViewImage.mHandler.postGetterCallback(cb); + } + } + } + } + } + } + mViewImage.mHandler.postGetterCallback( + completedCallback(isCanceled())); + } + } + } + } + + public ImageGetter(ViewImage viewImage) { + mViewImage = viewImage; + mGetterThread = new Thread(new ImageGetterRunnable()); + mGetterThread.setName("ImageGettter"); + mGetterThread.start(); + } + + private boolean isCanceled() { + synchronized (this) { + return mCancelCurrent; + } + } + + public void setPosition(int position, ImageGetterCallback cb) { + synchronized (this) { + if (!mReady) { + try { + mCancelCurrent = true; + ImageManager.IGetBitmap_cancelable load = mLoad; + if (load != null) { + load.cancel(); + } + // if the thread is waiting before loading the full size + // image then this will free it up + ImageGetter.this.notify(); + ImageGetter.this.wait(); + mCancelCurrent = false; + } catch (InterruptedException ex) { + // not sure what to do here + } + } + } + + mCurrentPosition = position; + mCB = cb; + + synchronized (this) { + ImageGetter.this.notify(); + } + } + + public void stop() { + synchronized (this) { + mDone = true; + ImageGetter.this.notify(); + } + try { + mGetterThread.join(); + } catch (InterruptedException ex) { + + } + } +} |