ViewImage.java revision 666ea1b28a76aeba74744148b15099254d918671
1666ea1b28a76aeba74744148b15099254d918671Owen Lin/*
2666ea1b28a76aeba74744148b15099254d918671Owen Lin * Copyright (C) 2007 The Android Open Source Project
3666ea1b28a76aeba74744148b15099254d918671Owen Lin *
4666ea1b28a76aeba74744148b15099254d918671Owen Lin * Licensed under the Apache License, Version 2.0 (the "License");
5666ea1b28a76aeba74744148b15099254d918671Owen Lin * you may not use this file except in compliance with the License.
6666ea1b28a76aeba74744148b15099254d918671Owen Lin * You may obtain a copy of the License at
7666ea1b28a76aeba74744148b15099254d918671Owen Lin *
8666ea1b28a76aeba74744148b15099254d918671Owen Lin *      http://www.apache.org/licenses/LICENSE-2.0
9666ea1b28a76aeba74744148b15099254d918671Owen Lin *
10666ea1b28a76aeba74744148b15099254d918671Owen Lin * Unless required by applicable law or agreed to in writing, software
11666ea1b28a76aeba74744148b15099254d918671Owen Lin * distributed under the License is distributed on an "AS IS" BASIS,
12666ea1b28a76aeba74744148b15099254d918671Owen Lin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13666ea1b28a76aeba74744148b15099254d918671Owen Lin * See the License for the specific language governing permissions and
14666ea1b28a76aeba74744148b15099254d918671Owen Lin * limitations under the License.
15666ea1b28a76aeba74744148b15099254d918671Owen Lin */
16666ea1b28a76aeba74744148b15099254d918671Owen Lin
17666ea1b28a76aeba74744148b15099254d918671Owen Linpackage com.android.camera;
18666ea1b28a76aeba74744148b15099254d918671Owen Lin
19666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.app.Activity;
20666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.content.Context;
21666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.content.Intent;
22666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.content.SharedPreferences;
23666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.graphics.Bitmap;
24666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.net.Uri;
25666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.os.Bundle;
26666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.preference.PreferenceManager;
27666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.provider.MediaStore;
28666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.util.AttributeSet;
29666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.util.Log;
30666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.view.GestureDetector;
31666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.view.KeyEvent;
32666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.view.Menu;
33666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.view.MenuItem;
34666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.view.MotionEvent;
35666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.view.View;
36666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.view.Window;
37666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.view.WindowManager;
38666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.view.View.OnTouchListener;
39666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.view.animation.AlphaAnimation;
40666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.view.animation.Animation;
41666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.view.animation.AnimationUtils;
42666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.widget.Toast;
43666ea1b28a76aeba74744148b15099254d918671Owen Linimport android.widget.ZoomButtonsController;
44666ea1b28a76aeba74744148b15099254d918671Owen Lin
45666ea1b28a76aeba74744148b15099254d918671Owen Linimport com.android.camera.gallery.IImage;
46666ea1b28a76aeba74744148b15099254d918671Owen Linimport com.android.camera.gallery.IImageList;
47666ea1b28a76aeba74744148b15099254d918671Owen Linimport com.android.camera.gallery.VideoObject;
48666ea1b28a76aeba74744148b15099254d918671Owen Lin
49666ea1b28a76aeba74744148b15099254d918671Owen Linimport java.util.Random;
50666ea1b28a76aeba74744148b15099254d918671Owen Lin
51666ea1b28a76aeba74744148b15099254d918671Owen Lin// This activity can display a whole picture and navigate them in a specific
52666ea1b28a76aeba74744148b15099254d918671Owen Lin// gallery. It has two modes: normal mode and slide show mode. In normal mode
53666ea1b28a76aeba74744148b15099254d918671Owen Lin// the user view one image at a time, and can click "previous" and "next"
54666ea1b28a76aeba74744148b15099254d918671Owen Lin// button to see the previous or next image. In slide show mode it shows one
55666ea1b28a76aeba74744148b15099254d918671Owen Lin// image after another, with some transition effect.
56666ea1b28a76aeba74744148b15099254d918671Owen Linpublic class ViewImage extends Activity implements View.OnClickListener {
57666ea1b28a76aeba74744148b15099254d918671Owen Lin    private static final String PREF_SLIDESHOW_REPEAT =
58666ea1b28a76aeba74744148b15099254d918671Owen Lin            "pref_gallery_slideshow_repeat_key";
59666ea1b28a76aeba74744148b15099254d918671Owen Lin    private static final String PREF_SHUFFLE_SLIDESHOW =
60666ea1b28a76aeba74744148b15099254d918671Owen Lin            "pref_gallery_slideshow_shuffle_key";
61666ea1b28a76aeba74744148b15099254d918671Owen Lin    private static final String STATE_URI = "uri";
62666ea1b28a76aeba74744148b15099254d918671Owen Lin    private static final String STATE_SLIDESHOW = "slideshow";
63666ea1b28a76aeba74744148b15099254d918671Owen Lin    private static final String EXTRA_SLIDESHOW = "slideshow";
64666ea1b28a76aeba74744148b15099254d918671Owen Lin    private static final String TAG = "ViewImage";
65666ea1b28a76aeba74744148b15099254d918671Owen Lin
66666ea1b28a76aeba74744148b15099254d918671Owen Lin    private ImageGetter mGetter;
67666ea1b28a76aeba74744148b15099254d918671Owen Lin    private Uri mSavedUri;
68666ea1b28a76aeba74744148b15099254d918671Owen Lin    boolean mPaused = true;
69666ea1b28a76aeba74744148b15099254d918671Owen Lin    private boolean mShowControls = true;
70666ea1b28a76aeba74744148b15099254d918671Owen Lin
71666ea1b28a76aeba74744148b15099254d918671Owen Lin    // Choices for what adjacents to load.
72666ea1b28a76aeba74744148b15099254d918671Owen Lin    private static final int[] sOrderAdjacents = new int[] {0, 1, -1};
73666ea1b28a76aeba74744148b15099254d918671Owen Lin    private static final int[] sOrderSlideshow = new int[] {0};
74666ea1b28a76aeba74744148b15099254d918671Owen Lin
75666ea1b28a76aeba74744148b15099254d918671Owen Lin    final GetterHandler mHandler = new GetterHandler();
76666ea1b28a76aeba74744148b15099254d918671Owen Lin
77666ea1b28a76aeba74744148b15099254d918671Owen Lin    private final Random mRandom = new Random(System.currentTimeMillis());
78666ea1b28a76aeba74744148b15099254d918671Owen Lin    private int [] mShuffleOrder = null;
79666ea1b28a76aeba74744148b15099254d918671Owen Lin    private boolean mUseShuffleOrder = false;
80666ea1b28a76aeba74744148b15099254d918671Owen Lin    private boolean mSlideShowLoop = false;
81666ea1b28a76aeba74744148b15099254d918671Owen Lin
82666ea1b28a76aeba74744148b15099254d918671Owen Lin    static final int MODE_NORMAL = 1;
83666ea1b28a76aeba74744148b15099254d918671Owen Lin    static final int MODE_SLIDESHOW = 2;
84666ea1b28a76aeba74744148b15099254d918671Owen Lin    private int mMode = MODE_NORMAL;
85666ea1b28a76aeba74744148b15099254d918671Owen Lin
86666ea1b28a76aeba74744148b15099254d918671Owen Lin    private boolean mFullScreenInNormalMode;
87666ea1b28a76aeba74744148b15099254d918671Owen Lin    private boolean mShowActionIcons;
88666ea1b28a76aeba74744148b15099254d918671Owen Lin    private View mActionIconPanel;
89666ea1b28a76aeba74744148b15099254d918671Owen Lin
90666ea1b28a76aeba74744148b15099254d918671Owen Lin    private int mSlideShowInterval;
91666ea1b28a76aeba74744148b15099254d918671Owen Lin    private int mLastSlideShowImage;
92666ea1b28a76aeba74744148b15099254d918671Owen Lin    int mCurrentPosition = 0;
93666ea1b28a76aeba74744148b15099254d918671Owen Lin
94666ea1b28a76aeba74744148b15099254d918671Owen Lin    // represents which style animation to use
95666ea1b28a76aeba74744148b15099254d918671Owen Lin    private int mAnimationIndex;
96666ea1b28a76aeba74744148b15099254d918671Owen Lin    private Animation [] mSlideShowInAnimation;
97666ea1b28a76aeba74744148b15099254d918671Owen Lin    private Animation [] mSlideShowOutAnimation;
98666ea1b28a76aeba74744148b15099254d918671Owen Lin
99666ea1b28a76aeba74744148b15099254d918671Owen Lin    private SharedPreferences mPrefs;
100666ea1b28a76aeba74744148b15099254d918671Owen Lin
101666ea1b28a76aeba74744148b15099254d918671Owen Lin    private View mNextImageView;
102666ea1b28a76aeba74744148b15099254d918671Owen Lin    private View mPrevImageView;
103666ea1b28a76aeba74744148b15099254d918671Owen Lin    private final Animation mHideNextImageViewAnimation =
104666ea1b28a76aeba74744148b15099254d918671Owen Lin            new AlphaAnimation(1F, 0F);
105666ea1b28a76aeba74744148b15099254d918671Owen Lin    private final Animation mHidePrevImageViewAnimation =
106666ea1b28a76aeba74744148b15099254d918671Owen Lin            new AlphaAnimation(1F, 0F);
107666ea1b28a76aeba74744148b15099254d918671Owen Lin    private final Animation mShowNextImageViewAnimation =
108666ea1b28a76aeba74744148b15099254d918671Owen Lin            new AlphaAnimation(0F, 1F);
109666ea1b28a76aeba74744148b15099254d918671Owen Lin    private final Animation mShowPrevImageViewAnimation =
110666ea1b28a76aeba74744148b15099254d918671Owen Lin            new AlphaAnimation(0F, 1F);
111666ea1b28a76aeba74744148b15099254d918671Owen Lin
112666ea1b28a76aeba74744148b15099254d918671Owen Lin    public static final String KEY_IMAGE_LIST = "image_list";
113666ea1b28a76aeba74744148b15099254d918671Owen Lin    private static final String STATE_SHOW_CONTROLS = "show_controls";
114666ea1b28a76aeba74744148b15099254d918671Owen Lin
115666ea1b28a76aeba74744148b15099254d918671Owen Lin    IImageList mAllImages;
116666ea1b28a76aeba74744148b15099254d918671Owen Lin
117666ea1b28a76aeba74744148b15099254d918671Owen Lin    private ImageManager.ImageListParam mParam;
118666ea1b28a76aeba74744148b15099254d918671Owen Lin
119666ea1b28a76aeba74744148b15099254d918671Owen Lin    private int mSlideShowImageCurrent = 0;
120666ea1b28a76aeba74744148b15099254d918671Owen Lin    private final ImageViewTouchBase [] mSlideShowImageViews =
121666ea1b28a76aeba74744148b15099254d918671Owen Lin            new ImageViewTouchBase[2];
122666ea1b28a76aeba74744148b15099254d918671Owen Lin
123666ea1b28a76aeba74744148b15099254d918671Owen Lin    GestureDetector mGestureDetector;
124666ea1b28a76aeba74744148b15099254d918671Owen Lin    private ZoomButtonsController mZoomButtonsController;
125666ea1b28a76aeba74744148b15099254d918671Owen Lin
126666ea1b28a76aeba74744148b15099254d918671Owen Lin    // The image view displayed for normal mode.
127666ea1b28a76aeba74744148b15099254d918671Owen Lin    private ImageViewTouch mImageView;
128666ea1b28a76aeba74744148b15099254d918671Owen Lin    // This is the cache for thumbnail bitmaps.
129666ea1b28a76aeba74744148b15099254d918671Owen Lin    private BitmapCache mCache;
130666ea1b28a76aeba74744148b15099254d918671Owen Lin    private MenuHelper.MenuItemsResult mImageMenuRunnable;
131666ea1b28a76aeba74744148b15099254d918671Owen Lin    private final Runnable mDismissOnScreenControlRunner = new Runnable() {
132666ea1b28a76aeba74744148b15099254d918671Owen Lin        public void run() {
133666ea1b28a76aeba74744148b15099254d918671Owen Lin            hideOnScreenControls();
134666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
135666ea1b28a76aeba74744148b15099254d918671Owen Lin    };
136666ea1b28a76aeba74744148b15099254d918671Owen Lin
137666ea1b28a76aeba74744148b15099254d918671Owen Lin    private void updateNextPrevControls() {
138666ea1b28a76aeba74744148b15099254d918671Owen Lin        boolean showPrev = mCurrentPosition > 0;
139666ea1b28a76aeba74744148b15099254d918671Owen Lin        boolean showNext = mCurrentPosition < mAllImages.getCount() - 1;
140666ea1b28a76aeba74744148b15099254d918671Owen Lin
141666ea1b28a76aeba74744148b15099254d918671Owen Lin        boolean prevIsVisible = mPrevImageView.getVisibility() == View.VISIBLE;
142666ea1b28a76aeba74744148b15099254d918671Owen Lin        boolean nextIsVisible = mNextImageView.getVisibility() == View.VISIBLE;
143666ea1b28a76aeba74744148b15099254d918671Owen Lin
144666ea1b28a76aeba74744148b15099254d918671Owen Lin        if (showPrev && !prevIsVisible) {
145666ea1b28a76aeba74744148b15099254d918671Owen Lin            Animation a = mShowPrevImageViewAnimation;
146666ea1b28a76aeba74744148b15099254d918671Owen Lin            a.setDuration(500);
147666ea1b28a76aeba74744148b15099254d918671Owen Lin            mPrevImageView.startAnimation(a);
148666ea1b28a76aeba74744148b15099254d918671Owen Lin            mPrevImageView.setVisibility(View.VISIBLE);
149666ea1b28a76aeba74744148b15099254d918671Owen Lin        } else if (!showPrev && prevIsVisible) {
150666ea1b28a76aeba74744148b15099254d918671Owen Lin            Animation a = mHidePrevImageViewAnimation;
151666ea1b28a76aeba74744148b15099254d918671Owen Lin            a.setDuration(500);
152666ea1b28a76aeba74744148b15099254d918671Owen Lin            mPrevImageView.startAnimation(a);
153666ea1b28a76aeba74744148b15099254d918671Owen Lin            mPrevImageView.setVisibility(View.GONE);
154666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
155666ea1b28a76aeba74744148b15099254d918671Owen Lin
156666ea1b28a76aeba74744148b15099254d918671Owen Lin        if (showNext && !nextIsVisible) {
157666ea1b28a76aeba74744148b15099254d918671Owen Lin            Animation a = mShowNextImageViewAnimation;
158666ea1b28a76aeba74744148b15099254d918671Owen Lin            a.setDuration(500);
159666ea1b28a76aeba74744148b15099254d918671Owen Lin            mNextImageView.startAnimation(a);
160666ea1b28a76aeba74744148b15099254d918671Owen Lin            mNextImageView.setVisibility(View.VISIBLE);
161666ea1b28a76aeba74744148b15099254d918671Owen Lin        } else if (!showNext && nextIsVisible) {
162666ea1b28a76aeba74744148b15099254d918671Owen Lin            Animation a = mHideNextImageViewAnimation;
163666ea1b28a76aeba74744148b15099254d918671Owen Lin            a.setDuration(500);
164666ea1b28a76aeba74744148b15099254d918671Owen Lin            mNextImageView.startAnimation(a);
165666ea1b28a76aeba74744148b15099254d918671Owen Lin            mNextImageView.setVisibility(View.GONE);
166666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
167666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
168666ea1b28a76aeba74744148b15099254d918671Owen Lin
169666ea1b28a76aeba74744148b15099254d918671Owen Lin    private void hideOnScreenControls() {
170666ea1b28a76aeba74744148b15099254d918671Owen Lin        if (mShowActionIcons
171666ea1b28a76aeba74744148b15099254d918671Owen Lin                && mActionIconPanel.getVisibility() == View.VISIBLE) {
172666ea1b28a76aeba74744148b15099254d918671Owen Lin            Animation animation = new AlphaAnimation(1, 0);
173666ea1b28a76aeba74744148b15099254d918671Owen Lin            animation.setDuration(500);
174666ea1b28a76aeba74744148b15099254d918671Owen Lin            mActionIconPanel.startAnimation(animation);
175666ea1b28a76aeba74744148b15099254d918671Owen Lin            mActionIconPanel.setVisibility(View.INVISIBLE);
176666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
177666ea1b28a76aeba74744148b15099254d918671Owen Lin
178666ea1b28a76aeba74744148b15099254d918671Owen Lin        if (mNextImageView.getVisibility() == View.VISIBLE) {
179666ea1b28a76aeba74744148b15099254d918671Owen Lin            Animation a = mHideNextImageViewAnimation;
180666ea1b28a76aeba74744148b15099254d918671Owen Lin            a.setDuration(500);
181666ea1b28a76aeba74744148b15099254d918671Owen Lin            mNextImageView.startAnimation(a);
182666ea1b28a76aeba74744148b15099254d918671Owen Lin            mNextImageView.setVisibility(View.INVISIBLE);
183666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
184666ea1b28a76aeba74744148b15099254d918671Owen Lin
185666ea1b28a76aeba74744148b15099254d918671Owen Lin        if (mPrevImageView.getVisibility() == View.VISIBLE) {
186666ea1b28a76aeba74744148b15099254d918671Owen Lin            Animation a = mHidePrevImageViewAnimation;
187666ea1b28a76aeba74744148b15099254d918671Owen Lin            a.setDuration(500);
188666ea1b28a76aeba74744148b15099254d918671Owen Lin            mPrevImageView.startAnimation(a);
189666ea1b28a76aeba74744148b15099254d918671Owen Lin            mPrevImageView.setVisibility(View.INVISIBLE);
190666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
191666ea1b28a76aeba74744148b15099254d918671Owen Lin
192666ea1b28a76aeba74744148b15099254d918671Owen Lin        mZoomButtonsController.setVisible(false);
193666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
194666ea1b28a76aeba74744148b15099254d918671Owen Lin
195666ea1b28a76aeba74744148b15099254d918671Owen Lin    private void showOnScreenControls() {
196666ea1b28a76aeba74744148b15099254d918671Owen Lin        if (mPaused) return;
197666ea1b28a76aeba74744148b15099254d918671Owen Lin        // If the view has not been attached to the window yet, the
198666ea1b28a76aeba74744148b15099254d918671Owen Lin        // zoomButtonControls will not able to show up. So delay it until the
199666ea1b28a76aeba74744148b15099254d918671Owen Lin        // view has attached to window.
200666ea1b28a76aeba74744148b15099254d918671Owen Lin        if (mActionIconPanel.getWindowToken() == null) {
201666ea1b28a76aeba74744148b15099254d918671Owen Lin            mHandler.postGetterCallback(new Runnable() {
202666ea1b28a76aeba74744148b15099254d918671Owen Lin                public void run() {
203666ea1b28a76aeba74744148b15099254d918671Owen Lin                    showOnScreenControls();
204666ea1b28a76aeba74744148b15099254d918671Owen Lin                }
205666ea1b28a76aeba74744148b15099254d918671Owen Lin            });
206666ea1b28a76aeba74744148b15099254d918671Owen Lin            return;
207666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
208666ea1b28a76aeba74744148b15099254d918671Owen Lin        updateNextPrevControls();
209666ea1b28a76aeba74744148b15099254d918671Owen Lin
210666ea1b28a76aeba74744148b15099254d918671Owen Lin        IImage image = mAllImages.getImageAt(mCurrentPosition);
211666ea1b28a76aeba74744148b15099254d918671Owen Lin        if (image instanceof VideoObject) {
212666ea1b28a76aeba74744148b15099254d918671Owen Lin            mZoomButtonsController.setVisible(false);
213666ea1b28a76aeba74744148b15099254d918671Owen Lin        } else {
214666ea1b28a76aeba74744148b15099254d918671Owen Lin            updateZoomButtonsEnabled();
215666ea1b28a76aeba74744148b15099254d918671Owen Lin            mZoomButtonsController.setVisible(true);
216666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
217666ea1b28a76aeba74744148b15099254d918671Owen Lin
218666ea1b28a76aeba74744148b15099254d918671Owen Lin        if (mShowActionIcons
219666ea1b28a76aeba74744148b15099254d918671Owen Lin                && mActionIconPanel.getVisibility() != View.VISIBLE) {
220666ea1b28a76aeba74744148b15099254d918671Owen Lin            Animation animation = new AlphaAnimation(0, 1);
221666ea1b28a76aeba74744148b15099254d918671Owen Lin            animation.setDuration(500);
222666ea1b28a76aeba74744148b15099254d918671Owen Lin            mActionIconPanel.startAnimation(animation);
223666ea1b28a76aeba74744148b15099254d918671Owen Lin            mActionIconPanel.setVisibility(View.VISIBLE);
224666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
225666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
226666ea1b28a76aeba74744148b15099254d918671Owen Lin
227666ea1b28a76aeba74744148b15099254d918671Owen Lin    @Override
228666ea1b28a76aeba74744148b15099254d918671Owen Lin    public boolean dispatchTouchEvent(MotionEvent m) {
229666ea1b28a76aeba74744148b15099254d918671Owen Lin        if (mPaused) return true;
230666ea1b28a76aeba74744148b15099254d918671Owen Lin        if (mZoomButtonsController.isVisible()) {
231666ea1b28a76aeba74744148b15099254d918671Owen Lin            scheduleDismissOnScreenControls();
232666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
233666ea1b28a76aeba74744148b15099254d918671Owen Lin        return super.dispatchTouchEvent(m);
234666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
235666ea1b28a76aeba74744148b15099254d918671Owen Lin
236666ea1b28a76aeba74744148b15099254d918671Owen Lin    private void updateZoomButtonsEnabled() {
237666ea1b28a76aeba74744148b15099254d918671Owen Lin        ImageViewTouch imageView = mImageView;
238666ea1b28a76aeba74744148b15099254d918671Owen Lin        float scale = imageView.getScale();
239666ea1b28a76aeba74744148b15099254d918671Owen Lin        mZoomButtonsController.setZoomInEnabled(scale < imageView.mMaxZoom);
240666ea1b28a76aeba74744148b15099254d918671Owen Lin        mZoomButtonsController.setZoomOutEnabled(scale > 1);
241666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
242666ea1b28a76aeba74744148b15099254d918671Owen Lin
243666ea1b28a76aeba74744148b15099254d918671Owen Lin    @Override
244666ea1b28a76aeba74744148b15099254d918671Owen Lin    protected void onDestroy() {
245666ea1b28a76aeba74744148b15099254d918671Owen Lin        // This is necessary to make the ZoomButtonsController unregister
246666ea1b28a76aeba74744148b15099254d918671Owen Lin        // its configuration change receiver.
247666ea1b28a76aeba74744148b15099254d918671Owen Lin        if (mZoomButtonsController != null) {
248666ea1b28a76aeba74744148b15099254d918671Owen Lin            mZoomButtonsController.setVisible(false);
249666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
250666ea1b28a76aeba74744148b15099254d918671Owen Lin        super.onDestroy();
251666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
252666ea1b28a76aeba74744148b15099254d918671Owen Lin
253666ea1b28a76aeba74744148b15099254d918671Owen Lin    private void scheduleDismissOnScreenControls() {
254666ea1b28a76aeba74744148b15099254d918671Owen Lin        mHandler.removeCallbacks(mDismissOnScreenControlRunner);
255666ea1b28a76aeba74744148b15099254d918671Owen Lin        mHandler.postDelayed(mDismissOnScreenControlRunner, 2000);
256666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
257666ea1b28a76aeba74744148b15099254d918671Owen Lin
258666ea1b28a76aeba74744148b15099254d918671Owen Lin    private void setupOnScreenControls(View rootView, View ownerView) {
259666ea1b28a76aeba74744148b15099254d918671Owen Lin        mNextImageView = rootView.findViewById(R.id.next_image);
260666ea1b28a76aeba74744148b15099254d918671Owen Lin        mPrevImageView = rootView.findViewById(R.id.prev_image);
261666ea1b28a76aeba74744148b15099254d918671Owen Lin
262666ea1b28a76aeba74744148b15099254d918671Owen Lin        mNextImageView.setOnClickListener(this);
263666ea1b28a76aeba74744148b15099254d918671Owen Lin        mPrevImageView.setOnClickListener(this);
264666ea1b28a76aeba74744148b15099254d918671Owen Lin
265666ea1b28a76aeba74744148b15099254d918671Owen Lin        setupZoomButtonController(ownerView);
266666ea1b28a76aeba74744148b15099254d918671Owen Lin        setupOnTouchListeners(rootView);
267666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
268666ea1b28a76aeba74744148b15099254d918671Owen Lin
269666ea1b28a76aeba74744148b15099254d918671Owen Lin    private void setupZoomButtonController(final View ownerView) {
270666ea1b28a76aeba74744148b15099254d918671Owen Lin        mZoomButtonsController = new ZoomButtonsController(ownerView);
271666ea1b28a76aeba74744148b15099254d918671Owen Lin        mZoomButtonsController.setAutoDismissed(false);
272666ea1b28a76aeba74744148b15099254d918671Owen Lin        mZoomButtonsController.setZoomSpeed(100);
273666ea1b28a76aeba74744148b15099254d918671Owen Lin        mZoomButtonsController.setOnZoomListener(
274666ea1b28a76aeba74744148b15099254d918671Owen Lin                new ZoomButtonsController.OnZoomListener() {
275666ea1b28a76aeba74744148b15099254d918671Owen Lin            public void onVisibilityChanged(boolean visible) {
276666ea1b28a76aeba74744148b15099254d918671Owen Lin                if (visible) {
277666ea1b28a76aeba74744148b15099254d918671Owen Lin                    updateZoomButtonsEnabled();
278666ea1b28a76aeba74744148b15099254d918671Owen Lin                }
279666ea1b28a76aeba74744148b15099254d918671Owen Lin            }
280666ea1b28a76aeba74744148b15099254d918671Owen Lin
281666ea1b28a76aeba74744148b15099254d918671Owen Lin            public void onZoom(boolean zoomIn) {
282666ea1b28a76aeba74744148b15099254d918671Owen Lin                if (zoomIn) {
283666ea1b28a76aeba74744148b15099254d918671Owen Lin                    mImageView.zoomIn();
284666ea1b28a76aeba74744148b15099254d918671Owen Lin                } else {
285666ea1b28a76aeba74744148b15099254d918671Owen Lin                    mImageView.zoomOut();
286666ea1b28a76aeba74744148b15099254d918671Owen Lin                }
287666ea1b28a76aeba74744148b15099254d918671Owen Lin                mZoomButtonsController.setVisible(true);
288666ea1b28a76aeba74744148b15099254d918671Owen Lin                updateZoomButtonsEnabled();
289666ea1b28a76aeba74744148b15099254d918671Owen Lin            }
290666ea1b28a76aeba74744148b15099254d918671Owen Lin        });
291666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
292666ea1b28a76aeba74744148b15099254d918671Owen Lin
293666ea1b28a76aeba74744148b15099254d918671Owen Lin    private void setupOnTouchListeners(View rootView) {
294666ea1b28a76aeba74744148b15099254d918671Owen Lin        mGestureDetector = new GestureDetector(this, new MyGestureListener());
295666ea1b28a76aeba74744148b15099254d918671Owen Lin
296666ea1b28a76aeba74744148b15099254d918671Owen Lin        // If the user touches anywhere on the panel (including the
297666ea1b28a76aeba74744148b15099254d918671Owen Lin        // next/prev button). We show the on-screen controls. In addition
298666ea1b28a76aeba74744148b15099254d918671Owen Lin        // to that, if the touch is not on the prev/next button, we
299666ea1b28a76aeba74744148b15099254d918671Owen Lin        // pass the event to the gesture detector to detect double tap.
300666ea1b28a76aeba74744148b15099254d918671Owen Lin        final OnTouchListener buttonListener = new OnTouchListener() {
301666ea1b28a76aeba74744148b15099254d918671Owen Lin            public boolean onTouch(View v, MotionEvent event) {
302666ea1b28a76aeba74744148b15099254d918671Owen Lin                scheduleDismissOnScreenControls();
303666ea1b28a76aeba74744148b15099254d918671Owen Lin                return false;
304666ea1b28a76aeba74744148b15099254d918671Owen Lin            }
305666ea1b28a76aeba74744148b15099254d918671Owen Lin        };
306666ea1b28a76aeba74744148b15099254d918671Owen Lin
307666ea1b28a76aeba74744148b15099254d918671Owen Lin        OnTouchListener rootListener = new OnTouchListener() {
308666ea1b28a76aeba74744148b15099254d918671Owen Lin            public boolean onTouch(View v, MotionEvent event) {
309666ea1b28a76aeba74744148b15099254d918671Owen Lin                buttonListener.onTouch(v, event);
310666ea1b28a76aeba74744148b15099254d918671Owen Lin                mGestureDetector.onTouchEvent(event);
311666ea1b28a76aeba74744148b15099254d918671Owen Lin
312666ea1b28a76aeba74744148b15099254d918671Owen Lin                // We do not use the return value of
313666ea1b28a76aeba74744148b15099254d918671Owen Lin                // mGestureDetector.onTouchEvent because we will not receive
314666ea1b28a76aeba74744148b15099254d918671Owen Lin                // the "up" event if we return false for the "down" event.
315666ea1b28a76aeba74744148b15099254d918671Owen Lin                return true;
316666ea1b28a76aeba74744148b15099254d918671Owen Lin            }
317666ea1b28a76aeba74744148b15099254d918671Owen Lin        };
318666ea1b28a76aeba74744148b15099254d918671Owen Lin
319666ea1b28a76aeba74744148b15099254d918671Owen Lin        mNextImageView.setOnTouchListener(buttonListener);
320666ea1b28a76aeba74744148b15099254d918671Owen Lin        mPrevImageView.setOnTouchListener(buttonListener);
321666ea1b28a76aeba74744148b15099254d918671Owen Lin        rootView.setOnTouchListener(rootListener);
322666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
323666ea1b28a76aeba74744148b15099254d918671Owen Lin
324666ea1b28a76aeba74744148b15099254d918671Owen Lin    private class MyGestureListener extends
325666ea1b28a76aeba74744148b15099254d918671Owen Lin            GestureDetector.SimpleOnGestureListener {
326666ea1b28a76aeba74744148b15099254d918671Owen Lin
327666ea1b28a76aeba74744148b15099254d918671Owen Lin        @Override
328666ea1b28a76aeba74744148b15099254d918671Owen Lin        public boolean onScroll(MotionEvent e1, MotionEvent e2,
329666ea1b28a76aeba74744148b15099254d918671Owen Lin                float distanceX, float distanceY) {
330666ea1b28a76aeba74744148b15099254d918671Owen Lin            ImageViewTouch imageView = mImageView;
331666ea1b28a76aeba74744148b15099254d918671Owen Lin            if (imageView.getScale() > 1F) {
332666ea1b28a76aeba74744148b15099254d918671Owen Lin                imageView.postTranslateCenter(-distanceX, -distanceY);
333666ea1b28a76aeba74744148b15099254d918671Owen Lin            }
334666ea1b28a76aeba74744148b15099254d918671Owen Lin            return true;
335666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
336666ea1b28a76aeba74744148b15099254d918671Owen Lin
337666ea1b28a76aeba74744148b15099254d918671Owen Lin        @Override
338666ea1b28a76aeba74744148b15099254d918671Owen Lin        public boolean onSingleTapUp(MotionEvent e) {
339666ea1b28a76aeba74744148b15099254d918671Owen Lin            setMode(MODE_NORMAL);
340666ea1b28a76aeba74744148b15099254d918671Owen Lin            return true;
341666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
342666ea1b28a76aeba74744148b15099254d918671Owen Lin
343666ea1b28a76aeba74744148b15099254d918671Owen Lin        @Override
344666ea1b28a76aeba74744148b15099254d918671Owen Lin        public boolean onSingleTapConfirmed(MotionEvent e) {
345666ea1b28a76aeba74744148b15099254d918671Owen Lin            showOnScreenControls();
346666ea1b28a76aeba74744148b15099254d918671Owen Lin            scheduleDismissOnScreenControls();
347666ea1b28a76aeba74744148b15099254d918671Owen Lin            return true;
348666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
349666ea1b28a76aeba74744148b15099254d918671Owen Lin
350666ea1b28a76aeba74744148b15099254d918671Owen Lin        @Override
351666ea1b28a76aeba74744148b15099254d918671Owen Lin        public boolean onDoubleTap(MotionEvent e) {
352666ea1b28a76aeba74744148b15099254d918671Owen Lin            ImageViewTouch imageView = mImageView;
353666ea1b28a76aeba74744148b15099254d918671Owen Lin
354666ea1b28a76aeba74744148b15099254d918671Owen Lin            // Switch between the original scale and 3x scale.
355666ea1b28a76aeba74744148b15099254d918671Owen Lin            if (imageView.getScale() > 2F) {
356666ea1b28a76aeba74744148b15099254d918671Owen Lin                mImageView.zoomTo(1f);
357666ea1b28a76aeba74744148b15099254d918671Owen Lin            } else {
358666ea1b28a76aeba74744148b15099254d918671Owen Lin                mImageView.zoomToPoint(3f, e.getX(), e.getY());
359666ea1b28a76aeba74744148b15099254d918671Owen Lin            }
360666ea1b28a76aeba74744148b15099254d918671Owen Lin            return true;
361666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
362666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
363666ea1b28a76aeba74744148b15099254d918671Owen Lin
364666ea1b28a76aeba74744148b15099254d918671Owen Lin    boolean isPickIntent() {
365666ea1b28a76aeba74744148b15099254d918671Owen Lin        String action = getIntent().getAction();
366666ea1b28a76aeba74744148b15099254d918671Owen Lin        return (Intent.ACTION_PICK.equals(action)
367666ea1b28a76aeba74744148b15099254d918671Owen Lin                || Intent.ACTION_GET_CONTENT.equals(action));
368666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
369666ea1b28a76aeba74744148b15099254d918671Owen Lin
370666ea1b28a76aeba74744148b15099254d918671Owen Lin    @Override
371666ea1b28a76aeba74744148b15099254d918671Owen Lin    public boolean onCreateOptionsMenu(Menu menu) {
372666ea1b28a76aeba74744148b15099254d918671Owen Lin        super.onCreateOptionsMenu(menu);
373666ea1b28a76aeba74744148b15099254d918671Owen Lin
374666ea1b28a76aeba74744148b15099254d918671Owen Lin        MenuItem item = menu.add(Menu.NONE, Menu.NONE,
375666ea1b28a76aeba74744148b15099254d918671Owen Lin                MenuHelper.POSITION_SLIDESHOW,
376666ea1b28a76aeba74744148b15099254d918671Owen Lin                R.string.slide_show);
377666ea1b28a76aeba74744148b15099254d918671Owen Lin        item.setOnMenuItemClickListener(
378666ea1b28a76aeba74744148b15099254d918671Owen Lin                new MenuItem.OnMenuItemClickListener() {
379666ea1b28a76aeba74744148b15099254d918671Owen Lin            public boolean onMenuItemClick(MenuItem item) {
380666ea1b28a76aeba74744148b15099254d918671Owen Lin                setMode(MODE_SLIDESHOW);
381666ea1b28a76aeba74744148b15099254d918671Owen Lin                mLastSlideShowImage = mCurrentPosition;
382666ea1b28a76aeba74744148b15099254d918671Owen Lin                loadNextImage(mCurrentPosition, 0, true);
383666ea1b28a76aeba74744148b15099254d918671Owen Lin                return true;
384666ea1b28a76aeba74744148b15099254d918671Owen Lin            }
385666ea1b28a76aeba74744148b15099254d918671Owen Lin        });
386666ea1b28a76aeba74744148b15099254d918671Owen Lin        item.setIcon(android.R.drawable.ic_menu_slideshow);
387666ea1b28a76aeba74744148b15099254d918671Owen Lin
388666ea1b28a76aeba74744148b15099254d918671Owen Lin        mImageMenuRunnable = MenuHelper.addImageMenuItems(
389666ea1b28a76aeba74744148b15099254d918671Owen Lin                menu,
390666ea1b28a76aeba74744148b15099254d918671Owen Lin                MenuHelper.INCLUDE_ALL,
391666ea1b28a76aeba74744148b15099254d918671Owen Lin                ViewImage.this,
392666ea1b28a76aeba74744148b15099254d918671Owen Lin                mHandler,
393666ea1b28a76aeba74744148b15099254d918671Owen Lin                mDeletePhotoRunnable,
394666ea1b28a76aeba74744148b15099254d918671Owen Lin                new MenuHelper.MenuInvoker() {
395666ea1b28a76aeba74744148b15099254d918671Owen Lin                    public void run(final MenuHelper.MenuCallback cb) {
396666ea1b28a76aeba74744148b15099254d918671Owen Lin                        if (mPaused) return;
397666ea1b28a76aeba74744148b15099254d918671Owen Lin                        setMode(MODE_NORMAL);
398666ea1b28a76aeba74744148b15099254d918671Owen Lin
399666ea1b28a76aeba74744148b15099254d918671Owen Lin                        IImage image = mAllImages.getImageAt(mCurrentPosition);
400666ea1b28a76aeba74744148b15099254d918671Owen Lin                        Uri uri = image.fullSizeImageUri();
401666ea1b28a76aeba74744148b15099254d918671Owen Lin                        cb.run(uri, image);
402666ea1b28a76aeba74744148b15099254d918671Owen Lin
403666ea1b28a76aeba74744148b15099254d918671Owen Lin                        mImageView.clear();
404666ea1b28a76aeba74744148b15099254d918671Owen Lin                        setImage(mCurrentPosition, false);
405666ea1b28a76aeba74744148b15099254d918671Owen Lin                    }
406666ea1b28a76aeba74744148b15099254d918671Owen Lin                });
407666ea1b28a76aeba74744148b15099254d918671Owen Lin
408666ea1b28a76aeba74744148b15099254d918671Owen Lin        item = menu.add(Menu.NONE, Menu.NONE,
409666ea1b28a76aeba74744148b15099254d918671Owen Lin                MenuHelper.POSITION_GALLERY_SETTING, R.string.camerasettings);
410666ea1b28a76aeba74744148b15099254d918671Owen Lin        item.setOnMenuItemClickListener(
411666ea1b28a76aeba74744148b15099254d918671Owen Lin                new MenuItem.OnMenuItemClickListener() {
412666ea1b28a76aeba74744148b15099254d918671Owen Lin            public boolean onMenuItemClick(MenuItem item) {
413666ea1b28a76aeba74744148b15099254d918671Owen Lin                Intent preferences = new Intent();
414666ea1b28a76aeba74744148b15099254d918671Owen Lin                preferences.setClass(ViewImage.this, GallerySettings.class);
415666ea1b28a76aeba74744148b15099254d918671Owen Lin                startActivity(preferences);
416666ea1b28a76aeba74744148b15099254d918671Owen Lin                return true;
417666ea1b28a76aeba74744148b15099254d918671Owen Lin            }
418666ea1b28a76aeba74744148b15099254d918671Owen Lin        });
419666ea1b28a76aeba74744148b15099254d918671Owen Lin        item.setAlphabeticShortcut('p');
420666ea1b28a76aeba74744148b15099254d918671Owen Lin        item.setIcon(android.R.drawable.ic_menu_preferences);
421666ea1b28a76aeba74744148b15099254d918671Owen Lin
422666ea1b28a76aeba74744148b15099254d918671Owen Lin        return true;
423666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
424666ea1b28a76aeba74744148b15099254d918671Owen Lin
425666ea1b28a76aeba74744148b15099254d918671Owen Lin    protected Runnable mDeletePhotoRunnable = new Runnable() {
426666ea1b28a76aeba74744148b15099254d918671Owen Lin        public void run() {
427666ea1b28a76aeba74744148b15099254d918671Owen Lin            mAllImages.removeImageAt(mCurrentPosition);
428666ea1b28a76aeba74744148b15099254d918671Owen Lin            if (mAllImages.getCount() == 0) {
429666ea1b28a76aeba74744148b15099254d918671Owen Lin                finish();
430666ea1b28a76aeba74744148b15099254d918671Owen Lin                return;
431666ea1b28a76aeba74744148b15099254d918671Owen Lin            } else {
432666ea1b28a76aeba74744148b15099254d918671Owen Lin                if (mCurrentPosition == mAllImages.getCount()) {
433666ea1b28a76aeba74744148b15099254d918671Owen Lin                    mCurrentPosition -= 1;
434666ea1b28a76aeba74744148b15099254d918671Owen Lin                }
435666ea1b28a76aeba74744148b15099254d918671Owen Lin            }
436666ea1b28a76aeba74744148b15099254d918671Owen Lin            mImageView.clear();
437666ea1b28a76aeba74744148b15099254d918671Owen Lin            mCache.clear();  // Because the position number is changed.
438666ea1b28a76aeba74744148b15099254d918671Owen Lin            setImage(mCurrentPosition, true);
439666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
440666ea1b28a76aeba74744148b15099254d918671Owen Lin    };
441666ea1b28a76aeba74744148b15099254d918671Owen Lin
442666ea1b28a76aeba74744148b15099254d918671Owen Lin    @Override
443666ea1b28a76aeba74744148b15099254d918671Owen Lin    public boolean onPrepareOptionsMenu(Menu menu) {
444666ea1b28a76aeba74744148b15099254d918671Owen Lin
445666ea1b28a76aeba74744148b15099254d918671Owen Lin        super.onPrepareOptionsMenu(menu);
446666ea1b28a76aeba74744148b15099254d918671Owen Lin        if (mPaused) return false;
447666ea1b28a76aeba74744148b15099254d918671Owen Lin
448666ea1b28a76aeba74744148b15099254d918671Owen Lin        setMode(MODE_NORMAL);
449666ea1b28a76aeba74744148b15099254d918671Owen Lin        IImage image = mAllImages.getImageAt(mCurrentPosition);
450666ea1b28a76aeba74744148b15099254d918671Owen Lin
451666ea1b28a76aeba74744148b15099254d918671Owen Lin        if (mImageMenuRunnable != null) {
452666ea1b28a76aeba74744148b15099254d918671Owen Lin            mImageMenuRunnable.gettingReadyToOpen(menu, image);
453666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
454666ea1b28a76aeba74744148b15099254d918671Owen Lin
455666ea1b28a76aeba74744148b15099254d918671Owen Lin        Uri uri = mAllImages.getImageAt(mCurrentPosition).fullSizeImageUri();
456666ea1b28a76aeba74744148b15099254d918671Owen Lin        MenuHelper.enableShareMenuItem(menu, MenuHelper.isWhiteListUri(uri));
457666ea1b28a76aeba74744148b15099254d918671Owen Lin
458666ea1b28a76aeba74744148b15099254d918671Owen Lin        MenuHelper.enableShowOnMapMenuItem(menu, MenuHelper.hasLatLngData(image));
459666ea1b28a76aeba74744148b15099254d918671Owen Lin
460666ea1b28a76aeba74744148b15099254d918671Owen Lin        return true;
461666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
462666ea1b28a76aeba74744148b15099254d918671Owen Lin
463666ea1b28a76aeba74744148b15099254d918671Owen Lin    @Override
464666ea1b28a76aeba74744148b15099254d918671Owen Lin    public boolean onMenuItemSelected(int featureId, MenuItem item) {
465666ea1b28a76aeba74744148b15099254d918671Owen Lin        boolean b = super.onMenuItemSelected(featureId, item);
466666ea1b28a76aeba74744148b15099254d918671Owen Lin        if (mImageMenuRunnable != null) {
467666ea1b28a76aeba74744148b15099254d918671Owen Lin            mImageMenuRunnable.aboutToCall(item,
468666ea1b28a76aeba74744148b15099254d918671Owen Lin                    mAllImages.getImageAt(mCurrentPosition));
469666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
470666ea1b28a76aeba74744148b15099254d918671Owen Lin        return b;
471666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
472666ea1b28a76aeba74744148b15099254d918671Owen Lin
473666ea1b28a76aeba74744148b15099254d918671Owen Lin    void setImage(int pos, boolean showControls) {
474666ea1b28a76aeba74744148b15099254d918671Owen Lin        mCurrentPosition = pos;
475666ea1b28a76aeba74744148b15099254d918671Owen Lin
476666ea1b28a76aeba74744148b15099254d918671Owen Lin        Bitmap b = mCache.getBitmap(pos);
477666ea1b28a76aeba74744148b15099254d918671Owen Lin        if (b != null) {
478666ea1b28a76aeba74744148b15099254d918671Owen Lin            IImage image = mAllImages.getImageAt(pos);
479666ea1b28a76aeba74744148b15099254d918671Owen Lin            mImageView.setImageRotateBitmapResetBase(
480666ea1b28a76aeba74744148b15099254d918671Owen Lin                    new RotateBitmap(b, image.getDegreesRotated()), true);
481666ea1b28a76aeba74744148b15099254d918671Owen Lin            updateZoomButtonsEnabled();
482666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
483666ea1b28a76aeba74744148b15099254d918671Owen Lin
484666ea1b28a76aeba74744148b15099254d918671Owen Lin        ImageGetterCallback cb = new ImageGetterCallback() {
485666ea1b28a76aeba74744148b15099254d918671Owen Lin            public void completed() {
486666ea1b28a76aeba74744148b15099254d918671Owen Lin            }
487666ea1b28a76aeba74744148b15099254d918671Owen Lin
488666ea1b28a76aeba74744148b15099254d918671Owen Lin            public boolean wantsThumbnail(int pos, int offset) {
489666ea1b28a76aeba74744148b15099254d918671Owen Lin                return !mCache.hasBitmap(pos + offset);
490666ea1b28a76aeba74744148b15099254d918671Owen Lin            }
491666ea1b28a76aeba74744148b15099254d918671Owen Lin
492666ea1b28a76aeba74744148b15099254d918671Owen Lin            public boolean wantsFullImage(int pos, int offset) {
493666ea1b28a76aeba74744148b15099254d918671Owen Lin                return offset == 0;
494666ea1b28a76aeba74744148b15099254d918671Owen Lin            }
495666ea1b28a76aeba74744148b15099254d918671Owen Lin
496666ea1b28a76aeba74744148b15099254d918671Owen Lin            public int fullImageSizeToUse(int pos, int offset) {
497666ea1b28a76aeba74744148b15099254d918671Owen Lin                // this number should be bigger so that we can zoom.  we may
498666ea1b28a76aeba74744148b15099254d918671Owen Lin                // need to get fancier and read in the fuller size image as the
499666ea1b28a76aeba74744148b15099254d918671Owen Lin                // user starts to zoom.
500666ea1b28a76aeba74744148b15099254d918671Owen Lin                // Originally the value is set to 480 in order to avoid OOM.
501666ea1b28a76aeba74744148b15099254d918671Owen Lin                // Now we set it to 2048 because of using
502666ea1b28a76aeba74744148b15099254d918671Owen Lin                // native memory allocation for Bitmaps.
503666ea1b28a76aeba74744148b15099254d918671Owen Lin                final int imageViewSize = 2048;
504666ea1b28a76aeba74744148b15099254d918671Owen Lin                return imageViewSize;
505666ea1b28a76aeba74744148b15099254d918671Owen Lin            }
506666ea1b28a76aeba74744148b15099254d918671Owen Lin
507666ea1b28a76aeba74744148b15099254d918671Owen Lin            public int [] loadOrder() {
508666ea1b28a76aeba74744148b15099254d918671Owen Lin                return sOrderAdjacents;
509666ea1b28a76aeba74744148b15099254d918671Owen Lin            }
510666ea1b28a76aeba74744148b15099254d918671Owen Lin
511666ea1b28a76aeba74744148b15099254d918671Owen Lin            public void imageLoaded(int pos, int offset, RotateBitmap bitmap,
512666ea1b28a76aeba74744148b15099254d918671Owen Lin                                    boolean isThumb) {
513666ea1b28a76aeba74744148b15099254d918671Owen Lin                // shouldn't get here after onPause()
514666ea1b28a76aeba74744148b15099254d918671Owen Lin
515666ea1b28a76aeba74744148b15099254d918671Owen Lin                // We may get a result from a previous request. Ignore it.
516666ea1b28a76aeba74744148b15099254d918671Owen Lin                if (pos != mCurrentPosition) {
517666ea1b28a76aeba74744148b15099254d918671Owen Lin                    bitmap.recycle();
518666ea1b28a76aeba74744148b15099254d918671Owen Lin                    return;
519666ea1b28a76aeba74744148b15099254d918671Owen Lin                }
520666ea1b28a76aeba74744148b15099254d918671Owen Lin
521666ea1b28a76aeba74744148b15099254d918671Owen Lin                if (isThumb) {
522666ea1b28a76aeba74744148b15099254d918671Owen Lin                    mCache.put(pos + offset, bitmap.getBitmap());
523666ea1b28a76aeba74744148b15099254d918671Owen Lin                }
524666ea1b28a76aeba74744148b15099254d918671Owen Lin                if (offset == 0) {
525666ea1b28a76aeba74744148b15099254d918671Owen Lin                    // isThumb: We always load thumb bitmap first, so we will
526666ea1b28a76aeba74744148b15099254d918671Owen Lin                    // reset the supp matrix for then thumb bitmap, and keep
527666ea1b28a76aeba74744148b15099254d918671Owen Lin                    // the supp matrix when the full bitmap is loaded.
528666ea1b28a76aeba74744148b15099254d918671Owen Lin                    mImageView.setImageRotateBitmapResetBase(bitmap, isThumb);
529666ea1b28a76aeba74744148b15099254d918671Owen Lin                    updateZoomButtonsEnabled();
530666ea1b28a76aeba74744148b15099254d918671Owen Lin                }
531666ea1b28a76aeba74744148b15099254d918671Owen Lin            }
532666ea1b28a76aeba74744148b15099254d918671Owen Lin        };
533666ea1b28a76aeba74744148b15099254d918671Owen Lin
534666ea1b28a76aeba74744148b15099254d918671Owen Lin        // Could be null if we're stopping a slide show in the course of pausing
535666ea1b28a76aeba74744148b15099254d918671Owen Lin        if (mGetter != null) {
536666ea1b28a76aeba74744148b15099254d918671Owen Lin            mGetter.setPosition(pos, cb, mAllImages, mHandler);
537666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
538666ea1b28a76aeba74744148b15099254d918671Owen Lin        updateActionIcons();
539666ea1b28a76aeba74744148b15099254d918671Owen Lin        if (showControls) showOnScreenControls();
540666ea1b28a76aeba74744148b15099254d918671Owen Lin        scheduleDismissOnScreenControls();
541666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
542666ea1b28a76aeba74744148b15099254d918671Owen Lin
543666ea1b28a76aeba74744148b15099254d918671Owen Lin    @Override
544666ea1b28a76aeba74744148b15099254d918671Owen Lin    public void onCreate(Bundle instanceState) {
545666ea1b28a76aeba74744148b15099254d918671Owen Lin        super.onCreate(instanceState);
546666ea1b28a76aeba74744148b15099254d918671Owen Lin
547666ea1b28a76aeba74744148b15099254d918671Owen Lin        Intent intent = getIntent();
548666ea1b28a76aeba74744148b15099254d918671Owen Lin        mFullScreenInNormalMode = intent.getBooleanExtra(
549666ea1b28a76aeba74744148b15099254d918671Owen Lin                MediaStore.EXTRA_FULL_SCREEN, true);
550666ea1b28a76aeba74744148b15099254d918671Owen Lin        mShowActionIcons = intent.getBooleanExtra(
551666ea1b28a76aeba74744148b15099254d918671Owen Lin                MediaStore.EXTRA_SHOW_ACTION_ICONS, true);
552666ea1b28a76aeba74744148b15099254d918671Owen Lin
553666ea1b28a76aeba74744148b15099254d918671Owen Lin        mPrefs = PreferenceManager.getDefaultSharedPreferences(this);
554666ea1b28a76aeba74744148b15099254d918671Owen Lin
555666ea1b28a76aeba74744148b15099254d918671Owen Lin        setDefaultKeyMode(DEFAULT_KEYS_SHORTCUT);
556666ea1b28a76aeba74744148b15099254d918671Owen Lin        requestWindowFeature(Window.FEATURE_NO_TITLE);
557666ea1b28a76aeba74744148b15099254d918671Owen Lin        setContentView(R.layout.viewimage);
558666ea1b28a76aeba74744148b15099254d918671Owen Lin
559666ea1b28a76aeba74744148b15099254d918671Owen Lin        mImageView = (ImageViewTouch) findViewById(R.id.image);
560666ea1b28a76aeba74744148b15099254d918671Owen Lin        mImageView.setEnableTrackballScroll(true);
561666ea1b28a76aeba74744148b15099254d918671Owen Lin        mCache = new BitmapCache(3);
562666ea1b28a76aeba74744148b15099254d918671Owen Lin        mImageView.setRecycler(mCache);
563666ea1b28a76aeba74744148b15099254d918671Owen Lin
564666ea1b28a76aeba74744148b15099254d918671Owen Lin        makeGetter();
565666ea1b28a76aeba74744148b15099254d918671Owen Lin
566666ea1b28a76aeba74744148b15099254d918671Owen Lin        mAnimationIndex = -1;
567666ea1b28a76aeba74744148b15099254d918671Owen Lin
568666ea1b28a76aeba74744148b15099254d918671Owen Lin        mSlideShowInAnimation = new Animation[] {
569666ea1b28a76aeba74744148b15099254d918671Owen Lin            makeInAnimation(R.anim.transition_in),
570666ea1b28a76aeba74744148b15099254d918671Owen Lin            makeInAnimation(R.anim.slide_in),
571666ea1b28a76aeba74744148b15099254d918671Owen Lin            makeInAnimation(R.anim.slide_in_vertical),
572666ea1b28a76aeba74744148b15099254d918671Owen Lin        };
573666ea1b28a76aeba74744148b15099254d918671Owen Lin
574666ea1b28a76aeba74744148b15099254d918671Owen Lin        mSlideShowOutAnimation = new Animation[] {
575666ea1b28a76aeba74744148b15099254d918671Owen Lin            makeOutAnimation(R.anim.transition_out),
576666ea1b28a76aeba74744148b15099254d918671Owen Lin            makeOutAnimation(R.anim.slide_out),
577666ea1b28a76aeba74744148b15099254d918671Owen Lin            makeOutAnimation(R.anim.slide_out_vertical),
578666ea1b28a76aeba74744148b15099254d918671Owen Lin        };
579666ea1b28a76aeba74744148b15099254d918671Owen Lin
580666ea1b28a76aeba74744148b15099254d918671Owen Lin        mSlideShowImageViews[0] =
581666ea1b28a76aeba74744148b15099254d918671Owen Lin                (ImageViewTouchBase) findViewById(R.id.image1_slideShow);
582666ea1b28a76aeba74744148b15099254d918671Owen Lin        mSlideShowImageViews[1] =
583666ea1b28a76aeba74744148b15099254d918671Owen Lin                (ImageViewTouchBase) findViewById(R.id.image2_slideShow);
584666ea1b28a76aeba74744148b15099254d918671Owen Lin        for (ImageViewTouchBase v : mSlideShowImageViews) {
585666ea1b28a76aeba74744148b15099254d918671Owen Lin            v.setVisibility(View.INVISIBLE);
586666ea1b28a76aeba74744148b15099254d918671Owen Lin            v.setRecycler(mCache);
587666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
588666ea1b28a76aeba74744148b15099254d918671Owen Lin
589666ea1b28a76aeba74744148b15099254d918671Owen Lin        mActionIconPanel = findViewById(R.id.action_icon_panel);
590666ea1b28a76aeba74744148b15099254d918671Owen Lin
591666ea1b28a76aeba74744148b15099254d918671Owen Lin        mParam = getIntent().getParcelableExtra(KEY_IMAGE_LIST);
592666ea1b28a76aeba74744148b15099254d918671Owen Lin
593666ea1b28a76aeba74744148b15099254d918671Owen Lin        boolean slideshow;
594666ea1b28a76aeba74744148b15099254d918671Owen Lin        if (instanceState != null) {
595666ea1b28a76aeba74744148b15099254d918671Owen Lin            mSavedUri = instanceState.getParcelable(STATE_URI);
596666ea1b28a76aeba74744148b15099254d918671Owen Lin            slideshow = instanceState.getBoolean(STATE_SLIDESHOW, false);
597666ea1b28a76aeba74744148b15099254d918671Owen Lin            mShowControls = instanceState.getBoolean(STATE_SHOW_CONTROLS, true);
598666ea1b28a76aeba74744148b15099254d918671Owen Lin        } else {
599666ea1b28a76aeba74744148b15099254d918671Owen Lin            mSavedUri = getIntent().getData();
600666ea1b28a76aeba74744148b15099254d918671Owen Lin            slideshow = intent.getBooleanExtra(EXTRA_SLIDESHOW, false);
601666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
602666ea1b28a76aeba74744148b15099254d918671Owen Lin
603666ea1b28a76aeba74744148b15099254d918671Owen Lin        // We only show action icons for URIs that we know we can share and
604666ea1b28a76aeba74744148b15099254d918671Owen Lin        // delete. Although we get read permission (for the images) from
605666ea1b28a76aeba74744148b15099254d918671Owen Lin        // applications like MMS, we cannot pass the permission to other
606666ea1b28a76aeba74744148b15099254d918671Owen Lin        // activities due to the current framework design.
607666ea1b28a76aeba74744148b15099254d918671Owen Lin        if (!MenuHelper.isWhiteListUri(mSavedUri)) {
608666ea1b28a76aeba74744148b15099254d918671Owen Lin            mShowActionIcons = false;
609666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
610666ea1b28a76aeba74744148b15099254d918671Owen Lin
611666ea1b28a76aeba74744148b15099254d918671Owen Lin        if (mShowActionIcons) {
612666ea1b28a76aeba74744148b15099254d918671Owen Lin            int[] pickIds = {R.id.attach, R.id.cancel};
613666ea1b28a76aeba74744148b15099254d918671Owen Lin            int[] normalIds = {R.id.setas, R.id.play, R.id.share, R.id.discard};
614666ea1b28a76aeba74744148b15099254d918671Owen Lin            int[] connectIds = isPickIntent() ? pickIds : normalIds;
615666ea1b28a76aeba74744148b15099254d918671Owen Lin            for (int id : connectIds) {
616666ea1b28a76aeba74744148b15099254d918671Owen Lin                View view = mActionIconPanel.findViewById(id);
617666ea1b28a76aeba74744148b15099254d918671Owen Lin                view.setVisibility(View.VISIBLE);
618666ea1b28a76aeba74744148b15099254d918671Owen Lin                view.setOnClickListener(this);
619666ea1b28a76aeba74744148b15099254d918671Owen Lin            }
620666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
621666ea1b28a76aeba74744148b15099254d918671Owen Lin
622666ea1b28a76aeba74744148b15099254d918671Owen Lin        // Don't show the "delete" icon for SingleImageList.
623666ea1b28a76aeba74744148b15099254d918671Owen Lin        if (ImageManager.isSingleImageMode(mSavedUri.toString())) {
624666ea1b28a76aeba74744148b15099254d918671Owen Lin            mActionIconPanel.findViewById(R.id.discard)
625666ea1b28a76aeba74744148b15099254d918671Owen Lin                    .setVisibility(View.GONE);
626666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
627666ea1b28a76aeba74744148b15099254d918671Owen Lin
628666ea1b28a76aeba74744148b15099254d918671Owen Lin        if (slideshow) {
629666ea1b28a76aeba74744148b15099254d918671Owen Lin            setMode(MODE_SLIDESHOW);
630666ea1b28a76aeba74744148b15099254d918671Owen Lin        } else {
631666ea1b28a76aeba74744148b15099254d918671Owen Lin            if (mFullScreenInNormalMode) {
632666ea1b28a76aeba74744148b15099254d918671Owen Lin                getWindow().addFlags(
633666ea1b28a76aeba74744148b15099254d918671Owen Lin                        WindowManager.LayoutParams.FLAG_FULLSCREEN);
634666ea1b28a76aeba74744148b15099254d918671Owen Lin            }
635666ea1b28a76aeba74744148b15099254d918671Owen Lin            if (mShowActionIcons) {
636666ea1b28a76aeba74744148b15099254d918671Owen Lin                mActionIconPanel.setVisibility(View.VISIBLE);
637666ea1b28a76aeba74744148b15099254d918671Owen Lin            }
638666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
639666ea1b28a76aeba74744148b15099254d918671Owen Lin
640666ea1b28a76aeba74744148b15099254d918671Owen Lin        setupOnScreenControls(findViewById(R.id.rootLayout), mImageView);
641666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
642666ea1b28a76aeba74744148b15099254d918671Owen Lin
643666ea1b28a76aeba74744148b15099254d918671Owen Lin    private void updateActionIcons() {
644666ea1b28a76aeba74744148b15099254d918671Owen Lin        if (isPickIntent()) return;
645666ea1b28a76aeba74744148b15099254d918671Owen Lin
646666ea1b28a76aeba74744148b15099254d918671Owen Lin        IImage image = mAllImages.getImageAt(mCurrentPosition);
647666ea1b28a76aeba74744148b15099254d918671Owen Lin        View panel = mActionIconPanel;
648666ea1b28a76aeba74744148b15099254d918671Owen Lin        if (image instanceof VideoObject) {
649666ea1b28a76aeba74744148b15099254d918671Owen Lin            panel.findViewById(R.id.setas).setVisibility(View.GONE);
650666ea1b28a76aeba74744148b15099254d918671Owen Lin            panel.findViewById(R.id.play).setVisibility(View.VISIBLE);
651666ea1b28a76aeba74744148b15099254d918671Owen Lin        } else {
652666ea1b28a76aeba74744148b15099254d918671Owen Lin            panel.findViewById(R.id.setas).setVisibility(View.VISIBLE);
653666ea1b28a76aeba74744148b15099254d918671Owen Lin            panel.findViewById(R.id.play).setVisibility(View.GONE);
654666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
655666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
656666ea1b28a76aeba74744148b15099254d918671Owen Lin
657666ea1b28a76aeba74744148b15099254d918671Owen Lin    private Animation makeInAnimation(int id) {
658666ea1b28a76aeba74744148b15099254d918671Owen Lin        Animation inAnimation = AnimationUtils.loadAnimation(this, id);
659666ea1b28a76aeba74744148b15099254d918671Owen Lin        return inAnimation;
660666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
661666ea1b28a76aeba74744148b15099254d918671Owen Lin
662666ea1b28a76aeba74744148b15099254d918671Owen Lin    private Animation makeOutAnimation(int id) {
663666ea1b28a76aeba74744148b15099254d918671Owen Lin        Animation outAnimation = AnimationUtils.loadAnimation(this, id);
664666ea1b28a76aeba74744148b15099254d918671Owen Lin        return outAnimation;
665666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
666666ea1b28a76aeba74744148b15099254d918671Owen Lin
667666ea1b28a76aeba74744148b15099254d918671Owen Lin    private static int getPreferencesInteger(
668666ea1b28a76aeba74744148b15099254d918671Owen Lin            SharedPreferences prefs, String key, int defaultValue) {
669666ea1b28a76aeba74744148b15099254d918671Owen Lin        String value = prefs.getString(key, null);
670666ea1b28a76aeba74744148b15099254d918671Owen Lin        try {
671666ea1b28a76aeba74744148b15099254d918671Owen Lin            return value == null ? defaultValue : Integer.parseInt(value);
672666ea1b28a76aeba74744148b15099254d918671Owen Lin        } catch (NumberFormatException ex) {
673666ea1b28a76aeba74744148b15099254d918671Owen Lin            Log.e(TAG, "couldn't parse preference: " + value, ex);
674666ea1b28a76aeba74744148b15099254d918671Owen Lin            return defaultValue;
675666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
676666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
677666ea1b28a76aeba74744148b15099254d918671Owen Lin
678666ea1b28a76aeba74744148b15099254d918671Owen Lin    void setMode(int mode) {
679666ea1b28a76aeba74744148b15099254d918671Owen Lin        if (mMode == mode) {
680666ea1b28a76aeba74744148b15099254d918671Owen Lin            return;
681666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
682666ea1b28a76aeba74744148b15099254d918671Owen Lin        View slideshowPanel = findViewById(R.id.slideShowContainer);
683666ea1b28a76aeba74744148b15099254d918671Owen Lin        View normalPanel = findViewById(R.id.abs);
684666ea1b28a76aeba74744148b15099254d918671Owen Lin
685666ea1b28a76aeba74744148b15099254d918671Owen Lin        Window win = getWindow();
686666ea1b28a76aeba74744148b15099254d918671Owen Lin        mMode = mode;
687666ea1b28a76aeba74744148b15099254d918671Owen Lin        if (mode == MODE_SLIDESHOW) {
688666ea1b28a76aeba74744148b15099254d918671Owen Lin            slideshowPanel.setVisibility(View.VISIBLE);
689666ea1b28a76aeba74744148b15099254d918671Owen Lin            normalPanel.setVisibility(View.GONE);
690666ea1b28a76aeba74744148b15099254d918671Owen Lin
691666ea1b28a76aeba74744148b15099254d918671Owen Lin            win.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN
692666ea1b28a76aeba74744148b15099254d918671Owen Lin                    | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
693666ea1b28a76aeba74744148b15099254d918671Owen Lin
694666ea1b28a76aeba74744148b15099254d918671Owen Lin            mImageView.clear();
695666ea1b28a76aeba74744148b15099254d918671Owen Lin            mActionIconPanel.setVisibility(View.GONE);
696666ea1b28a76aeba74744148b15099254d918671Owen Lin
697666ea1b28a76aeba74744148b15099254d918671Owen Lin            slideshowPanel.getRootView().requestLayout();
698666ea1b28a76aeba74744148b15099254d918671Owen Lin
699666ea1b28a76aeba74744148b15099254d918671Owen Lin            // The preferences we want to read:
700666ea1b28a76aeba74744148b15099254d918671Owen Lin            //   mUseShuffleOrder
701666ea1b28a76aeba74744148b15099254d918671Owen Lin            //   mSlideShowLoop
702666ea1b28a76aeba74744148b15099254d918671Owen Lin            //   mAnimationIndex
703666ea1b28a76aeba74744148b15099254d918671Owen Lin            //   mSlideShowInterval
704666ea1b28a76aeba74744148b15099254d918671Owen Lin
705666ea1b28a76aeba74744148b15099254d918671Owen Lin            mUseShuffleOrder = mPrefs.getBoolean(PREF_SHUFFLE_SLIDESHOW, false);
706666ea1b28a76aeba74744148b15099254d918671Owen Lin            mSlideShowLoop = mPrefs.getBoolean(PREF_SLIDESHOW_REPEAT, false);
707666ea1b28a76aeba74744148b15099254d918671Owen Lin            mAnimationIndex = getPreferencesInteger(
708666ea1b28a76aeba74744148b15099254d918671Owen Lin                    mPrefs, "pref_gallery_slideshow_transition_key", 0);
709666ea1b28a76aeba74744148b15099254d918671Owen Lin            mSlideShowInterval = getPreferencesInteger(
710666ea1b28a76aeba74744148b15099254d918671Owen Lin                    mPrefs, "pref_gallery_slideshow_interval_key", 3) * 1000;
711666ea1b28a76aeba74744148b15099254d918671Owen Lin        } else {
712666ea1b28a76aeba74744148b15099254d918671Owen Lin            slideshowPanel.setVisibility(View.GONE);
713666ea1b28a76aeba74744148b15099254d918671Owen Lin            normalPanel.setVisibility(View.VISIBLE);
714666ea1b28a76aeba74744148b15099254d918671Owen Lin
715666ea1b28a76aeba74744148b15099254d918671Owen Lin            win.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
716666ea1b28a76aeba74744148b15099254d918671Owen Lin            if (mFullScreenInNormalMode) {
717666ea1b28a76aeba74744148b15099254d918671Owen Lin                win.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
718666ea1b28a76aeba74744148b15099254d918671Owen Lin            } else {
719666ea1b28a76aeba74744148b15099254d918671Owen Lin                win.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
720666ea1b28a76aeba74744148b15099254d918671Owen Lin            }
721666ea1b28a76aeba74744148b15099254d918671Owen Lin
722666ea1b28a76aeba74744148b15099254d918671Owen Lin            if (mGetter != null) {
723666ea1b28a76aeba74744148b15099254d918671Owen Lin                mGetter.cancelCurrent();
724666ea1b28a76aeba74744148b15099254d918671Owen Lin            }
725666ea1b28a76aeba74744148b15099254d918671Owen Lin
726666ea1b28a76aeba74744148b15099254d918671Owen Lin            if (mShowActionIcons) {
727666ea1b28a76aeba74744148b15099254d918671Owen Lin                Animation animation = new AlphaAnimation(0F, 1F);
728666ea1b28a76aeba74744148b15099254d918671Owen Lin                animation.setDuration(500);
729666ea1b28a76aeba74744148b15099254d918671Owen Lin                mActionIconPanel.setAnimation(animation);
730666ea1b28a76aeba74744148b15099254d918671Owen Lin                mActionIconPanel.setVisibility(View.VISIBLE);
731666ea1b28a76aeba74744148b15099254d918671Owen Lin            }
732666ea1b28a76aeba74744148b15099254d918671Owen Lin
733666ea1b28a76aeba74744148b15099254d918671Owen Lin            ImageViewTouchBase dst = mImageView;
734666ea1b28a76aeba74744148b15099254d918671Owen Lin            dst.mLastXTouchPos = -1;
735666ea1b28a76aeba74744148b15099254d918671Owen Lin            dst.mLastYTouchPos = -1;
736666ea1b28a76aeba74744148b15099254d918671Owen Lin
737666ea1b28a76aeba74744148b15099254d918671Owen Lin            for (ImageViewTouchBase ivt : mSlideShowImageViews) {
738666ea1b28a76aeba74744148b15099254d918671Owen Lin                ivt.clear();
739666ea1b28a76aeba74744148b15099254d918671Owen Lin            }
740666ea1b28a76aeba74744148b15099254d918671Owen Lin
741666ea1b28a76aeba74744148b15099254d918671Owen Lin            mShuffleOrder = null;
742666ea1b28a76aeba74744148b15099254d918671Owen Lin
743666ea1b28a76aeba74744148b15099254d918671Owen Lin            // mGetter null is a proxy for being paused
744666ea1b28a76aeba74744148b15099254d918671Owen Lin            if (mGetter != null) {
745666ea1b28a76aeba74744148b15099254d918671Owen Lin                setImage(mCurrentPosition, true);
746666ea1b28a76aeba74744148b15099254d918671Owen Lin            }
747666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
748666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
749666ea1b28a76aeba74744148b15099254d918671Owen Lin
750666ea1b28a76aeba74744148b15099254d918671Owen Lin    private void generateShuffleOrder() {
751666ea1b28a76aeba74744148b15099254d918671Owen Lin        if (mShuffleOrder == null
752666ea1b28a76aeba74744148b15099254d918671Owen Lin                || mShuffleOrder.length != mAllImages.getCount()) {
753666ea1b28a76aeba74744148b15099254d918671Owen Lin            mShuffleOrder = new int[mAllImages.getCount()];
754666ea1b28a76aeba74744148b15099254d918671Owen Lin            for (int i = 0, n = mShuffleOrder.length; i < n; i++) {
755666ea1b28a76aeba74744148b15099254d918671Owen Lin                mShuffleOrder[i] = i;
756666ea1b28a76aeba74744148b15099254d918671Owen Lin            }
757666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
758666ea1b28a76aeba74744148b15099254d918671Owen Lin
759666ea1b28a76aeba74744148b15099254d918671Owen Lin        for (int i = mShuffleOrder.length - 1; i >= 0; i--) {
760666ea1b28a76aeba74744148b15099254d918671Owen Lin            int r = mRandom.nextInt(i + 1);
761666ea1b28a76aeba74744148b15099254d918671Owen Lin            if (r != i) {
762666ea1b28a76aeba74744148b15099254d918671Owen Lin                int tmp = mShuffleOrder[r];
763666ea1b28a76aeba74744148b15099254d918671Owen Lin                mShuffleOrder[r] = mShuffleOrder[i];
764666ea1b28a76aeba74744148b15099254d918671Owen Lin                mShuffleOrder[i] = tmp;
765666ea1b28a76aeba74744148b15099254d918671Owen Lin            }
766666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
767666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
768666ea1b28a76aeba74744148b15099254d918671Owen Lin
769666ea1b28a76aeba74744148b15099254d918671Owen Lin    private void loadNextImage(final int requestedPos, final long delay,
770666ea1b28a76aeba74744148b15099254d918671Owen Lin                               final boolean firstCall) {
771666ea1b28a76aeba74744148b15099254d918671Owen Lin        if (firstCall && mUseShuffleOrder) {
772666ea1b28a76aeba74744148b15099254d918671Owen Lin            generateShuffleOrder();
773666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
774666ea1b28a76aeba74744148b15099254d918671Owen Lin
775666ea1b28a76aeba74744148b15099254d918671Owen Lin        final long targetDisplayTime = System.currentTimeMillis() + delay;
776666ea1b28a76aeba74744148b15099254d918671Owen Lin
777666ea1b28a76aeba74744148b15099254d918671Owen Lin        ImageGetterCallback cb = new ImageGetterCallback() {
778666ea1b28a76aeba74744148b15099254d918671Owen Lin            public void completed() {
779666ea1b28a76aeba74744148b15099254d918671Owen Lin            }
780666ea1b28a76aeba74744148b15099254d918671Owen Lin
781666ea1b28a76aeba74744148b15099254d918671Owen Lin            public boolean wantsThumbnail(int pos, int offset) {
782666ea1b28a76aeba74744148b15099254d918671Owen Lin                return true;
783666ea1b28a76aeba74744148b15099254d918671Owen Lin            }
784666ea1b28a76aeba74744148b15099254d918671Owen Lin
785666ea1b28a76aeba74744148b15099254d918671Owen Lin            public boolean wantsFullImage(int pos, int offset) {
786666ea1b28a76aeba74744148b15099254d918671Owen Lin                return false;
787666ea1b28a76aeba74744148b15099254d918671Owen Lin            }
788666ea1b28a76aeba74744148b15099254d918671Owen Lin
789666ea1b28a76aeba74744148b15099254d918671Owen Lin            public int [] loadOrder() {
790666ea1b28a76aeba74744148b15099254d918671Owen Lin                return sOrderSlideshow;
791666ea1b28a76aeba74744148b15099254d918671Owen Lin            }
792666ea1b28a76aeba74744148b15099254d918671Owen Lin
793666ea1b28a76aeba74744148b15099254d918671Owen Lin            public int fullImageSizeToUse(int pos, int offset) {
794666ea1b28a76aeba74744148b15099254d918671Owen Lin                return 480; // TODO compute this
795666ea1b28a76aeba74744148b15099254d918671Owen Lin            }
796666ea1b28a76aeba74744148b15099254d918671Owen Lin
797666ea1b28a76aeba74744148b15099254d918671Owen Lin            public void imageLoaded(final int pos, final int offset,
798666ea1b28a76aeba74744148b15099254d918671Owen Lin                    final RotateBitmap bitmap, final boolean isThumb) {
799666ea1b28a76aeba74744148b15099254d918671Owen Lin                long timeRemaining = Math.max(0,
800666ea1b28a76aeba74744148b15099254d918671Owen Lin                        targetDisplayTime - System.currentTimeMillis());
801666ea1b28a76aeba74744148b15099254d918671Owen Lin                mHandler.postDelayedGetterCallback(new Runnable() {
802666ea1b28a76aeba74744148b15099254d918671Owen Lin                    public void run() {
803666ea1b28a76aeba74744148b15099254d918671Owen Lin                        if (mMode == MODE_NORMAL) {
804666ea1b28a76aeba74744148b15099254d918671Owen Lin                            return;
805666ea1b28a76aeba74744148b15099254d918671Owen Lin                        }
806666ea1b28a76aeba74744148b15099254d918671Owen Lin
807666ea1b28a76aeba74744148b15099254d918671Owen Lin                        ImageViewTouchBase oldView =
808666ea1b28a76aeba74744148b15099254d918671Owen Lin                                mSlideShowImageViews[mSlideShowImageCurrent];
809666ea1b28a76aeba74744148b15099254d918671Owen Lin
810666ea1b28a76aeba74744148b15099254d918671Owen Lin                        if (++mSlideShowImageCurrent
811666ea1b28a76aeba74744148b15099254d918671Owen Lin                                == mSlideShowImageViews.length) {
812666ea1b28a76aeba74744148b15099254d918671Owen Lin                            mSlideShowImageCurrent = 0;
813666ea1b28a76aeba74744148b15099254d918671Owen Lin                        }
814666ea1b28a76aeba74744148b15099254d918671Owen Lin
815666ea1b28a76aeba74744148b15099254d918671Owen Lin                        ImageViewTouchBase newView =
816666ea1b28a76aeba74744148b15099254d918671Owen Lin                                mSlideShowImageViews[mSlideShowImageCurrent];
817666ea1b28a76aeba74744148b15099254d918671Owen Lin                        newView.setVisibility(View.VISIBLE);
818666ea1b28a76aeba74744148b15099254d918671Owen Lin                        newView.setImageRotateBitmapResetBase(bitmap, true);
819666ea1b28a76aeba74744148b15099254d918671Owen Lin                        newView.bringToFront();
820666ea1b28a76aeba74744148b15099254d918671Owen Lin
821666ea1b28a76aeba74744148b15099254d918671Owen Lin                        int animation = 0;
822666ea1b28a76aeba74744148b15099254d918671Owen Lin
823666ea1b28a76aeba74744148b15099254d918671Owen Lin                        if (mAnimationIndex == -1) {
824666ea1b28a76aeba74744148b15099254d918671Owen Lin                            int n = mRandom.nextInt(
825666ea1b28a76aeba74744148b15099254d918671Owen Lin                                    mSlideShowInAnimation.length);
826666ea1b28a76aeba74744148b15099254d918671Owen Lin                            animation = n;
827666ea1b28a76aeba74744148b15099254d918671Owen Lin                        } else {
828666ea1b28a76aeba74744148b15099254d918671Owen Lin                            animation = mAnimationIndex;
829666ea1b28a76aeba74744148b15099254d918671Owen Lin                        }
830666ea1b28a76aeba74744148b15099254d918671Owen Lin
831666ea1b28a76aeba74744148b15099254d918671Owen Lin                        Animation aIn = mSlideShowInAnimation[animation];
832666ea1b28a76aeba74744148b15099254d918671Owen Lin                        newView.startAnimation(aIn);
833666ea1b28a76aeba74744148b15099254d918671Owen Lin                        newView.setVisibility(View.VISIBLE);
834666ea1b28a76aeba74744148b15099254d918671Owen Lin
835666ea1b28a76aeba74744148b15099254d918671Owen Lin                        Animation aOut = mSlideShowOutAnimation[animation];
836666ea1b28a76aeba74744148b15099254d918671Owen Lin                        oldView.setVisibility(View.INVISIBLE);
837666ea1b28a76aeba74744148b15099254d918671Owen Lin                        oldView.startAnimation(aOut);
838666ea1b28a76aeba74744148b15099254d918671Owen Lin
839666ea1b28a76aeba74744148b15099254d918671Owen Lin                        mCurrentPosition = requestedPos;
840666ea1b28a76aeba74744148b15099254d918671Owen Lin
841666ea1b28a76aeba74744148b15099254d918671Owen Lin                        if (mCurrentPosition == mLastSlideShowImage
842666ea1b28a76aeba74744148b15099254d918671Owen Lin                                && !firstCall) {
843666ea1b28a76aeba74744148b15099254d918671Owen Lin                            if (mSlideShowLoop) {
844666ea1b28a76aeba74744148b15099254d918671Owen Lin                                if (mUseShuffleOrder) {
845666ea1b28a76aeba74744148b15099254d918671Owen Lin                                    generateShuffleOrder();
846666ea1b28a76aeba74744148b15099254d918671Owen Lin                                }
847666ea1b28a76aeba74744148b15099254d918671Owen Lin                            } else {
848666ea1b28a76aeba74744148b15099254d918671Owen Lin                                setMode(MODE_NORMAL);
849666ea1b28a76aeba74744148b15099254d918671Owen Lin                                return;
850666ea1b28a76aeba74744148b15099254d918671Owen Lin                            }
851666ea1b28a76aeba74744148b15099254d918671Owen Lin                        }
852666ea1b28a76aeba74744148b15099254d918671Owen Lin
853666ea1b28a76aeba74744148b15099254d918671Owen Lin                        loadNextImage(
854666ea1b28a76aeba74744148b15099254d918671Owen Lin                                (mCurrentPosition + 1) % mAllImages.getCount(),
855666ea1b28a76aeba74744148b15099254d918671Owen Lin                                mSlideShowInterval, false);
856666ea1b28a76aeba74744148b15099254d918671Owen Lin                    }
857666ea1b28a76aeba74744148b15099254d918671Owen Lin                }, timeRemaining);
858666ea1b28a76aeba74744148b15099254d918671Owen Lin            }
859666ea1b28a76aeba74744148b15099254d918671Owen Lin        };
860666ea1b28a76aeba74744148b15099254d918671Owen Lin        // Could be null if we're stopping a slide show in the course of pausing
861666ea1b28a76aeba74744148b15099254d918671Owen Lin        if (mGetter != null) {
862666ea1b28a76aeba74744148b15099254d918671Owen Lin            int pos = requestedPos;
863666ea1b28a76aeba74744148b15099254d918671Owen Lin            if (mShuffleOrder != null) {
864666ea1b28a76aeba74744148b15099254d918671Owen Lin                pos = mShuffleOrder[pos];
865666ea1b28a76aeba74744148b15099254d918671Owen Lin            }
866666ea1b28a76aeba74744148b15099254d918671Owen Lin            mGetter.setPosition(pos, cb, mAllImages, mHandler);
867666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
868666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
869666ea1b28a76aeba74744148b15099254d918671Owen Lin
870666ea1b28a76aeba74744148b15099254d918671Owen Lin    private void makeGetter() {
871666ea1b28a76aeba74744148b15099254d918671Owen Lin        mGetter = new ImageGetter(getContentResolver());
872666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
873666ea1b28a76aeba74744148b15099254d918671Owen Lin
874666ea1b28a76aeba74744148b15099254d918671Owen Lin    private IImageList buildImageListFromUri(Uri uri) {
875666ea1b28a76aeba74744148b15099254d918671Owen Lin        String sortOrder = mPrefs.getString(
876666ea1b28a76aeba74744148b15099254d918671Owen Lin                "pref_gallery_sort_key", "descending");
877666ea1b28a76aeba74744148b15099254d918671Owen Lin        int sort = sortOrder.equals("ascending")
878666ea1b28a76aeba74744148b15099254d918671Owen Lin                ? ImageManager.SORT_ASCENDING
879666ea1b28a76aeba74744148b15099254d918671Owen Lin                : ImageManager.SORT_DESCENDING;
880666ea1b28a76aeba74744148b15099254d918671Owen Lin        return ImageManager.makeImageList(getContentResolver(), uri, sort);
881666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
882666ea1b28a76aeba74744148b15099254d918671Owen Lin
883666ea1b28a76aeba74744148b15099254d918671Owen Lin    private boolean init(Uri uri) {
884666ea1b28a76aeba74744148b15099254d918671Owen Lin        if (uri == null) return false;
885666ea1b28a76aeba74744148b15099254d918671Owen Lin        mAllImages = (mParam == null)
886666ea1b28a76aeba74744148b15099254d918671Owen Lin                ? buildImageListFromUri(uri)
887666ea1b28a76aeba74744148b15099254d918671Owen Lin                : ImageManager.makeImageList(getContentResolver(), mParam);
888666ea1b28a76aeba74744148b15099254d918671Owen Lin        IImage image = mAllImages.getImageForUri(uri);
889666ea1b28a76aeba74744148b15099254d918671Owen Lin        if (image == null) return false;
890666ea1b28a76aeba74744148b15099254d918671Owen Lin        mCurrentPosition = mAllImages.getImageIndex(image);
891666ea1b28a76aeba74744148b15099254d918671Owen Lin        mLastSlideShowImage = mCurrentPosition;
892666ea1b28a76aeba74744148b15099254d918671Owen Lin        return true;
893666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
894666ea1b28a76aeba74744148b15099254d918671Owen Lin
895666ea1b28a76aeba74744148b15099254d918671Owen Lin    private Uri getCurrentUri() {
896666ea1b28a76aeba74744148b15099254d918671Owen Lin        if (mAllImages.getCount() == 0) return null;
897666ea1b28a76aeba74744148b15099254d918671Owen Lin        IImage image = mAllImages.getImageAt(mCurrentPosition);
898666ea1b28a76aeba74744148b15099254d918671Owen Lin        return image.fullSizeImageUri();
899666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
900666ea1b28a76aeba74744148b15099254d918671Owen Lin
901666ea1b28a76aeba74744148b15099254d918671Owen Lin    @Override
902666ea1b28a76aeba74744148b15099254d918671Owen Lin    public void onSaveInstanceState(Bundle b) {
903666ea1b28a76aeba74744148b15099254d918671Owen Lin        super.onSaveInstanceState(b);
904666ea1b28a76aeba74744148b15099254d918671Owen Lin        b.putParcelable(STATE_URI,
905666ea1b28a76aeba74744148b15099254d918671Owen Lin                mAllImages.getImageAt(mCurrentPosition).fullSizeImageUri());
906666ea1b28a76aeba74744148b15099254d918671Owen Lin        b.putBoolean(STATE_SLIDESHOW, mMode == MODE_SLIDESHOW);
907666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
908666ea1b28a76aeba74744148b15099254d918671Owen Lin
909666ea1b28a76aeba74744148b15099254d918671Owen Lin    @Override
910666ea1b28a76aeba74744148b15099254d918671Owen Lin    public void onStart() {
911666ea1b28a76aeba74744148b15099254d918671Owen Lin        super.onStart();
912666ea1b28a76aeba74744148b15099254d918671Owen Lin        mPaused = false;
913666ea1b28a76aeba74744148b15099254d918671Owen Lin
914666ea1b28a76aeba74744148b15099254d918671Owen Lin        if (!init(mSavedUri)) {
915666ea1b28a76aeba74744148b15099254d918671Owen Lin            Log.w(TAG, "init failed: " + mSavedUri);
916666ea1b28a76aeba74744148b15099254d918671Owen Lin            finish();
917666ea1b28a76aeba74744148b15099254d918671Owen Lin            return;
918666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
919666ea1b28a76aeba74744148b15099254d918671Owen Lin
920666ea1b28a76aeba74744148b15099254d918671Owen Lin        // normally this will never be zero but if one "backs" into this
921666ea1b28a76aeba74744148b15099254d918671Owen Lin        // activity after removing the sdcard it could be zero.  in that
922666ea1b28a76aeba74744148b15099254d918671Owen Lin        // case just "finish" since there's nothing useful that can happen.
923666ea1b28a76aeba74744148b15099254d918671Owen Lin        int count = mAllImages.getCount();
924666ea1b28a76aeba74744148b15099254d918671Owen Lin        if (count == 0) {
925666ea1b28a76aeba74744148b15099254d918671Owen Lin            finish();
926666ea1b28a76aeba74744148b15099254d918671Owen Lin            return;
927666ea1b28a76aeba74744148b15099254d918671Owen Lin        } else if (count <= mCurrentPosition) {
928666ea1b28a76aeba74744148b15099254d918671Owen Lin            mCurrentPosition = count - 1;
929666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
930666ea1b28a76aeba74744148b15099254d918671Owen Lin
931666ea1b28a76aeba74744148b15099254d918671Owen Lin        if (mGetter == null) {
932666ea1b28a76aeba74744148b15099254d918671Owen Lin            makeGetter();
933666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
934666ea1b28a76aeba74744148b15099254d918671Owen Lin
935666ea1b28a76aeba74744148b15099254d918671Owen Lin        if (mMode == MODE_SLIDESHOW) {
936666ea1b28a76aeba74744148b15099254d918671Owen Lin            loadNextImage(mCurrentPosition, 0, true);
937666ea1b28a76aeba74744148b15099254d918671Owen Lin        } else {  // MODE_NORMAL
938666ea1b28a76aeba74744148b15099254d918671Owen Lin            setImage(mCurrentPosition, mShowControls);
939666ea1b28a76aeba74744148b15099254d918671Owen Lin            mShowControls = false;
940666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
941666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
942666ea1b28a76aeba74744148b15099254d918671Owen Lin
943666ea1b28a76aeba74744148b15099254d918671Owen Lin    @Override
944666ea1b28a76aeba74744148b15099254d918671Owen Lin    public void onStop() {
945666ea1b28a76aeba74744148b15099254d918671Owen Lin        super.onStop();
946666ea1b28a76aeba74744148b15099254d918671Owen Lin        mPaused = true;
947666ea1b28a76aeba74744148b15099254d918671Owen Lin
948666ea1b28a76aeba74744148b15099254d918671Owen Lin        // mGetter could be null if we call finish() and leave early in
949666ea1b28a76aeba74744148b15099254d918671Owen Lin        // onStart().
950666ea1b28a76aeba74744148b15099254d918671Owen Lin        if (mGetter != null) {
951666ea1b28a76aeba74744148b15099254d918671Owen Lin            mGetter.cancelCurrent();
952666ea1b28a76aeba74744148b15099254d918671Owen Lin            mGetter.stop();
953666ea1b28a76aeba74744148b15099254d918671Owen Lin            mGetter = null;
954666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
955666ea1b28a76aeba74744148b15099254d918671Owen Lin        setMode(MODE_NORMAL);
956666ea1b28a76aeba74744148b15099254d918671Owen Lin
957666ea1b28a76aeba74744148b15099254d918671Owen Lin        // removing all callback in the message queue
958666ea1b28a76aeba74744148b15099254d918671Owen Lin        mHandler.removeAllGetterCallbacks();
959666ea1b28a76aeba74744148b15099254d918671Owen Lin
960666ea1b28a76aeba74744148b15099254d918671Owen Lin        if (mAllImages != null) {
961666ea1b28a76aeba74744148b15099254d918671Owen Lin            mSavedUri = getCurrentUri();
962666ea1b28a76aeba74744148b15099254d918671Owen Lin            mAllImages.close();
963666ea1b28a76aeba74744148b15099254d918671Owen Lin            mAllImages = null;
964666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
965666ea1b28a76aeba74744148b15099254d918671Owen Lin
966666ea1b28a76aeba74744148b15099254d918671Owen Lin        hideOnScreenControls();
967666ea1b28a76aeba74744148b15099254d918671Owen Lin        mImageView.clear();
968666ea1b28a76aeba74744148b15099254d918671Owen Lin        mCache.clear();
969666ea1b28a76aeba74744148b15099254d918671Owen Lin
970666ea1b28a76aeba74744148b15099254d918671Owen Lin        for (ImageViewTouchBase iv : mSlideShowImageViews) {
971666ea1b28a76aeba74744148b15099254d918671Owen Lin            iv.clear();
972666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
973666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
974666ea1b28a76aeba74744148b15099254d918671Owen Lin
975666ea1b28a76aeba74744148b15099254d918671Owen Lin    private void startShareMediaActivity(IImage image) {
976666ea1b28a76aeba74744148b15099254d918671Owen Lin        boolean isVideo = image instanceof VideoObject;
977666ea1b28a76aeba74744148b15099254d918671Owen Lin        Intent intent = new Intent();
978666ea1b28a76aeba74744148b15099254d918671Owen Lin        intent.setAction(Intent.ACTION_SEND);
979666ea1b28a76aeba74744148b15099254d918671Owen Lin        intent.setType(image.getMimeType());
980666ea1b28a76aeba74744148b15099254d918671Owen Lin        intent.putExtra(Intent.EXTRA_STREAM, image.fullSizeImageUri());
981666ea1b28a76aeba74744148b15099254d918671Owen Lin        try {
982666ea1b28a76aeba74744148b15099254d918671Owen Lin            startActivity(Intent.createChooser(intent, getText(
983666ea1b28a76aeba74744148b15099254d918671Owen Lin                    isVideo ? R.string.sendVideo : R.string.sendImage)));
984666ea1b28a76aeba74744148b15099254d918671Owen Lin        } catch (android.content.ActivityNotFoundException ex) {
985666ea1b28a76aeba74744148b15099254d918671Owen Lin            Toast.makeText(this, isVideo
986666ea1b28a76aeba74744148b15099254d918671Owen Lin                    ? R.string.no_way_to_share_image
987666ea1b28a76aeba74744148b15099254d918671Owen Lin                    : R.string.no_way_to_share_video,
988666ea1b28a76aeba74744148b15099254d918671Owen Lin                    Toast.LENGTH_SHORT).show();
989666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
990666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
991666ea1b28a76aeba74744148b15099254d918671Owen Lin
992666ea1b28a76aeba74744148b15099254d918671Owen Lin    private void startPlayVideoActivity() {
993666ea1b28a76aeba74744148b15099254d918671Owen Lin        IImage image = mAllImages.getImageAt(mCurrentPosition);
994666ea1b28a76aeba74744148b15099254d918671Owen Lin        Intent intent = new Intent(
995666ea1b28a76aeba74744148b15099254d918671Owen Lin                Intent.ACTION_VIEW, image.fullSizeImageUri());
996666ea1b28a76aeba74744148b15099254d918671Owen Lin        try {
997666ea1b28a76aeba74744148b15099254d918671Owen Lin            startActivity(intent);
998666ea1b28a76aeba74744148b15099254d918671Owen Lin        } catch (android.content.ActivityNotFoundException ex) {
999666ea1b28a76aeba74744148b15099254d918671Owen Lin            Log.e(TAG, "Couldn't view video " + image.fullSizeImageUri(), ex);
1000666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
1001666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
1002666ea1b28a76aeba74744148b15099254d918671Owen Lin
1003666ea1b28a76aeba74744148b15099254d918671Owen Lin    public void onClick(View v) {
1004666ea1b28a76aeba74744148b15099254d918671Owen Lin        switch (v.getId()) {
1005666ea1b28a76aeba74744148b15099254d918671Owen Lin            case R.id.discard:
1006666ea1b28a76aeba74744148b15099254d918671Owen Lin                MenuHelper.deletePhoto(this, mDeletePhotoRunnable);
1007666ea1b28a76aeba74744148b15099254d918671Owen Lin                break;
1008666ea1b28a76aeba74744148b15099254d918671Owen Lin            case R.id.play:
1009666ea1b28a76aeba74744148b15099254d918671Owen Lin                startPlayVideoActivity();
1010666ea1b28a76aeba74744148b15099254d918671Owen Lin                break;
1011666ea1b28a76aeba74744148b15099254d918671Owen Lin            case R.id.share: {
1012666ea1b28a76aeba74744148b15099254d918671Owen Lin                IImage image = mAllImages.getImageAt(mCurrentPosition);
1013666ea1b28a76aeba74744148b15099254d918671Owen Lin                if (!MenuHelper.isWhiteListUri(image.fullSizeImageUri())) {
1014666ea1b28a76aeba74744148b15099254d918671Owen Lin                    return;
1015666ea1b28a76aeba74744148b15099254d918671Owen Lin                }
1016666ea1b28a76aeba74744148b15099254d918671Owen Lin                startShareMediaActivity(image);
1017666ea1b28a76aeba74744148b15099254d918671Owen Lin                break;
1018666ea1b28a76aeba74744148b15099254d918671Owen Lin            }
1019666ea1b28a76aeba74744148b15099254d918671Owen Lin            case R.id.setas: {
1020666ea1b28a76aeba74744148b15099254d918671Owen Lin                IImage image = mAllImages.getImageAt(mCurrentPosition);
1021666ea1b28a76aeba74744148b15099254d918671Owen Lin                Intent intent = Util.createSetAsIntent(image);
1022666ea1b28a76aeba74744148b15099254d918671Owen Lin                try {
1023666ea1b28a76aeba74744148b15099254d918671Owen Lin                    startActivity(Intent.createChooser(
1024666ea1b28a76aeba74744148b15099254d918671Owen Lin                            intent, getText(R.string.setImage)));
1025666ea1b28a76aeba74744148b15099254d918671Owen Lin                } catch (android.content.ActivityNotFoundException ex) {
1026666ea1b28a76aeba74744148b15099254d918671Owen Lin                    Toast.makeText(this, R.string.no_way_to_share_video,
1027666ea1b28a76aeba74744148b15099254d918671Owen Lin                            Toast.LENGTH_SHORT).show();
1028666ea1b28a76aeba74744148b15099254d918671Owen Lin                }
1029666ea1b28a76aeba74744148b15099254d918671Owen Lin                break;
1030666ea1b28a76aeba74744148b15099254d918671Owen Lin            }
1031666ea1b28a76aeba74744148b15099254d918671Owen Lin            case R.id.next_image:
1032666ea1b28a76aeba74744148b15099254d918671Owen Lin                moveNextOrPrevious(1);
1033666ea1b28a76aeba74744148b15099254d918671Owen Lin                break;
1034666ea1b28a76aeba74744148b15099254d918671Owen Lin            case R.id.prev_image:
1035666ea1b28a76aeba74744148b15099254d918671Owen Lin                moveNextOrPrevious(-1);
1036666ea1b28a76aeba74744148b15099254d918671Owen Lin                break;
1037666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
1038666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
1039666ea1b28a76aeba74744148b15099254d918671Owen Lin
1040666ea1b28a76aeba74744148b15099254d918671Owen Lin    private void moveNextOrPrevious(int delta) {
1041666ea1b28a76aeba74744148b15099254d918671Owen Lin        int nextImagePos = mCurrentPosition + delta;
1042666ea1b28a76aeba74744148b15099254d918671Owen Lin        if ((0 <= nextImagePos) && (nextImagePos < mAllImages.getCount())) {
1043666ea1b28a76aeba74744148b15099254d918671Owen Lin            setImage(nextImagePos, true);
1044666ea1b28a76aeba74744148b15099254d918671Owen Lin            showOnScreenControls();
1045666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
1046666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
1047666ea1b28a76aeba74744148b15099254d918671Owen Lin
1048666ea1b28a76aeba74744148b15099254d918671Owen Lin    @Override
1049666ea1b28a76aeba74744148b15099254d918671Owen Lin    protected void onActivityResult(int requestCode, int resultCode,
1050666ea1b28a76aeba74744148b15099254d918671Owen Lin            Intent data) {
1051666ea1b28a76aeba74744148b15099254d918671Owen Lin        switch (requestCode) {
1052666ea1b28a76aeba74744148b15099254d918671Owen Lin            case MenuHelper.RESULT_COMMON_MENU_CROP:
1053666ea1b28a76aeba74744148b15099254d918671Owen Lin                if (resultCode == RESULT_OK) {
1054666ea1b28a76aeba74744148b15099254d918671Owen Lin                    // The CropImage activity passes back the Uri of the
1055666ea1b28a76aeba74744148b15099254d918671Owen Lin                    // cropped image as the Action rather than the Data.
1056666ea1b28a76aeba74744148b15099254d918671Owen Lin                    mSavedUri = Uri.parse(data.getAction());
1057666ea1b28a76aeba74744148b15099254d918671Owen Lin
1058666ea1b28a76aeba74744148b15099254d918671Owen Lin                    // if onStart() runs before, then set the returned
1059666ea1b28a76aeba74744148b15099254d918671Owen Lin                    // image as currentImage.
1060666ea1b28a76aeba74744148b15099254d918671Owen Lin                    if (mAllImages != null) {
1061666ea1b28a76aeba74744148b15099254d918671Owen Lin                        IImage image = mAllImages.getImageForUri(mSavedUri);
1062666ea1b28a76aeba74744148b15099254d918671Owen Lin                        // image could be null if SD card is removed.
1063666ea1b28a76aeba74744148b15099254d918671Owen Lin                        if (image == null) {
1064666ea1b28a76aeba74744148b15099254d918671Owen Lin                            finish();
1065666ea1b28a76aeba74744148b15099254d918671Owen Lin                        } else {
1066666ea1b28a76aeba74744148b15099254d918671Owen Lin                            mCurrentPosition = mAllImages.getImageIndex(image);
1067666ea1b28a76aeba74744148b15099254d918671Owen Lin                            setImage(mCurrentPosition, false);
1068666ea1b28a76aeba74744148b15099254d918671Owen Lin                        }
1069666ea1b28a76aeba74744148b15099254d918671Owen Lin                    }
1070666ea1b28a76aeba74744148b15099254d918671Owen Lin                }
1071666ea1b28a76aeba74744148b15099254d918671Owen Lin                break;
1072666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
1073666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
1074666ea1b28a76aeba74744148b15099254d918671Owen Lin}
1075666ea1b28a76aeba74744148b15099254d918671Owen Lin
1076666ea1b28a76aeba74744148b15099254d918671Owen Linclass ImageViewTouch extends ImageViewTouchBase {
1077666ea1b28a76aeba74744148b15099254d918671Owen Lin    private final ViewImage mViewImage;
1078666ea1b28a76aeba74744148b15099254d918671Owen Lin    private boolean mEnableTrackballScroll;
1079666ea1b28a76aeba74744148b15099254d918671Owen Lin
1080666ea1b28a76aeba74744148b15099254d918671Owen Lin    public ImageViewTouch(Context context) {
1081666ea1b28a76aeba74744148b15099254d918671Owen Lin        super(context);
1082666ea1b28a76aeba74744148b15099254d918671Owen Lin        mViewImage = (ViewImage) context;
1083666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
1084666ea1b28a76aeba74744148b15099254d918671Owen Lin
1085666ea1b28a76aeba74744148b15099254d918671Owen Lin    public ImageViewTouch(Context context, AttributeSet attrs) {
1086666ea1b28a76aeba74744148b15099254d918671Owen Lin        super(context, attrs);
1087666ea1b28a76aeba74744148b15099254d918671Owen Lin        mViewImage = (ViewImage) context;
1088666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
1089666ea1b28a76aeba74744148b15099254d918671Owen Lin
1090666ea1b28a76aeba74744148b15099254d918671Owen Lin    public void setEnableTrackballScroll(boolean enable) {
1091666ea1b28a76aeba74744148b15099254d918671Owen Lin        mEnableTrackballScroll = enable;
1092666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
1093666ea1b28a76aeba74744148b15099254d918671Owen Lin
1094666ea1b28a76aeba74744148b15099254d918671Owen Lin    protected void postTranslateCenter(float dx, float dy) {
1095666ea1b28a76aeba74744148b15099254d918671Owen Lin        super.postTranslate(dx, dy);
1096666ea1b28a76aeba74744148b15099254d918671Owen Lin        center(true, true);
1097666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
1098666ea1b28a76aeba74744148b15099254d918671Owen Lin
1099666ea1b28a76aeba74744148b15099254d918671Owen Lin    private static final float PAN_RATE = 20;
1100666ea1b28a76aeba74744148b15099254d918671Owen Lin
1101666ea1b28a76aeba74744148b15099254d918671Owen Lin    // This is the time we allow the dpad to change the image position again.
1102666ea1b28a76aeba74744148b15099254d918671Owen Lin    private long mNextChangePositionTime;
1103666ea1b28a76aeba74744148b15099254d918671Owen Lin
1104666ea1b28a76aeba74744148b15099254d918671Owen Lin    @Override
1105666ea1b28a76aeba74744148b15099254d918671Owen Lin    public boolean onKeyDown(int keyCode, KeyEvent event) {
1106666ea1b28a76aeba74744148b15099254d918671Owen Lin        if (mViewImage.mPaused) return false;
1107666ea1b28a76aeba74744148b15099254d918671Owen Lin
1108666ea1b28a76aeba74744148b15099254d918671Owen Lin        // Don't respond to arrow keys if trackball scrolling is not enabled
1109666ea1b28a76aeba74744148b15099254d918671Owen Lin        if (!mEnableTrackballScroll) {
1110666ea1b28a76aeba74744148b15099254d918671Owen Lin            if ((keyCode >= KeyEvent.KEYCODE_DPAD_UP)
1111666ea1b28a76aeba74744148b15099254d918671Owen Lin                    && (keyCode <= KeyEvent.KEYCODE_DPAD_RIGHT)) {
1112666ea1b28a76aeba74744148b15099254d918671Owen Lin                return super.onKeyDown(keyCode, event);
1113666ea1b28a76aeba74744148b15099254d918671Owen Lin            }
1114666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
1115666ea1b28a76aeba74744148b15099254d918671Owen Lin
1116666ea1b28a76aeba74744148b15099254d918671Owen Lin        int current = mViewImage.mCurrentPosition;
1117666ea1b28a76aeba74744148b15099254d918671Owen Lin
1118666ea1b28a76aeba74744148b15099254d918671Owen Lin        int nextImagePos = -2; // default no next image
1119666ea1b28a76aeba74744148b15099254d918671Owen Lin        try {
1120666ea1b28a76aeba74744148b15099254d918671Owen Lin            switch (keyCode) {
1121666ea1b28a76aeba74744148b15099254d918671Owen Lin                case KeyEvent.KEYCODE_DPAD_CENTER: {
1122666ea1b28a76aeba74744148b15099254d918671Owen Lin                    if (mViewImage.isPickIntent()) {
1123666ea1b28a76aeba74744148b15099254d918671Owen Lin                        IImage img = mViewImage.mAllImages
1124666ea1b28a76aeba74744148b15099254d918671Owen Lin                                .getImageAt(mViewImage.mCurrentPosition);
1125666ea1b28a76aeba74744148b15099254d918671Owen Lin                        mViewImage.setResult(ViewImage.RESULT_OK,
1126666ea1b28a76aeba74744148b15099254d918671Owen Lin                                 new Intent().setData(img.fullSizeImageUri()));
1127666ea1b28a76aeba74744148b15099254d918671Owen Lin                        mViewImage.finish();
1128666ea1b28a76aeba74744148b15099254d918671Owen Lin                    }
1129666ea1b28a76aeba74744148b15099254d918671Owen Lin                    break;
1130666ea1b28a76aeba74744148b15099254d918671Owen Lin                }
1131666ea1b28a76aeba74744148b15099254d918671Owen Lin                case KeyEvent.KEYCODE_DPAD_LEFT: {
1132666ea1b28a76aeba74744148b15099254d918671Owen Lin                    if (getScale() <= 1F && event.getEventTime()
1133666ea1b28a76aeba74744148b15099254d918671Owen Lin                            >= mNextChangePositionTime) {
1134666ea1b28a76aeba74744148b15099254d918671Owen Lin                        nextImagePos = current - 1;
1135666ea1b28a76aeba74744148b15099254d918671Owen Lin                        mNextChangePositionTime = event.getEventTime() + 500;
1136666ea1b28a76aeba74744148b15099254d918671Owen Lin                    } else {
1137666ea1b28a76aeba74744148b15099254d918671Owen Lin                        panBy(PAN_RATE, 0);
1138666ea1b28a76aeba74744148b15099254d918671Owen Lin                        center(true, false);
1139666ea1b28a76aeba74744148b15099254d918671Owen Lin                    }
1140666ea1b28a76aeba74744148b15099254d918671Owen Lin                    return true;
1141666ea1b28a76aeba74744148b15099254d918671Owen Lin                }
1142666ea1b28a76aeba74744148b15099254d918671Owen Lin                case KeyEvent.KEYCODE_DPAD_RIGHT: {
1143666ea1b28a76aeba74744148b15099254d918671Owen Lin                    if (getScale() <= 1F && event.getEventTime()
1144666ea1b28a76aeba74744148b15099254d918671Owen Lin                            >= mNextChangePositionTime) {
1145666ea1b28a76aeba74744148b15099254d918671Owen Lin                        nextImagePos = current + 1;
1146666ea1b28a76aeba74744148b15099254d918671Owen Lin                        mNextChangePositionTime = event.getEventTime() + 500;
1147666ea1b28a76aeba74744148b15099254d918671Owen Lin                    } else {
1148666ea1b28a76aeba74744148b15099254d918671Owen Lin                        panBy(-PAN_RATE, 0);
1149666ea1b28a76aeba74744148b15099254d918671Owen Lin                        center(true, false);
1150666ea1b28a76aeba74744148b15099254d918671Owen Lin                    }
1151666ea1b28a76aeba74744148b15099254d918671Owen Lin                    return true;
1152666ea1b28a76aeba74744148b15099254d918671Owen Lin                }
1153666ea1b28a76aeba74744148b15099254d918671Owen Lin                case KeyEvent.KEYCODE_DPAD_UP: {
1154666ea1b28a76aeba74744148b15099254d918671Owen Lin                    panBy(0, PAN_RATE);
1155666ea1b28a76aeba74744148b15099254d918671Owen Lin                    center(false, true);
1156666ea1b28a76aeba74744148b15099254d918671Owen Lin                    return true;
1157666ea1b28a76aeba74744148b15099254d918671Owen Lin                }
1158666ea1b28a76aeba74744148b15099254d918671Owen Lin                case KeyEvent.KEYCODE_DPAD_DOWN: {
1159666ea1b28a76aeba74744148b15099254d918671Owen Lin                    panBy(0, -PAN_RATE);
1160666ea1b28a76aeba74744148b15099254d918671Owen Lin                    center(false, true);
1161666ea1b28a76aeba74744148b15099254d918671Owen Lin                    return true;
1162666ea1b28a76aeba74744148b15099254d918671Owen Lin                }
1163666ea1b28a76aeba74744148b15099254d918671Owen Lin                case KeyEvent.KEYCODE_DEL:
1164666ea1b28a76aeba74744148b15099254d918671Owen Lin                    MenuHelper.deletePhoto(
1165666ea1b28a76aeba74744148b15099254d918671Owen Lin                            mViewImage, mViewImage.mDeletePhotoRunnable);
1166666ea1b28a76aeba74744148b15099254d918671Owen Lin                    break;
1167666ea1b28a76aeba74744148b15099254d918671Owen Lin            }
1168666ea1b28a76aeba74744148b15099254d918671Owen Lin        } finally {
1169666ea1b28a76aeba74744148b15099254d918671Owen Lin            if (nextImagePos >= 0
1170666ea1b28a76aeba74744148b15099254d918671Owen Lin                    && nextImagePos < mViewImage.mAllImages.getCount()) {
1171666ea1b28a76aeba74744148b15099254d918671Owen Lin                synchronized (mViewImage) {
1172666ea1b28a76aeba74744148b15099254d918671Owen Lin                    mViewImage.setMode(ViewImage.MODE_NORMAL);
1173666ea1b28a76aeba74744148b15099254d918671Owen Lin                    mViewImage.setImage(nextImagePos, true);
1174666ea1b28a76aeba74744148b15099254d918671Owen Lin                }
1175666ea1b28a76aeba74744148b15099254d918671Owen Lin           } else if (nextImagePos != -2) {
1176666ea1b28a76aeba74744148b15099254d918671Owen Lin               center(true, true);
1177666ea1b28a76aeba74744148b15099254d918671Owen Lin           }
1178666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
1179666ea1b28a76aeba74744148b15099254d918671Owen Lin
1180666ea1b28a76aeba74744148b15099254d918671Owen Lin        return super.onKeyDown(keyCode, event);
1181666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
1182666ea1b28a76aeba74744148b15099254d918671Owen Lin}
1183666ea1b28a76aeba74744148b15099254d918671Owen Lin
1184666ea1b28a76aeba74744148b15099254d918671Owen Lin// This is a cache for Bitmap displayed in ViewImage (normal mode, thumb only).
1185666ea1b28a76aeba74744148b15099254d918671Owen Linclass BitmapCache implements ImageViewTouchBase.Recycler {
1186666ea1b28a76aeba74744148b15099254d918671Owen Lin    public static class Entry {
1187666ea1b28a76aeba74744148b15099254d918671Owen Lin        int mPos;
1188666ea1b28a76aeba74744148b15099254d918671Owen Lin        Bitmap mBitmap;
1189666ea1b28a76aeba74744148b15099254d918671Owen Lin        public Entry() {
1190666ea1b28a76aeba74744148b15099254d918671Owen Lin            clear();
1191666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
1192666ea1b28a76aeba74744148b15099254d918671Owen Lin        public void clear() {
1193666ea1b28a76aeba74744148b15099254d918671Owen Lin            mPos = -1;
1194666ea1b28a76aeba74744148b15099254d918671Owen Lin            mBitmap = null;
1195666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
1196666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
1197666ea1b28a76aeba74744148b15099254d918671Owen Lin
1198666ea1b28a76aeba74744148b15099254d918671Owen Lin    private final Entry[] mCache;
1199666ea1b28a76aeba74744148b15099254d918671Owen Lin
1200666ea1b28a76aeba74744148b15099254d918671Owen Lin    public BitmapCache(int size) {
1201666ea1b28a76aeba74744148b15099254d918671Owen Lin        mCache = new Entry[size];
1202666ea1b28a76aeba74744148b15099254d918671Owen Lin        for (int i = 0; i < mCache.length; i++) {
1203666ea1b28a76aeba74744148b15099254d918671Owen Lin            mCache[i] = new Entry();
1204666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
1205666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
1206666ea1b28a76aeba74744148b15099254d918671Owen Lin
1207666ea1b28a76aeba74744148b15099254d918671Owen Lin    // Given the position, find the associated entry. Returns null if there is
1208666ea1b28a76aeba74744148b15099254d918671Owen Lin    // no such entry.
1209666ea1b28a76aeba74744148b15099254d918671Owen Lin    private Entry findEntry(int pos) {
1210666ea1b28a76aeba74744148b15099254d918671Owen Lin        for (Entry e : mCache) {
1211666ea1b28a76aeba74744148b15099254d918671Owen Lin            if (pos == e.mPos) {
1212666ea1b28a76aeba74744148b15099254d918671Owen Lin                return e;
1213666ea1b28a76aeba74744148b15099254d918671Owen Lin            }
1214666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
1215666ea1b28a76aeba74744148b15099254d918671Owen Lin        return null;
1216666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
1217666ea1b28a76aeba74744148b15099254d918671Owen Lin
1218666ea1b28a76aeba74744148b15099254d918671Owen Lin    // Returns the thumb bitmap if we have it, otherwise return null.
1219666ea1b28a76aeba74744148b15099254d918671Owen Lin    public synchronized Bitmap getBitmap(int pos) {
1220666ea1b28a76aeba74744148b15099254d918671Owen Lin        Entry e = findEntry(pos);
1221666ea1b28a76aeba74744148b15099254d918671Owen Lin        if (e != null) {
1222666ea1b28a76aeba74744148b15099254d918671Owen Lin            return e.mBitmap;
1223666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
1224666ea1b28a76aeba74744148b15099254d918671Owen Lin        return null;
1225666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
1226666ea1b28a76aeba74744148b15099254d918671Owen Lin
1227666ea1b28a76aeba74744148b15099254d918671Owen Lin    public synchronized void put(int pos, Bitmap bitmap) {
1228666ea1b28a76aeba74744148b15099254d918671Owen Lin        // First see if we already have this entry.
1229666ea1b28a76aeba74744148b15099254d918671Owen Lin        if (findEntry(pos) != null) {
1230666ea1b28a76aeba74744148b15099254d918671Owen Lin            return;
1231666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
1232666ea1b28a76aeba74744148b15099254d918671Owen Lin
1233666ea1b28a76aeba74744148b15099254d918671Owen Lin        // Find the best entry we should replace.
1234666ea1b28a76aeba74744148b15099254d918671Owen Lin        // See if there is any empty entry.
1235666ea1b28a76aeba74744148b15099254d918671Owen Lin        // Otherwise assuming sequential access, kick out the entry with the
1236666ea1b28a76aeba74744148b15099254d918671Owen Lin        // greatest distance.
1237666ea1b28a76aeba74744148b15099254d918671Owen Lin        Entry best = null;
1238666ea1b28a76aeba74744148b15099254d918671Owen Lin        int maxDist = -1;
1239666ea1b28a76aeba74744148b15099254d918671Owen Lin        for (Entry e : mCache) {
1240666ea1b28a76aeba74744148b15099254d918671Owen Lin            if (e.mPos == -1) {
1241666ea1b28a76aeba74744148b15099254d918671Owen Lin                best = e;
1242666ea1b28a76aeba74744148b15099254d918671Owen Lin                break;
1243666ea1b28a76aeba74744148b15099254d918671Owen Lin            } else {
1244666ea1b28a76aeba74744148b15099254d918671Owen Lin                int dist = Math.abs(pos - e.mPos);
1245666ea1b28a76aeba74744148b15099254d918671Owen Lin                if (dist > maxDist) {
1246666ea1b28a76aeba74744148b15099254d918671Owen Lin                    maxDist = dist;
1247666ea1b28a76aeba74744148b15099254d918671Owen Lin                    best = e;
1248666ea1b28a76aeba74744148b15099254d918671Owen Lin                }
1249666ea1b28a76aeba74744148b15099254d918671Owen Lin            }
1250666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
1251666ea1b28a76aeba74744148b15099254d918671Owen Lin
1252666ea1b28a76aeba74744148b15099254d918671Owen Lin        // Recycle the image being kicked out.
1253666ea1b28a76aeba74744148b15099254d918671Owen Lin        // This only works because our current usage is sequential, so we
1254666ea1b28a76aeba74744148b15099254d918671Owen Lin        // do not happen to recycle the image being displayed.
1255666ea1b28a76aeba74744148b15099254d918671Owen Lin        if (best.mBitmap != null) {
1256666ea1b28a76aeba74744148b15099254d918671Owen Lin            best.mBitmap.recycle();
1257666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
1258666ea1b28a76aeba74744148b15099254d918671Owen Lin
1259666ea1b28a76aeba74744148b15099254d918671Owen Lin        best.mPos = pos;
1260666ea1b28a76aeba74744148b15099254d918671Owen Lin        best.mBitmap = bitmap;
1261666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
1262666ea1b28a76aeba74744148b15099254d918671Owen Lin
1263666ea1b28a76aeba74744148b15099254d918671Owen Lin    // Recycle all bitmaps in the cache and clear the cache.
1264666ea1b28a76aeba74744148b15099254d918671Owen Lin    public synchronized void clear() {
1265666ea1b28a76aeba74744148b15099254d918671Owen Lin        for (Entry e : mCache) {
1266666ea1b28a76aeba74744148b15099254d918671Owen Lin            if (e.mBitmap != null) {
1267666ea1b28a76aeba74744148b15099254d918671Owen Lin                e.mBitmap.recycle();
1268666ea1b28a76aeba74744148b15099254d918671Owen Lin            }
1269666ea1b28a76aeba74744148b15099254d918671Owen Lin            e.clear();
1270666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
1271666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
1272666ea1b28a76aeba74744148b15099254d918671Owen Lin
1273666ea1b28a76aeba74744148b15099254d918671Owen Lin    // Returns whether the bitmap is in the cache.
1274666ea1b28a76aeba74744148b15099254d918671Owen Lin    public synchronized boolean hasBitmap(int pos) {
1275666ea1b28a76aeba74744148b15099254d918671Owen Lin        Entry e = findEntry(pos);
1276666ea1b28a76aeba74744148b15099254d918671Owen Lin        return (e != null);
1277666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
1278666ea1b28a76aeba74744148b15099254d918671Owen Lin
1279666ea1b28a76aeba74744148b15099254d918671Owen Lin    // Recycle the bitmap if it's not in the cache.
1280666ea1b28a76aeba74744148b15099254d918671Owen Lin    // The input must be non-null.
1281666ea1b28a76aeba74744148b15099254d918671Owen Lin    public synchronized void recycle(Bitmap b) {
1282666ea1b28a76aeba74744148b15099254d918671Owen Lin        for (Entry e : mCache) {
1283666ea1b28a76aeba74744148b15099254d918671Owen Lin            if (e.mPos != -1) {
1284666ea1b28a76aeba74744148b15099254d918671Owen Lin                if (e.mBitmap == b) {
1285666ea1b28a76aeba74744148b15099254d918671Owen Lin                    return;
1286666ea1b28a76aeba74744148b15099254d918671Owen Lin                }
1287666ea1b28a76aeba74744148b15099254d918671Owen Lin            }
1288666ea1b28a76aeba74744148b15099254d918671Owen Lin        }
1289666ea1b28a76aeba74744148b15099254d918671Owen Lin        b.recycle();
1290666ea1b28a76aeba74744148b15099254d918671Owen Lin    }
1291666ea1b28a76aeba74744148b15099254d918671Owen Lin}
1292