1f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein/*
2f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * Copyright (C) 2011 Google Inc.
3f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * Licensed to The Android Open Source Project.
4f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein *
5f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * Licensed under the Apache License, Version 2.0 (the "License");
6f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * you may not use this file except in compliance with the License.
7f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * You may obtain a copy of the License at
8f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein *
9f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein *      http://www.apache.org/licenses/LICENSE-2.0
10f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein *
11f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * Unless required by applicable law or agreed to in writing, software
12f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * distributed under the License is distributed on an "AS IS" BASIS,
13f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * See the License for the specific language governing permissions and
15f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * limitations under the License.
16f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein */
17f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
18f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinpackage com.android.ex.photo.fragments;
19f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
20f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport android.app.Activity;
21f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport android.content.Context;
22f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport android.content.Intent;
230c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sappersteinimport android.database.Cursor;
24f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport android.graphics.Bitmap;
25f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport android.os.Bundle;
26fc3a6f46f375ef9347f57b88fd7e0c8b62ce1058Martin Hibdonimport android.os.Handler;
278746927a945358bb9e515985a37cac7807261026Martin Hibdonimport android.support.v4.app.Fragment;
288746927a945358bb9e515985a37cac7807261026Martin Hibdonimport android.support.v4.app.LoaderManager;
298746927a945358bb9e515985a37cac7807261026Martin Hibdonimport android.support.v4.content.Loader;
30f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport android.util.DisplayMetrics;
31f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport android.view.LayoutInflater;
32f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport android.view.View;
33f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport android.view.View.OnClickListener;
34f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport android.view.ViewGroup;
35f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport android.view.WindowManager;
369007d640832f674a9d65058a3c2a484c078d239eAndrew Sappersteinimport android.widget.ImageView;
37150e623129eef49467f1d6f67649e4636a4513f2Andrew Sappersteinimport android.widget.ProgressBar;
38150e623129eef49467f1d6f67649e4636a4513f2Andrew Sappersteinimport android.widget.TextView;
39f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
40f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport com.android.ex.photo.Intents;
41399fe3d995ed4366a18c7ce6632b3014284df57aMartin Hibdonimport com.android.ex.photo.PhotoViewCallbacks;
42399fe3d995ed4366a18c7ce6632b3014284df57aMartin Hibdonimport com.android.ex.photo.PhotoViewCallbacks.CursorChangedListener;
43399fe3d995ed4366a18c7ce6632b3014284df57aMartin Hibdonimport com.android.ex.photo.PhotoViewCallbacks.OnScreenListener;
44f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport com.android.ex.photo.R;
450c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sappersteinimport com.android.ex.photo.adapters.PhotoPagerAdapter;
46f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport com.android.ex.photo.loaders.PhotoBitmapLoader;
47f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport com.android.ex.photo.util.ImageUtils;
48f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinimport com.android.ex.photo.views.PhotoView;
49150e623129eef49467f1d6f67649e4636a4513f2Andrew Sappersteinimport com.android.ex.photo.views.ProgressBarWrapper;
50f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
51f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein/**
52f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein * Displays a photo.
53f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein */
54f77a7eb196d16110c7b1087352b423913821ff61Andrew Sappersteinpublic class PhotoViewFragment extends Fragment implements
558746927a945358bb9e515985a37cac7807261026Martin Hibdon        LoaderManager.LoaderCallbacks<Bitmap>, OnClickListener, OnScreenListener, CursorChangedListener {
56f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    /**
57f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein     * Interface for components that are internally scrollable left-to-right.
58f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein     */
59f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    public static interface HorizontallyScrollable {
60f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        /**
61f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein         * Return {@code true} if the component needs to receive right-to-left
62f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein         * touch movements.
63f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein         *
64f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein         * @param origX the raw x coordinate of the initial touch
65f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein         * @param origY the raw y coordinate of the initial touch
66f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein         */
67f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
68f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        public boolean interceptMoveLeft(float origX, float origY);
69f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
70f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        /**
71f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein         * Return {@code true} if the component needs to receive left-to-right
72f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein         * touch movements.
73f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein         *
74f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein         * @param origX the raw x coordinate of the initial touch
75f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein         * @param origY the raw y coordinate of the initial touch
76f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein         */
77f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        public boolean interceptMoveRight(float origX, float origY);
78f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    }
79f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
80934bd9e0b4b3fcf7730325fa416b8c162141f7e9Martin Hibdon    protected final static String STATE_INTENT_KEY =
81f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein            "com.android.mail.photo.fragments.PhotoViewFragment.INTENT";
82f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
83f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    // Loader IDs
84bf77f3b89ad05406eecb30c2ea9390f7e921de32Martin Hibdon    protected final static int LOADER_ID_PHOTO = 1;
85bf77f3b89ad05406eecb30c2ea9390f7e921de32Martin Hibdon    protected final static int LOADER_ID_THUMBNAIL = 2;
86f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
87f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    /** The size of the photo */
88f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    public static Integer sPhotoSize;
89f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
90f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    /** The URL of a photo to display */
91934bd9e0b4b3fcf7730325fa416b8c162141f7e9Martin Hibdon    protected String mResolvedPhotoUri;
92934bd9e0b4b3fcf7730325fa416b8c162141f7e9Martin Hibdon    protected String mThumbnailUri;
93f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    /** The intent we were launched with */
94934bd9e0b4b3fcf7730325fa416b8c162141f7e9Martin Hibdon    protected Intent mIntent;
95934bd9e0b4b3fcf7730325fa416b8c162141f7e9Martin Hibdon    protected PhotoViewCallbacks mCallback;
96934bd9e0b4b3fcf7730325fa416b8c162141f7e9Martin Hibdon    protected PhotoPagerAdapter mAdapter;
97f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
98934bd9e0b4b3fcf7730325fa416b8c162141f7e9Martin Hibdon    protected PhotoView mPhotoView;
99934bd9e0b4b3fcf7730325fa416b8c162141f7e9Martin Hibdon    protected ImageView mPhotoPreviewImage;
100934bd9e0b4b3fcf7730325fa416b8c162141f7e9Martin Hibdon    protected TextView mEmptyText;
101934bd9e0b4b3fcf7730325fa416b8c162141f7e9Martin Hibdon    protected ImageView mRetryButton;
102934bd9e0b4b3fcf7730325fa416b8c162141f7e9Martin Hibdon    protected ProgressBarWrapper mPhotoProgressBar;
103150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein
104934bd9e0b4b3fcf7730325fa416b8c162141f7e9Martin Hibdon    protected final int mPosition;
105f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
106f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    /** Whether or not the fragment should make the photo full-screen */
107934bd9e0b4b3fcf7730325fa416b8c162141f7e9Martin Hibdon    protected boolean mFullScreen;
108f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
109ae78bbd1c97e702147b29966903ca6e08ed3616fAdam Copp    /** Whether or not this fragment will only show the loading spinner */
110934bd9e0b4b3fcf7730325fa416b8c162141f7e9Martin Hibdon    protected final boolean mOnlyShowSpinner;
111ae78bbd1c97e702147b29966903ca6e08ed3616fAdam Copp
1129556f61c11991d6e955cfd68ca53f4f489dfa8c5Paul Westbrook    /** Whether or not the progress bar is showing valid information about the progress stated */
113934bd9e0b4b3fcf7730325fa416b8c162141f7e9Martin Hibdon    protected boolean mProgressBarNeeded = true;
1149556f61c11991d6e955cfd68ca53f4f489dfa8c5Paul Westbrook
115934bd9e0b4b3fcf7730325fa416b8c162141f7e9Martin Hibdon    protected View mPhotoPreviewAndProgress;
116928a39fb533255b34145285fabbd4f51961df63aAndrew Sapperstein
117f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    public PhotoViewFragment() {
1180c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein        mPosition = -1;
119ae78bbd1c97e702147b29966903ca6e08ed3616fAdam Copp        mOnlyShowSpinner = false;
1209556f61c11991d6e955cfd68ca53f4f489dfa8c5Paul Westbrook        mProgressBarNeeded = true;
121f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    }
122f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
123ae78bbd1c97e702147b29966903ca6e08ed3616fAdam Copp    public PhotoViewFragment(Intent intent, int position, PhotoPagerAdapter adapter,
124ae78bbd1c97e702147b29966903ca6e08ed3616fAdam Copp            boolean onlyShowSpinner) {
125f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        mIntent = intent;
1260c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein        mPosition = position;
1270c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein        mAdapter = adapter;
128ae78bbd1c97e702147b29966903ca6e08ed3616fAdam Copp        mOnlyShowSpinner = onlyShowSpinner;
1299556f61c11991d6e955cfd68ca53f4f489dfa8c5Paul Westbrook        mProgressBarNeeded = true;
130f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    }
131f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
132f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    @Override
133f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    public void onAttach(Activity activity) {
134f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        super.onAttach(activity);
135399fe3d995ed4366a18c7ce6632b3014284df57aMartin Hibdon        mCallback = (PhotoViewCallbacks) activity;
136f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        if (mCallback == null) {
137150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein            throw new IllegalArgumentException(
138150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein                    "Activity must be a derived class of PhotoViewActivity");
139f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        }
140f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
141f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        if (sPhotoSize == null) {
142f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein            final DisplayMetrics metrics = new DisplayMetrics();
143f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein            final WindowManager wm =
144f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein                    (WindowManager) getActivity().getSystemService(Context.WINDOW_SERVICE);
145f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein            final ImageUtils.ImageSize imageSize = ImageUtils.sUseImageSize;
146f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein            wm.getDefaultDisplay().getMetrics(metrics);
147f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein            switch (imageSize) {
148f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein                case EXTRA_SMALL: {
149f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein                    // Use a photo that's 80% of the "small" size
150f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein                    sPhotoSize = (Math.min(metrics.heightPixels, metrics.widthPixels) * 800) / 1000;
151f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein                    break;
152f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein                }
153f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
154f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein                case SMALL:
155f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein                case NORMAL:
156f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein                default: {
157f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein                    sPhotoSize = Math.min(metrics.heightPixels, metrics.widthPixels);
158f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein                    break;
159f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein                }
160f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein            }
161f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        }
162f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    }
163f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
164f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    @Override
165f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    public void onDetach() {
166f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        mCallback = null;
167f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        super.onDetach();
168f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    }
169f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
170f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    @Override
171f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    public void onCreate(Bundle savedInstanceState) {
172f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        super.onCreate(savedInstanceState);
173f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
174f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        if (savedInstanceState != null) {
175c4d9382e8e52e1122d51f52402c6c4a609a785d6Mark Wei            final Bundle state = savedInstanceState.getBundle(STATE_INTENT_KEY);
176c4d9382e8e52e1122d51f52402c6c4a609a785d6Mark Wei            if (state != null) {
177c4d9382e8e52e1122d51f52402c6c4a609a785d6Mark Wei                mIntent = new Intent().putExtras(state);
178c4d9382e8e52e1122d51f52402c6c4a609a785d6Mark Wei            }
179f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        }
180f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
1812539f2ef0fa351d40551dda5ba0b543b2a042b0fMark Wei        if (mIntent != null) {
1822539f2ef0fa351d40551dda5ba0b543b2a042b0fMark Wei            mResolvedPhotoUri = mIntent.getStringExtra(Intents.EXTRA_RESOLVED_PHOTO_URI);
1832539f2ef0fa351d40551dda5ba0b543b2a042b0fMark Wei            mThumbnailUri = mIntent.getStringExtra(Intents.EXTRA_THUMBNAIL_URI);
1842539f2ef0fa351d40551dda5ba0b543b2a042b0fMark Wei        }
185f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    }
186f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
187f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    @Override
188f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    public View onCreateView(LayoutInflater inflater, ViewGroup container,
189f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein            Bundle savedInstanceState) {
190f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        final View view = inflater.inflate(R.layout.photo_fragment_view, container, false);
191f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
192f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        mPhotoView = (PhotoView) view.findViewById(R.id.photo_view);
19391dbfd25cc234de393ae22fc39a832a6335e1bc2Adam Copp        mPhotoView.setMaxInitialScale(mIntent.getFloatExtra(Intents.EXTRA_MAX_INITIAL_SCALE, 1));
194f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        mPhotoView.setOnClickListener(this);
195f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        mPhotoView.setFullScreen(mFullScreen, false);
196edad0e0512af73ea89b85c5e4568a42bdae3f539Adam Copp        mPhotoView.enableImageTransforms(false);
1979007d640832f674a9d65058a3c2a484c078d239eAndrew Sapperstein
198150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein        mPhotoPreviewAndProgress = view.findViewById(R.id.photo_preview);
199150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein        mPhotoPreviewImage = (ImageView) view.findViewById(R.id.photo_preview_image);
200150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein        final ProgressBar indeterminate =
201150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein                (ProgressBar) view.findViewById(R.id.indeterminate_progress);
202150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein        final ProgressBar determinate =
203150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein                (ProgressBar) view.findViewById(R.id.determinate_progress);
204150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein        mPhotoProgressBar = new ProgressBarWrapper(determinate, indeterminate, true);
205150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein        mEmptyText = (TextView) view.findViewById(R.id.empty_text);
206150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein        mRetryButton = (ImageView) view.findViewById(R.id.retry_button);
207f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
208f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        // Don't call until we've setup the entire view
209f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        setViewVisibility();
210f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
211f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        return view;
212f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    }
213f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
214f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    @Override
215f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    public void onResume() {
216f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        mCallback.addScreenListener(this);
2170c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein        mCallback.addCursorListener(this);
218f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
219bd8b47b147f29f196f37d66ccb561d40414ab5b6Adam Copp        getLoaderManager().initLoader(LOADER_ID_THUMBNAIL, null, this);
220f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
221f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        super.onResume();
222f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    }
223f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
224f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    @Override
225f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    public void onPause() {
226f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        super.onPause();
2270c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein        // Remove listeners
2280c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein        mCallback.removeCursorListener(this);
229f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        mCallback.removeScreenListener(this);
230f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        resetPhotoView();
231f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    }
232f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
233f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    @Override
234f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    public void onDestroyView() {
235f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        // Clean up views and other components
236f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        if (mPhotoView != null) {
237f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein            mPhotoView.clear();
238f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein            mPhotoView = null;
239f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        }
240f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
241f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        super.onDestroyView();
242f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    }
243f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
244f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    @Override
245f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    public void onSaveInstanceState(Bundle outState) {
246f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        super.onSaveInstanceState(outState);
247f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
248f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        if (mIntent != null) {
249f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein            outState.putParcelable(STATE_INTENT_KEY, mIntent.getExtras());
250f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        }
251f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    }
252f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
253f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    @Override
254f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    public Loader<Bitmap> onCreateLoader(int id, Bundle args) {
255ae78bbd1c97e702147b29966903ca6e08ed3616fAdam Copp        if(mOnlyShowSpinner) {
256ae78bbd1c97e702147b29966903ca6e08ed3616fAdam Copp            return null;
257ae78bbd1c97e702147b29966903ca6e08ed3616fAdam Copp        }
258928a39fb533255b34145285fabbd4f51961df63aAndrew Sapperstein        switch (id) {
259928a39fb533255b34145285fabbd4f51961df63aAndrew Sapperstein            case LOADER_ID_PHOTO:
260928a39fb533255b34145285fabbd4f51961df63aAndrew Sapperstein                return new PhotoBitmapLoader(getActivity(), mResolvedPhotoUri);
261928a39fb533255b34145285fabbd4f51961df63aAndrew Sapperstein            case LOADER_ID_THUMBNAIL:
262928a39fb533255b34145285fabbd4f51961df63aAndrew Sapperstein                return new PhotoBitmapLoader(getActivity(), mThumbnailUri);
263928a39fb533255b34145285fabbd4f51961df63aAndrew Sapperstein            default:
264928a39fb533255b34145285fabbd4f51961df63aAndrew Sapperstein                return null;
265f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        }
266f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    }
267f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
268f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    @Override
269f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    public void onLoadFinished(Loader<Bitmap> loader, Bitmap data) {
270f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        // If we don't have a view, the fragment has been paused. We'll get the cursor again later.
271f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        if (getView() == null) {
272f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein            return;
273f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        }
274f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
275f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        final int id = loader.getId();
276928a39fb533255b34145285fabbd4f51961df63aAndrew Sapperstein        switch (id) {
277928a39fb533255b34145285fabbd4f51961df63aAndrew Sapperstein            case LOADER_ID_PHOTO:
2789556f61c11991d6e955cfd68ca53f4f489dfa8c5Paul Westbrook                if (data != null) {
279150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein                    bindPhoto(data);
280edad0e0512af73ea89b85c5e4568a42bdae3f539Adam Copp                    enableImageTransforms(true);
281150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein                    mPhotoPreviewAndProgress.setVisibility(View.GONE);
2829556f61c11991d6e955cfd68ca53f4f489dfa8c5Paul Westbrook                    mProgressBarNeeded = false;
2839556f61c11991d6e955cfd68ca53f4f489dfa8c5Paul Westbrook                } else {
2849556f61c11991d6e955cfd68ca53f4f489dfa8c5Paul Westbrook                    // Received a null result for the full size image.  Instead attempt to load the
2859556f61c11991d6e955cfd68ca53f4f489dfa8c5Paul Westbrook                    // thumbnail
286fc3a6f46f375ef9347f57b88fd7e0c8b62ce1058Martin Hibdon                    Handler handler = new Handler();
287fc3a6f46f375ef9347f57b88fd7e0c8b62ce1058Martin Hibdon                    handler.post(new Runnable() {
288fc3a6f46f375ef9347f57b88fd7e0c8b62ce1058Martin Hibdon                        @Override
289fc3a6f46f375ef9347f57b88fd7e0c8b62ce1058Martin Hibdon                        public void run() {
290fc3a6f46f375ef9347f57b88fd7e0c8b62ce1058Martin Hibdon                            getLoaderManager().initLoader(LOADER_ID_THUMBNAIL, null,
291fc3a6f46f375ef9347f57b88fd7e0c8b62ce1058Martin Hibdon                                                          PhotoViewFragment.this);
292fc3a6f46f375ef9347f57b88fd7e0c8b62ce1058Martin Hibdon                        }
293fc3a6f46f375ef9347f57b88fd7e0c8b62ce1058Martin Hibdon                    });
294928a39fb533255b34145285fabbd4f51961df63aAndrew Sapperstein                }
295928a39fb533255b34145285fabbd4f51961df63aAndrew Sapperstein                break;
296928a39fb533255b34145285fabbd4f51961df63aAndrew Sapperstein            case LOADER_ID_THUMBNAIL:
2971389ae2ea3376b317e4810f9e3b123a0cb5ac008Adam Copp                mProgressBarNeeded = false;
2989007d640832f674a9d65058a3c2a484c078d239eAndrew Sapperstein                if (isPhotoBound()) {
2999556f61c11991d6e955cfd68ca53f4f489dfa8c5Paul Westbrook                    // There is need to do anything with the thumbnail image, as the full size
3009556f61c11991d6e955cfd68ca53f4f489dfa8c5Paul Westbrook                    // image is being shown.
3019556f61c11991d6e955cfd68ca53f4f489dfa8c5Paul Westbrook                    mPhotoPreviewAndProgress.setVisibility(View.GONE);
3029007d640832f674a9d65058a3c2a484c078d239eAndrew Sapperstein                    return;
303150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein                } else if (data == null) {
3049007d640832f674a9d65058a3c2a484c078d239eAndrew Sapperstein                    // no preview, show default
305150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein                    mPhotoPreviewImage.setVisibility(View.VISIBLE);
306150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein                    mPhotoPreviewImage.setImageResource(R.drawable.default_image);
307150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein                } else {
308bd8b47b147f29f196f37d66ccb561d40414ab5b6Adam Copp                    bindPhoto(data);
309edad0e0512af73ea89b85c5e4568a42bdae3f539Adam Copp                    enableImageTransforms(false);
310535ffb18682c17d08be17aae5a31c11bf9d44ae5Mike Dodd                    Handler handler = new Handler();
311535ffb18682c17d08be17aae5a31c11bf9d44ae5Mike Dodd                    handler.post(new Runnable() {
312535ffb18682c17d08be17aae5a31c11bf9d44ae5Mike Dodd                        @Override
313535ffb18682c17d08be17aae5a31c11bf9d44ae5Mike Dodd                        public void run() {
314535ffb18682c17d08be17aae5a31c11bf9d44ae5Mike Dodd                            getLoaderManager().initLoader(LOADER_ID_PHOTO, null,
315535ffb18682c17d08be17aae5a31c11bf9d44ae5Mike Dodd                                PhotoViewFragment.this);
316535ffb18682c17d08be17aae5a31c11bf9d44ae5Mike Dodd                        }
317535ffb18682c17d08be17aae5a31c11bf9d44ae5Mike Dodd                    });
318928a39fb533255b34145285fabbd4f51961df63aAndrew Sapperstein                }
319928a39fb533255b34145285fabbd4f51961df63aAndrew Sapperstein                break;
320928a39fb533255b34145285fabbd4f51961df63aAndrew Sapperstein            default:
321928a39fb533255b34145285fabbd4f51961df63aAndrew Sapperstein                break;
322f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        }
323150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein
3249556f61c11991d6e955cfd68ca53f4f489dfa8c5Paul Westbrook        if (mProgressBarNeeded == false) {
3259556f61c11991d6e955cfd68ca53f4f489dfa8c5Paul Westbrook            // Hide the progress bar as it isn't needed anymore.
3269556f61c11991d6e955cfd68ca53f4f489dfa8c5Paul Westbrook            mPhotoProgressBar.setVisibility(View.GONE);
3279556f61c11991d6e955cfd68ca53f4f489dfa8c5Paul Westbrook        }
3289556f61c11991d6e955cfd68ca53f4f489dfa8c5Paul Westbrook
329150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein        mCallback.setViewActivated();
330150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein        setViewVisibility();
331f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    }
332f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
333f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    /**
334f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein     * Binds an image to the photo view.
335f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein     */
336f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    private void bindPhoto(Bitmap bitmap) {
337f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        if (mPhotoView != null) {
338f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein            mPhotoView.bindPhoto(bitmap);
339f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        }
340f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    }
341f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
342f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    /**
343edad0e0512af73ea89b85c5e4568a42bdae3f539Adam Copp     * Enable or disable image transformations. When transformations are enabled, this view
344edad0e0512af73ea89b85c5e4568a42bdae3f539Adam Copp     * consumes all touch events.
345edad0e0512af73ea89b85c5e4568a42bdae3f539Adam Copp     */
346edad0e0512af73ea89b85c5e4568a42bdae3f539Adam Copp    public void enableImageTransforms(boolean enable) {
347edad0e0512af73ea89b85c5e4568a42bdae3f539Adam Copp        mPhotoView.enableImageTransforms(enable);
348edad0e0512af73ea89b85c5e4568a42bdae3f539Adam Copp    }
349edad0e0512af73ea89b85c5e4568a42bdae3f539Adam Copp
350edad0e0512af73ea89b85c5e4568a42bdae3f539Adam Copp    /**
351f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein     * Resets the photo view to it's default state w/ no bound photo.
352f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein     */
353f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    private void resetPhotoView() {
354f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        if (mPhotoView != null) {
355f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein            mPhotoView.bindPhoto(null);
356f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        }
357f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    }
358f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
359f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    @Override
360f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    public void onLoaderReset(Loader<Bitmap> loader) {
361f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        // Do nothing
362f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    }
363f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
364f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    @Override
365f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    public void onClick(View v) {
3661abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein        mCallback.toggleFullScreen();
367f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    }
368f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
369f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    @Override
3701abd4654c2eeacc7d854a438a9c72d7239278beaAndrew Sapperstein    public void onFullScreenChanged(boolean fullScreen) {
371f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        setViewVisibility();
372f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    }
373f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
374f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    @Override
375f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    public void onViewActivated() {
376f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        if (!mCallback.isFragmentActive(this)) {
377f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein            // we're not in the foreground; reset our view
378f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein            resetViews();
379f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        } else {
380f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein            mCallback.onFragmentVisible(this);
381f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        }
382f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    }
383f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
384f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    /**
385f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein     * Reset the views to their default states
386f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein     */
387f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    public void resetViews() {
388f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        if (mPhotoView != null) {
389f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein            mPhotoView.resetTransformations();
390f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        }
391f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    }
392f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
393f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    @Override
394f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    public boolean onInterceptMoveLeft(float origX, float origY) {
395f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        if (!mCallback.isFragmentActive(this)) {
396f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein            // we're not in the foreground; don't intercept any touches
397f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein            return false;
398f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        }
399f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
400f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        return (mPhotoView != null && mPhotoView.interceptMoveLeft(origX, origY));
401f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    }
402f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
403f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    @Override
404f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    public boolean onInterceptMoveRight(float origX, float origY) {
405f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        if (!mCallback.isFragmentActive(this)) {
406f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein            // we're not in the foreground; don't intercept any touches
407f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein            return false;
408f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        }
409f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
410f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        return (mPhotoView != null && mPhotoView.interceptMoveRight(origX, origY));
411f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    }
412f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
413f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    /**
414f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein     * Returns {@code true} if a photo has been bound. Otherwise, returns {@code false}.
415f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein     */
416f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    public boolean isPhotoBound() {
417150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein        return (mPhotoView != null && mPhotoView.isPhotoBound());
418f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    }
419f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
420f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    /**
421f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein     * Sets view visibility depending upon whether or not we're in "full screen" mode.
422f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein     */
423f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    private void setViewVisibility() {
424f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        final boolean fullScreen = mCallback.isFragmentFullScreen(this);
425f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        final boolean hide = fullScreen;
426f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
427f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        setFullScreen(hide);
428f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    }
429f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein
430f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    /**
431f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein     * Sets full-screen mode for the views.
432f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein     */
433f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    public void setFullScreen(boolean fullScreen) {
434f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein        mFullScreen = fullScreen;
435f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein    }
4360c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein
4370c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein    @Override
4380c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein    public void onCursorChanged(Cursor cursor) {
4390c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein        if (cursor.moveToPosition(mPosition) && !isPhotoBound()) {
4400c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein            final LoaderManager manager = getLoaderManager();
4410c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein            final Loader<Bitmap> fakeLoader = manager.getLoader(LOADER_ID_PHOTO);
4420c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein            if (fakeLoader == null) {
4430c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein                return;
4440c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein            }
4450c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein
4460c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein            final PhotoBitmapLoader loader =
4470c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein                    (PhotoBitmapLoader) fakeLoader;
4480c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein            mResolvedPhotoUri = mAdapter.getPhotoUri(cursor);
4490c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein            loader.setPhotoUri(mResolvedPhotoUri);
4500c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein            loader.forceLoad();
4510c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein        }
4520c18e5deef5209d21b527a01feb6b789715eb48eAndrew Sapperstein    }
453150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein
454150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein    public ProgressBarWrapper getPhotoProgressBar() {
455150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein        return mPhotoProgressBar;
456150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein    }
457150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein
458150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein    public TextView getEmptyText() {
459150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein        return mEmptyText;
460150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein    }
461150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein
462150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein    public ImageView getRetryButton() {
463150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein        return mRetryButton;
464150e623129eef49467f1d6f67649e4636a4513f2Andrew Sapperstein    }
4659556f61c11991d6e955cfd68ca53f4f489dfa8c5Paul Westbrook
4669556f61c11991d6e955cfd68ca53f4f489dfa8c5Paul Westbrook    public boolean isProgressBarNeeded() {
4679556f61c11991d6e955cfd68ca53f4f489dfa8c5Paul Westbrook        return mProgressBarNeeded;
4689556f61c11991d6e955cfd68ca53f4f489dfa8c5Paul Westbrook    }
469f77a7eb196d16110c7b1087352b423913821ff61Andrew Sapperstein}
470