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