11cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein/*
21cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein * Copyright (C) 2011 Google Inc.
31cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein * Licensed to The Android Open Source Project.
41cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein *
51cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein * Licensed under the Apache License, Version 2.0 (the "License");
61cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein * you may not use this file except in compliance with the License.
71cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein * You may obtain a copy of the License at
81cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein *
91cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein *      http://www.apache.org/licenses/LICENSE-2.0
101cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein *
111cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein * Unless required by applicable law or agreed to in writing, software
121cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein * distributed under the License is distributed on an "AS IS" BASIS,
131cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
141cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein * See the License for the specific language governing permissions and
151cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein * limitations under the License.
161cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein */
171cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
181cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sappersteinpackage com.android.ex.photo;
191cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
201cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sappersteinimport android.app.ActionBar;
21509bd03a2a783f804e9456767b52e0f8ef43479bAndrew Sappersteinimport android.app.ActionBar.OnMenuVisibilityListener;
221cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sappersteinimport android.app.Activity;
231cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sappersteinimport android.app.ActivityManager;
241cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sappersteinimport android.app.Fragment;
251cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sappersteinimport android.app.LoaderManager.LoaderCallbacks;
261cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sappersteinimport android.content.Intent;
271cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sappersteinimport android.content.Loader;
288f7bdab470c48a5e53c9a8a54ae9eb7f59827a32Paul Westbrookimport android.content.res.Resources;
291cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sappersteinimport android.database.Cursor;
301cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sappersteinimport android.net.Uri;
31b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sappersteinimport android.os.Build;
321cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sappersteinimport android.os.Bundle;
331cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sappersteinimport android.os.Handler;
341cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sappersteinimport android.support.v4.view.ViewPager.OnPageChangeListener;
351cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sappersteinimport android.view.View;
361cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
371cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sappersteinimport com.android.ex.photo.PhotoViewPager.InterceptType;
381cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sappersteinimport com.android.ex.photo.PhotoViewPager.OnInterceptTouchListener;
391cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sappersteinimport com.android.ex.photo.adapters.PhotoPagerAdapter;
40a6729336171ef61950d5f585b0f39c013ae6dcbcAndrew Sappersteinimport com.android.ex.photo.fragments.PhotoViewFragment;
411cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sappersteinimport com.android.ex.photo.loaders.PhotoPagerLoader;
421cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sappersteinimport com.android.ex.photo.provider.PhotoContract;
431cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
441cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sappersteinimport java.util.HashSet;
451cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sappersteinimport java.util.Set;
461cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
471cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein/**
481cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein * Activity to view the contents of an album.
491cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein */
501cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sappersteinpublic class PhotoViewActivity extends Activity implements
511cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        LoaderCallbacks<Cursor>, OnPageChangeListener, OnInterceptTouchListener,
52459c618b574a3d3b6a544267a87c2093bacac20dPaul Westbrook        OnMenuVisibilityListener {
531cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
541cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    /**
551cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein     * Listener to be invoked for screen events.
561cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein     */
571cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    public static interface OnScreenListener {
581cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
591cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        /**
601cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein         * The full screen state has changed.
611cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein         */
62b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein        public void onFullScreenChanged(boolean fullScreen);
631cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
641cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        /**
651cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein         * A new view has been activated and the previous view de-activated.
661cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein         */
671cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        public void onViewActivated();
681cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
691cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        /**
701cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein         * Called when a right-to-left touch move intercept is about to occur.
711cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein         *
721cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein         * @param origX the raw x coordinate of the initial touch
731cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein         * @param origY the raw y coordinate of the initial touch
741cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein         * @return {@code true} if the touch should be intercepted.
751cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein         */
761cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        public boolean onInterceptMoveLeft(float origX, float origY);
771cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
781cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        /**
791cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein         * Called when a left-to-right touch move intercept is about to occur.
801cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein         *
811cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein         * @param origX the raw x coordinate of the initial touch
821cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein         * @param origY the raw y coordinate of the initial touch
831cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein         * @return {@code true} if the touch should be intercepted.
841cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein         */
851cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        public boolean onInterceptMoveRight(float origX, float origY);
861cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    }
871cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
88a6729336171ef61950d5f585b0f39c013ae6dcbcAndrew Sapperstein    public static interface CursorChangedListener {
89a6729336171ef61950d5f585b0f39c013ae6dcbcAndrew Sapperstein        /**
90a6729336171ef61950d5f585b0f39c013ae6dcbcAndrew Sapperstein         * Called when the cursor that contains the photo list data
91a6729336171ef61950d5f585b0f39c013ae6dcbcAndrew Sapperstein         * is updated. Note that there is no guarantee that the cursor
92a6729336171ef61950d5f585b0f39c013ae6dcbcAndrew Sapperstein         * will be at the proper position.
93a6729336171ef61950d5f585b0f39c013ae6dcbcAndrew Sapperstein         * @param cursor the cursor containing the photo list data
94a6729336171ef61950d5f585b0f39c013ae6dcbcAndrew Sapperstein         */
95a6729336171ef61950d5f585b0f39c013ae6dcbcAndrew Sapperstein        public void onCursorChanged(Cursor cursor);
96a6729336171ef61950d5f585b0f39c013ae6dcbcAndrew Sapperstein    }
97a6729336171ef61950d5f585b0f39c013ae6dcbcAndrew Sapperstein
981cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    private final static String STATE_ITEM_KEY =
991cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein            "com.google.android.apps.plus.PhotoViewFragment.ITEM";
1001cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    private final static String STATE_FULLSCREEN_KEY =
1011cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein            "com.google.android.apps.plus.PhotoViewFragment.FULLSCREEN";
1021cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
1031cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    private static final int LOADER_PHOTO_LIST = 1;
1041cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
1051cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    /** Count used when the real photo count is unknown [but, may be determined] */
1061cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    public static final int ALBUM_COUNT_UNKNOWN = -1;
1071cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
1081cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    /** Argument key for the dialog message */
1091cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    public static final String KEY_MESSAGE = "dialog_message";
1101cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
1111cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    public static int sMemoryClass;
1121cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
1131cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    /** The URI of the photos we're viewing; may be {@code null} */
1141cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    private String mPhotosUri;
1151cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    /** The index of the currently viewed photo */
1161cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    private int mPhotoIndex;
1171cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    /** The query projection to use; may be {@code null} */
1181cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    private String[] mProjection;
1191cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    /** The total number of photos; only valid if {@link #mIsEmpty} is {@code false}. */
1201cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    private int mAlbumCount = ALBUM_COUNT_UNKNOWN;
1211cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    /** {@code true} if the view is empty. Otherwise, {@code false}. */
1221cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    private boolean mIsEmpty;
1231cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    /** The main pager; provides left/right swipe between photos */
1241cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    private PhotoViewPager mViewPager;
1251cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    /** Adapter to create pager views */
1261cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    private PhotoPagerAdapter mAdapter;
1271cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    /** Whether or not we're in "full screen" mode */
1281cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    private boolean mFullScreen;
1291cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    /** The set of listeners wanting full screen state */
1301cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    private Set<OnScreenListener> mScreenListeners = new HashSet<OnScreenListener>();
131a6729336171ef61950d5f585b0f39c013ae6dcbcAndrew Sapperstein    /** The set of listeners wanting full screen state */
132a6729336171ef61950d5f585b0f39c013ae6dcbcAndrew Sapperstein    private Set<CursorChangedListener> mCursorListeners = new HashSet<CursorChangedListener>();
1331cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    /** When {@code true}, restart the loader when the activity becomes active */
1341cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    private boolean mRestartLoader;
1351cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    /** Whether or not this activity is paused */
1361cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    private boolean mIsPaused = true;
137114cef99189d693ed9cd8cf778a60823d06d5298Paul Westbrook    private final Handler mHandler = new Handler();
1381cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    // TODO Find a better way to do this. We basically want the activity to display the
1391cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    // "loading..." progress until the fragment takes over and shows it's own "loading..."
1401cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    // progress [located in photo_header_view.xml]. We could potentially have all status displayed
1411cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    // by the activity, but, that gets tricky when it comes to screen rotation. For now, we
1421cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    // track the loading by this variable which is fragile and may cause phantom "loading..."
1431cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    // text.
144b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein    private long mActionBarHideDelayTime;
1451cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
1461cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    @Override
1471cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    protected void onCreate(Bundle savedInstanceState) {
1481cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        super.onCreate(savedInstanceState);
1491cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
1501cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        final ActivityManager mgr = (ActivityManager) getApplicationContext().
1511cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein                getSystemService(Activity.ACTIVITY_SERVICE);
1521cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        sMemoryClass = mgr.getMemoryClass();
1531cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
1541cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        Intent mIntent = getIntent();
1551cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
1561cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        int currentItem = -1;
1571cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        if (savedInstanceState != null) {
1581cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein            currentItem = savedInstanceState.getInt(STATE_ITEM_KEY, -1);
1591cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein            mFullScreen = savedInstanceState.getBoolean(STATE_FULLSCREEN_KEY, false);
1601cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        }
1611cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
1621cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        // uri of the photos to view; optional
1631cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        if (mIntent.hasExtra(Intents.EXTRA_PHOTOS_URI)) {
1641cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein            mPhotosUri = mIntent.getStringExtra(Intents.EXTRA_PHOTOS_URI);
1651cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        }
1661cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
1671cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        // projection for the query; optional
1681cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        // I.f not set, the default projection is used.
1691cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        // This projection must include the columns from the default projection.
1701cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        if (mIntent.hasExtra(Intents.EXTRA_PROJECTION)) {
1711cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein            mProjection = mIntent.getStringArrayExtra(Intents.EXTRA_PROJECTION);
1721cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        } else {
1731cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein            mProjection = null;
1741cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        }
1751cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
1761cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        // Set the current item from the intent if wasn't in the saved instance
1771cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        if (mIntent.hasExtra(Intents.EXTRA_PHOTO_INDEX) && currentItem < 0) {
1781cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein            currentItem = mIntent.getIntExtra(Intents.EXTRA_PHOTO_INDEX, -1);
1791cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        }
1801cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        mPhotoIndex = currentItem;
1811cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
1821cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        setContentView(R.layout.photo_activity_view);
1831cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
1841cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        // Create the adapter and add the view pager
1851cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        mAdapter = new PhotoPagerAdapter(this, getFragmentManager(), null);
1861cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
1878f7bdab470c48a5e53c9a8a54ae9eb7f59827a32Paul Westbrook        final Resources resources = getResources();
1881cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        mViewPager = (PhotoViewPager) findViewById(R.id.photo_view_pager);
1891cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        mViewPager.setAdapter(mAdapter);
1901cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        mViewPager.setOnPageChangeListener(this);
1911cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        mViewPager.setOnInterceptTouchListener(this);
1928f7bdab470c48a5e53c9a8a54ae9eb7f59827a32Paul Westbrook        mViewPager.setPageMargin(resources.getDimensionPixelSize(R.dimen.photo_page_margin));
1931cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
1941cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        // Kick off the loader
1951cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        getLoaderManager().initLoader(LOADER_PHOTO_LIST, null, this);
1961cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
1971cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        final ActionBar actionBar = getActionBar();
1981cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        actionBar.setDisplayHomeAsUpEnabled(true);
1998f7bdab470c48a5e53c9a8a54ae9eb7f59827a32Paul Westbrook        mActionBarHideDelayTime = resources.getInteger(R.integer.action_bar_delay_time_in_millis);
200509bd03a2a783f804e9456767b52e0f8ef43479bAndrew Sapperstein        actionBar.addOnMenuVisibilityListener(this);
20176aca5f8ae1a795aa4f351209a41545b6b3ade6eAndrew Sapperstein        actionBar.setDisplayOptions(0, ActionBar.DISPLAY_SHOW_TITLE);
2021cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    }
2031cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
2041cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    @Override
2051cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    protected void onResume() {
2061cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        super.onResume();
2071cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        setFullScreen(mFullScreen, false);
2081cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
2091cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        mIsPaused = false;
2101cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        if (mRestartLoader) {
2111cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein            mRestartLoader = false;
2121cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein            getLoaderManager().restartLoader(LOADER_PHOTO_LIST, null, this);
2131cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        }
2141cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    }
2151cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
2161cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    @Override
2171cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    protected void onPause() {
2181cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        mIsPaused = true;
2191cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
2201cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        super.onPause();
2211cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    }
2221cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
2231cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    @Override
2241cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    public void onBackPressed() {
2251cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        // If in full screen mode, toggle mode & eat the 'back'
2261cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        if (mFullScreen) {
2271cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein            toggleFullScreen();
2281cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        } else {
2291cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein            super.onBackPressed();
2301cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        }
2311cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    }
2321cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
2331cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    @Override
2341cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    public void onSaveInstanceState(Bundle outState) {
2351cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        super.onSaveInstanceState(outState);
2361cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
2371cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        outState.putInt(STATE_ITEM_KEY, mViewPager.getCurrentItem());
2381cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        outState.putBoolean(STATE_FULLSCREEN_KEY, mFullScreen);
2391cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    }
2401cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
2411cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    public void addScreenListener(OnScreenListener listener) {
2421cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        mScreenListeners.add(listener);
2431cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    }
2441cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
2451cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    public void removeScreenListener(OnScreenListener listener) {
2461cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        mScreenListeners.remove(listener);
2471cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    }
2481cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
249a6729336171ef61950d5f585b0f39c013ae6dcbcAndrew Sapperstein    public synchronized void addCursorListener(CursorChangedListener listener) {
250a6729336171ef61950d5f585b0f39c013ae6dcbcAndrew Sapperstein        mCursorListeners.add(listener);
251a6729336171ef61950d5f585b0f39c013ae6dcbcAndrew Sapperstein    }
252a6729336171ef61950d5f585b0f39c013ae6dcbcAndrew Sapperstein
253a6729336171ef61950d5f585b0f39c013ae6dcbcAndrew Sapperstein    public synchronized void removeCursorListener(CursorChangedListener listener) {
254a6729336171ef61950d5f585b0f39c013ae6dcbcAndrew Sapperstein        mCursorListeners.remove(listener);
255a6729336171ef61950d5f585b0f39c013ae6dcbcAndrew Sapperstein    }
256a6729336171ef61950d5f585b0f39c013ae6dcbcAndrew Sapperstein
2571cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    public boolean isFragmentFullScreen(Fragment fragment) {
2581cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        if (mViewPager == null || mAdapter == null || mAdapter.getCount() == 0) {
2591cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein            return mFullScreen;
2601cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        }
2611cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        return mFullScreen || (mViewPager.getCurrentItem() != mAdapter.getItemPosition(fragment));
2621cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    }
2631cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
2641cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    public void toggleFullScreen() {
2651cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        setFullScreen(!mFullScreen, true);
2661cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    }
2671cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
2681cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    public void onPhotoRemoved(long photoId) {
2691cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        final Cursor data = mAdapter.getCursor();
2701cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        if (data == null) {
2711cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein            // Huh?! How would this happen?
2721cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein            return;
2731cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        }
2741cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
2751cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        final int dataCount = data.getCount();
2761cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        if (dataCount <= 1) {
2771cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein            finish();
2781cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein            return;
2791cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        }
2801cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
2811cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        getLoaderManager().restartLoader(LOADER_PHOTO_LIST, null, this);
2821cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    }
2831cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
2841cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    @Override
2851cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
2861cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        if (id == LOADER_PHOTO_LIST) {
2871cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein            return new PhotoPagerLoader(this, Uri.parse(mPhotosUri), mProjection);
2881cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        }
2891cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        return null;
2901cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    }
2911cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
2921cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    @Override
2931cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    public void onLoadFinished(final Loader<Cursor> loader, final Cursor data) {
2941cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        final int id = loader.getId();
2951cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        if (id == LOADER_PHOTO_LIST) {
2961cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein            if (data == null || data.getCount() == 0) {
2971cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein                mIsEmpty = true;
2981cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein            } else {
2991cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein                mAlbumCount = data.getCount();
3001cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
301114cef99189d693ed9cd8cf778a60823d06d5298Paul Westbrook                // We're paused; don't do anything now, we'll get re-invoked
302114cef99189d693ed9cd8cf778a60823d06d5298Paul Westbrook                // when the activity becomes active again
303114cef99189d693ed9cd8cf778a60823d06d5298Paul Westbrook                // TODO(pwestbro): This shouldn't be necessary, as the loader manager should
304114cef99189d693ed9cd8cf778a60823d06d5298Paul Westbrook                // restart the loader
305114cef99189d693ed9cd8cf778a60823d06d5298Paul Westbrook                if (mIsPaused) {
306114cef99189d693ed9cd8cf778a60823d06d5298Paul Westbrook                    mRestartLoader = true;
307114cef99189d693ed9cd8cf778a60823d06d5298Paul Westbrook                    return;
308114cef99189d693ed9cd8cf778a60823d06d5298Paul Westbrook                }
309114cef99189d693ed9cd8cf778a60823d06d5298Paul Westbrook                mIsEmpty = false;
310114cef99189d693ed9cd8cf778a60823d06d5298Paul Westbrook
311114cef99189d693ed9cd8cf778a60823d06d5298Paul Westbrook                // set the selected photo
312114cef99189d693ed9cd8cf778a60823d06d5298Paul Westbrook                int itemIndex = mPhotoIndex;
313114cef99189d693ed9cd8cf778a60823d06d5298Paul Westbrook
314114cef99189d693ed9cd8cf778a60823d06d5298Paul Westbrook                // Use an index of 0 if the index wasn't specified or couldn't be found
315114cef99189d693ed9cd8cf778a60823d06d5298Paul Westbrook                if (itemIndex < 0) {
316114cef99189d693ed9cd8cf778a60823d06d5298Paul Westbrook                    itemIndex = 0;
317114cef99189d693ed9cd8cf778a60823d06d5298Paul Westbrook                }
318114cef99189d693ed9cd8cf778a60823d06d5298Paul Westbrook
319114cef99189d693ed9cd8cf778a60823d06d5298Paul Westbrook                mAdapter.swapCursor(data);
320114cef99189d693ed9cd8cf778a60823d06d5298Paul Westbrook                notifyCursorListeners(data);
321114cef99189d693ed9cd8cf778a60823d06d5298Paul Westbrook
322114cef99189d693ed9cd8cf778a60823d06d5298Paul Westbrook                mViewPager.setCurrentItem(itemIndex, false);
323114cef99189d693ed9cd8cf778a60823d06d5298Paul Westbrook                setViewActivated();
3241cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein            }
3252b4059cdcd8014265b3ec7f06b9502cebb9e9972Paul Westbrook            // Update the any action items
3262b4059cdcd8014265b3ec7f06b9502cebb9e9972Paul Westbrook            updateActionItems();
3271cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        }
3281cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    }
3291cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
3302b4059cdcd8014265b3ec7f06b9502cebb9e9972Paul Westbrook    protected void updateActionItems() {
3312b4059cdcd8014265b3ec7f06b9502cebb9e9972Paul Westbrook        // Do nothing, but allow extending classes to do work
3322b4059cdcd8014265b3ec7f06b9502cebb9e9972Paul Westbrook    }
3332b4059cdcd8014265b3ec7f06b9502cebb9e9972Paul Westbrook
334a6729336171ef61950d5f585b0f39c013ae6dcbcAndrew Sapperstein    private synchronized void notifyCursorListeners(Cursor data) {
335a6729336171ef61950d5f585b0f39c013ae6dcbcAndrew Sapperstein        // tell all of the objects listening for cursor changes
336a6729336171ef61950d5f585b0f39c013ae6dcbcAndrew Sapperstein        // that the cursor has changed
337a6729336171ef61950d5f585b0f39c013ae6dcbcAndrew Sapperstein        for (CursorChangedListener listener : mCursorListeners) {
338a6729336171ef61950d5f585b0f39c013ae6dcbcAndrew Sapperstein            listener.onCursorChanged(data);
339a6729336171ef61950d5f585b0f39c013ae6dcbcAndrew Sapperstein        }
340a6729336171ef61950d5f585b0f39c013ae6dcbcAndrew Sapperstein    }
341a6729336171ef61950d5f585b0f39c013ae6dcbcAndrew Sapperstein
3421cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    @Override
3431cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    public void onLoaderReset(Loader<Cursor> loader) {
344114cef99189d693ed9cd8cf778a60823d06d5298Paul Westbrook        // If the loader is reset, remove the reference in the adapter to this cursor
345114cef99189d693ed9cd8cf778a60823d06d5298Paul Westbrook        // TODO(pwestbro): reenable this when b/7075236 is fixed
346114cef99189d693ed9cd8cf778a60823d06d5298Paul Westbrook        // mAdapter.swapCursor(null);
3471cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    }
3481cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
3491cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    @Override
3501cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
3511cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    }
3521cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
3531cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    @Override
3541cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    public void onPageSelected(int position) {
3551cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        mPhotoIndex = position;
356509bd03a2a783f804e9456767b52e0f8ef43479bAndrew Sapperstein        setViewActivated();
3571cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    }
3581cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
3591cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    @Override
3601cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    public void onPageScrollStateChanged(int state) {
3611cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    }
3621cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
3631cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    public boolean isFragmentActive(Fragment fragment) {
3641cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        if (mViewPager == null || mAdapter == null) {
3651cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein            return false;
3661cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        }
3671cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        return mViewPager.getCurrentItem() == mAdapter.getItemPosition(fragment);
3681cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    }
3691cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
370a6729336171ef61950d5f585b0f39c013ae6dcbcAndrew Sapperstein    public void onFragmentVisible(PhotoViewFragment fragment) {
371509bd03a2a783f804e9456767b52e0f8ef43479bAndrew Sapperstein        updateActionBar(fragment);
3721cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    }
3731cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
3741cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    @Override
3751cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    public InterceptType onTouchIntercept(float origX, float origY) {
3761cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        boolean interceptLeft = false;
3771cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        boolean interceptRight = false;
3781cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
3791cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        for (OnScreenListener listener : mScreenListeners) {
3801cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein            if (!interceptLeft) {
3811cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein                interceptLeft = listener.onInterceptMoveLeft(origX, origY);
3821cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein            }
3831cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein            if (!interceptRight) {
3841cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein                interceptRight = listener.onInterceptMoveRight(origX, origY);
3851cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein            }
3861cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein            listener.onViewActivated();
3871cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        }
3881cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
3891cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        if (interceptLeft) {
3901cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein            if (interceptRight) {
3911cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein                return InterceptType.BOTH;
3921cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein            }
3931cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein            return InterceptType.LEFT;
3941cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        } else if (interceptRight) {
3951cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein            return InterceptType.RIGHT;
3961cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        }
3971cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        return InterceptType.NONE;
3981cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    }
3991cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
4001cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    /**
4011cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein     * Updates the title bar according to the value of {@link #mFullScreen}.
4021cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein     */
403b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein    private void setFullScreen(boolean fullScreen, boolean setDelayedRunnable) {
4041cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        final boolean fullScreenChanged = (fullScreen != mFullScreen);
4051cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        mFullScreen = fullScreen;
4061cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
4071cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        if (mFullScreen) {
408b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein            setLightsOutMode(true);
409509bd03a2a783f804e9456767b52e0f8ef43479bAndrew Sapperstein            cancelActionBarHideRunnable();
4101cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        } else {
411b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein            setLightsOutMode(false);
412b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein            if (setDelayedRunnable) {
413509bd03a2a783f804e9456767b52e0f8ef43479bAndrew Sapperstein                postActionBarHideRunnableWithDelay();
414b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein            }
4151cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        }
4161cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
4171cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        if (fullScreenChanged) {
4181cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein            for (OnScreenListener listener : mScreenListeners) {
419b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein                listener.onFullScreenChanged(mFullScreen);
420b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein            }
421b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein        }
422b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein    }
423b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein
424509bd03a2a783f804e9456767b52e0f8ef43479bAndrew Sapperstein    private void postActionBarHideRunnableWithDelay() {
425114cef99189d693ed9cd8cf778a60823d06d5298Paul Westbrook        mHandler.postDelayed(mActionBarHideRunnable,
426509bd03a2a783f804e9456767b52e0f8ef43479bAndrew Sapperstein                mActionBarHideDelayTime);
427509bd03a2a783f804e9456767b52e0f8ef43479bAndrew Sapperstein    }
428509bd03a2a783f804e9456767b52e0f8ef43479bAndrew Sapperstein
429509bd03a2a783f804e9456767b52e0f8ef43479bAndrew Sapperstein    private void cancelActionBarHideRunnable() {
430114cef99189d693ed9cd8cf778a60823d06d5298Paul Westbrook        mHandler.removeCallbacks(mActionBarHideRunnable);
431509bd03a2a783f804e9456767b52e0f8ef43479bAndrew Sapperstein    }
432509bd03a2a783f804e9456767b52e0f8ef43479bAndrew Sapperstein
433b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein    private void setLightsOutMode(boolean enabled) {
434b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
435b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein            int flags = enabled
436b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein                    ? View.SYSTEM_UI_FLAG_LOW_PROFILE
437b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein                    | View.SYSTEM_UI_FLAG_FULLSCREEN
438b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein                    | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
439b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein                    | View.SYSTEM_UI_FLAG_LAYOUT_STABLE
440b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein                    : View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
441b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein                    | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
442b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein
443b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein            // using mViewPager since we have it and we need a view
444b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein            mViewPager.setSystemUiVisibility(flags);
445b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein        } else {
446b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein            final ActionBar actionBar = getActionBar();
447b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein            if (enabled) {
448b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein                actionBar.hide();
449b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein            } else {
450b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein                actionBar.show();
4511cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein            }
452b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein            int flags = enabled
453b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein                    ? View.SYSTEM_UI_FLAG_LOW_PROFILE
454b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein                    : View.SYSTEM_UI_FLAG_VISIBLE;
455b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein            mViewPager.setSystemUiVisibility(flags);
4561cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        }
4571cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    }
4581cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
459b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein    private Runnable mActionBarHideRunnable = new Runnable() {
460b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein        @Override
461b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein        public void run() {
462b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein            PhotoViewActivity.this.setLightsOutMode(true);
463b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein        }
464b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein    };
465b81f8c963a0d97034872f14f4e2294d1e2b44da1Andrew Sapperstein
466a6729336171ef61950d5f585b0f39c013ae6dcbcAndrew Sapperstein    public void setViewActivated() {
4671cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        for (OnScreenListener listener : mScreenListeners) {
4681cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein            listener.onViewActivated();
4691cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        }
4701cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    }
4711cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
4721cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    /**
4731cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein     * Adjusts the activity title and subtitle to reflect the photo name and count.
4741cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein     */
475509bd03a2a783f804e9456767b52e0f8ef43479bAndrew Sapperstein    protected void updateActionBar(PhotoViewFragment fragment) {
4761cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        final int position = mViewPager.getCurrentItem() + 1;
47776aca5f8ae1a795aa4f351209a41545b6b3ade6eAndrew Sapperstein        final String title;
4781cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        final String subtitle;
4791cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        final boolean hasAlbumCount = mAlbumCount >= 0;
4801cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
4811cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        final Cursor cursor = getCursorAtProperPosition();
4821cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
4831cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        if (cursor != null) {
4841cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein            final int photoNameIndex = cursor.getColumnIndex(PhotoContract.PhotoViewColumns.NAME);
48576aca5f8ae1a795aa4f351209a41545b6b3ade6eAndrew Sapperstein            title = cursor.getString(photoNameIndex);
48676aca5f8ae1a795aa4f351209a41545b6b3ade6eAndrew Sapperstein        } else {
48776aca5f8ae1a795aa4f351209a41545b6b3ade6eAndrew Sapperstein            title = null;
4881cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        }
4891cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
4901cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        if (mIsEmpty || !hasAlbumCount || position <= 0) {
4911cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein            subtitle = null;
4921cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        } else {
4931cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein            subtitle = getResources().getString(R.string.photo_view_count, position, mAlbumCount);
4941cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        }
4951cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
4961cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        final ActionBar actionBar = getActionBar();
49776aca5f8ae1a795aa4f351209a41545b6b3ade6eAndrew Sapperstein        actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_TITLE, ActionBar.DISPLAY_SHOW_TITLE);
49876aca5f8ae1a795aa4f351209a41545b6b3ade6eAndrew Sapperstein        actionBar.setTitle(title);
4991cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        actionBar.setSubtitle(subtitle);
5001cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    }
5011cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
5021cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    /**
5031cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein     * Utility method that will return the cursor that contains the data
5041cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein     * at the current position so that it refers to the current image on screen.
5051cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein     * @return the cursor at the current position or
5061cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein     * null if no cursor exists or if the {@link PhotoViewPager} is null.
5071cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein     */
5081cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    public Cursor getCursorAtProperPosition() {
5091cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        if (mViewPager == null) {
5101cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein            return null;
5111cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        }
5121cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
5131cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        final int position = mViewPager.getCurrentItem();
5141cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        final Cursor cursor = mAdapter.getCursor();
5151cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
5161cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        if (cursor == null) {
5171cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein            return null;
5181cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        }
5191cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
5201cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        cursor.moveToPosition(position);
5211cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein
5221cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein        return cursor;
5231cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein    }
5249ceb1b41122f649cd26234f34edc2c1cf75b2f95Andrew Sapperstein
5259ceb1b41122f649cd26234f34edc2c1cf75b2f95Andrew Sapperstein    public Cursor getCursor() {
5269ceb1b41122f649cd26234f34edc2c1cf75b2f95Andrew Sapperstein        return (mAdapter == null) ? null : mAdapter.getCursor();
5279ceb1b41122f649cd26234f34edc2c1cf75b2f95Andrew Sapperstein    }
528509bd03a2a783f804e9456767b52e0f8ef43479bAndrew Sapperstein
529509bd03a2a783f804e9456767b52e0f8ef43479bAndrew Sapperstein    @Override
530509bd03a2a783f804e9456767b52e0f8ef43479bAndrew Sapperstein    public void onMenuVisibilityChanged(boolean isVisible) {
531509bd03a2a783f804e9456767b52e0f8ef43479bAndrew Sapperstein        if (isVisible) {
532509bd03a2a783f804e9456767b52e0f8ef43479bAndrew Sapperstein            cancelActionBarHideRunnable();
533509bd03a2a783f804e9456767b52e0f8ef43479bAndrew Sapperstein        } else {
534509bd03a2a783f804e9456767b52e0f8ef43479bAndrew Sapperstein            postActionBarHideRunnableWithDelay();
535509bd03a2a783f804e9456767b52e0f8ef43479bAndrew Sapperstein        }
536509bd03a2a783f804e9456767b52e0f8ef43479bAndrew Sapperstein    }
5375f0470b259c56dd5df171948d6efd4219a3a17f8Mark Wei
5385f0470b259c56dd5df171948d6efd4219a3a17f8Mark Wei    public void onNewPhotoLoaded() {
5395f0470b259c56dd5df171948d6efd4219a3a17f8Mark Wei    }
5401cc4b2144a45abb495c8b14f6cfc5a10fb5e8ba8Andrew Sapperstein}
541