AlbumSetPage.java revision b21b8e58a604f6c701245d84b141b5b87663192b
1f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin/*
2f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Copyright (C) 2010 The Android Open Source Project
3f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin *
4f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Licensed under the Apache License, Version 2.0 (the "License");
5f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * you may not use this file except in compliance with the License.
6f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * You may obtain a copy of the License at
7f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin *
8f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin *      http://www.apache.org/licenses/LICENSE-2.0
9f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin *
10f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Unless required by applicable law or agreed to in writing, software
11f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * distributed under the License is distributed on an "AS IS" BASIS,
12f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * See the License for the specific language governing permissions and
14f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * limitations under the License.
15f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin */
16f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
17f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linpackage com.android.gallery3d.app;
18f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
191f4e6d14bba7290ea0268fbde28ffc664d4f7004Ray Chenimport android.app.Activity;
201f4e6d14bba7290ea0268fbde28ffc664d4f7004Ray Chenimport android.content.Context;
211f4e6d14bba7290ea0268fbde28ffc664d4f7004Ray Chenimport android.content.Intent;
221f4e6d14bba7290ea0268fbde28ffc664d4f7004Ray Chenimport android.graphics.Rect;
231f4e6d14bba7290ea0268fbde28ffc664d4f7004Ray Chenimport android.os.Bundle;
2490fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huangimport android.os.Handler;
2590fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huangimport android.os.Message;
261f4e6d14bba7290ea0268fbde28ffc664d4f7004Ray Chenimport android.os.Vibrator;
271f4e6d14bba7290ea0268fbde28ffc664d4f7004Ray Chenimport android.widget.Toast;
281f4e6d14bba7290ea0268fbde28ffc664d4f7004Ray Chen
29b21b8e58a604f6c701245d84b141b5b87663192bOwen Linimport com.actionbarsherlock.view.Menu;
30b21b8e58a604f6c701245d84b141b5b87663192bOwen Linimport com.actionbarsherlock.view.MenuInflater;
31b21b8e58a604f6c701245d84b141b5b87663192bOwen Linimport com.actionbarsherlock.view.MenuItem;
32f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.R;
33f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.common.Utils;
34f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.data.DataManager;
35f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.data.MediaDetails;
36f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.data.MediaObject;
37f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.data.MediaSet;
38f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.data.Path;
39f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.picasasource.PicasaSource;
40f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.settings.GallerySettings;
41f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.ui.ActionModeHandler;
42f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.ui.ActionModeHandler.ActionModeListener;
43c3d8ac3b9504346dafc49e006b5f732dd1db21e8Owen Linimport com.android.gallery3d.ui.AlbumSetSlotRenderer;
444105e22d72d7a44e67cba4a58ad88018ed664d10Ray Chenimport com.android.gallery3d.ui.DetailsHelper;
454105e22d72d7a44e67cba4a58ad88018ed664d10Ray Chenimport com.android.gallery3d.ui.DetailsHelper.CloseListener;
4690fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huangimport com.android.gallery3d.ui.FadeTexture;
47f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.ui.GLCanvas;
4871632ac6c1596dd1fd477f95e268f96ad72ea572Owen Linimport com.android.gallery3d.ui.GLRoot;
49f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.ui.GLView;
50f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.ui.SelectionManager;
51f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport com.android.gallery3d.ui.SlotView;
5290fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huangimport com.android.gallery3d.ui.SynchronizedHandler;
5357cbaa1ef40d2215c6400f5ae4af3a09e67abb2dHung-ying Tyanimport com.android.gallery3d.util.Future;
54fbdd338d83596ba545a8a7c8105d2ad7b5df56e6Owen Linimport com.android.gallery3d.util.GalleryUtils;
55daf88feb0aab5806723b850d22a372cafe758239Ray Chenimport com.android.gallery3d.util.HelpUtils;
56f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
57f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linpublic class AlbumSetPage extends ActivityState implements
58f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        SelectionManager.SelectionListener, GalleryActionBar.ClusterRunner,
5957cbaa1ef40d2215c6400f5ae4af3a09e67abb2dHung-ying Tyan        EyePosition.EyePositionListener, MediaSet.SyncListener {
60f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    @SuppressWarnings("unused")
61f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private static final String TAG = "AlbumSetPage";
62f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
6390fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang    private static final int MSG_PICK_ALBUM = 1;
6490fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang
65f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public static final String KEY_MEDIA_PATH = "media-path";
66f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public static final String KEY_SET_TITLE = "set-title";
67f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public static final String KEY_SET_SUBTITLE = "set-subtitle";
68b5f8d908c5dd287052cd49eddaf1f82d858cca03Ray Chen    public static final String KEY_SELECTED_CLUSTER_TYPE = "selected-cluster";
696cf807453fb58ccd4cc513ff187b306c7090e67cOwen Lin
70f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private static final int DATA_CACHE_SIZE = 256;
71f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private static final int REQUEST_DO_ANIMATION = 1;
72f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
73fbdd338d83596ba545a8a7c8105d2ad7b5df56e6Owen Lin    private static final int BIT_LOADING_RELOAD = 1;
74fbdd338d83596ba545a8a7c8105d2ad7b5df56e6Owen Lin    private static final int BIT_LOADING_SYNC = 2;
75fbdd338d83596ba545a8a7c8105d2ad7b5df56e6Owen Lin
76f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private boolean mIsActive = false;
777260f6f74d465520e4497b23fe56f98abb0c15a2Owen Lin    private SlotView mSlotView;
78c3d8ac3b9504346dafc49e006b5f732dd1db21e8Owen Lin    private AlbumSetSlotRenderer mAlbumSetView;
79f0c89374bfc008fb79ac3cb91cfd6d565d203041Bobby Georgescu    private Config.AlbumSetPage mConfig;
80f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
81f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private MediaSet mMediaSet;
829c21268fa8d394cca6cab78dd023a52e0b147a6eRay Chen    private String mTitle;
83f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private String mSubtitle;
84b5f8d908c5dd287052cd49eddaf1f82d858cca03Ray Chen    private boolean mShowClusterMenu;
858cab3e872dd95e55ba34fdb94269a0c5069e72aeRay Chen    private GalleryActionBar mActionBar;
86b5f8d908c5dd287052cd49eddaf1f82d858cca03Ray Chen    private int mSelectedAction;
871f4e6d14bba7290ea0268fbde28ffc664d4f7004Ray Chen    private Vibrator mVibrator;
88f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
89f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    protected SelectionManager mSelectionManager;
90c3d8ac3b9504346dafc49e006b5f732dd1db21e8Owen Lin    private AlbumSetDataLoader mAlbumSetDataAdapter;
91f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
92f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private boolean mGetContent;
93f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private boolean mGetAlbum;
94f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private ActionModeHandler mActionModeHandler;
954105e22d72d7a44e67cba4a58ad88018ed664d10Ray Chen    private DetailsHelper mDetailsHelper;
964105e22d72d7a44e67cba4a58ad88018ed664d10Ray Chen    private MyDetailsSource mDetailsSource;
97f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private boolean mShowDetails;
98f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private EyePosition mEyePosition;
9990fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang    private Handler mHandler;
100f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
101f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    // The eyes' position of the user, the origin is at the center of the
102f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    // device and the unit is in pixels.
103f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private float mX;
104f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private float mY;
105f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private float mZ;
106f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
10757cbaa1ef40d2215c6400f5ae4af3a09e67abb2dHung-ying Tyan    private Future<Integer> mSyncTask = null;
10857cbaa1ef40d2215c6400f5ae4af3a09e67abb2dHung-ying Tyan
109fbdd338d83596ba545a8a7c8105d2ad7b5df56e6Owen Lin    private int mLoadingBits = 0;
110fbdd338d83596ba545a8a7c8105d2ad7b5df56e6Owen Lin    private boolean mInitialSynced = false;
111fbdd338d83596ba545a8a7c8105d2ad7b5df56e6Owen Lin
112915c2c5b2c367df71599370613af0924bd7c4887Bobby Georgescu    @Override
113915c2c5b2c367df71599370613af0924bd7c4887Bobby Georgescu    protected int getBackgroundColorId() {
114915c2c5b2c367df71599370613af0924bd7c4887Bobby Georgescu        return R.color.albumset_background;
115915c2c5b2c367df71599370613af0924bd7c4887Bobby Georgescu    }
116915c2c5b2c367df71599370613af0924bd7c4887Bobby Georgescu
117dbf4ba12afba115888493caa34937643257e2bb1Ray Chen    private final GLView mRootPane = new GLView() {
118dbf4ba12afba115888493caa34937643257e2bb1Ray Chen        private final float mMatrix[] = new float[16];
119f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
120f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        @Override
121ff951a85c3c9015ef7ccd8902e69ce88360a0cb8Chih-Chung Chang        protected void renderBackground(GLCanvas view) {
122915c2c5b2c367df71599370613af0924bd7c4887Bobby Georgescu            view.clearBuffer(getBackgroundColor());
123ff951a85c3c9015ef7ccd8902e69ce88360a0cb8Chih-Chung Chang        }
124ff951a85c3c9015ef7ccd8902e69ce88360a0cb8Chih-Chung Chang
125ff951a85c3c9015ef7ccd8902e69ce88360a0cb8Chih-Chung Chang        @Override
126f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        protected void onLayout(
127f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                boolean changed, int left, int top, int right, int bottom) {
128f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            mEyePosition.resetPosition();
129f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
130f0c89374bfc008fb79ac3cb91cfd6d565d203041Bobby Georgescu            int slotViewTop = mActionBar.getHeight() + mConfig.paddingTop;
131f0c89374bfc008fb79ac3cb91cfd6d565d203041Bobby Georgescu            int slotViewBottom = bottom - top - mConfig.paddingBottom;
132f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            int slotViewRight = right - left;
133f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
134f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            if (mShowDetails) {
1354105e22d72d7a44e67cba4a58ad88018ed664d10Ray Chen                mDetailsHelper.layout(left, slotViewTop, right, bottom);
136f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            } else {
13731cac30e46a293f6d0901e22c6ab0d083cae7021Owen Lin                mAlbumSetView.setHighlightItemPath(null);
138f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
139f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
1407260f6f74d465520e4497b23fe56f98abb0c15a2Owen Lin            mSlotView.layout(0, slotViewTop, slotViewRight, slotViewBottom);
141f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
142f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
143f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        @Override
144f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        protected void render(GLCanvas canvas) {
145f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            canvas.save(GLCanvas.SAVE_FLAG_MATRIX);
146f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            GalleryUtils.setViewPointMatrix(mMatrix,
147f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                    getWidth() / 2 + mX, getHeight() / 2 + mY, mZ);
148f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            canvas.multiplyMatrix(mMatrix, 0);
149f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            super.render(canvas);
150f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            canvas.restore();
151f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
152f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    };
153f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
154f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    @Override
155f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public void onEyePositionChanged(float x, float y, float z) {
156f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mRootPane.lockRendering();
157f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mX = x;
158f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mY = y;
159f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mZ = z;
160f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mRootPane.unlockRendering();
161f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mRootPane.invalidate();
162f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
163f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
164f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    @Override
165f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public void onBackPressed() {
166f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        if (mShowDetails) {
167f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            hideDetails();
168f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        } else if (mSelectionManager.inSelectionMode()) {
169f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            mSelectionManager.leaveSelectionMode();
170f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        } else {
171f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            super.onBackPressed();
172f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
173f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
174f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
1752341c197b0becf99422e8ad305def77df6161714Owen Lin    private void getSlotCenter(int slotIndex, int center[]) {
176f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        Rect offset = new Rect();
1777260f6f74d465520e4497b23fe56f98abb0c15a2Owen Lin        mRootPane.getBoundsOf(mSlotView, offset);
1787260f6f74d465520e4497b23fe56f98abb0c15a2Owen Lin        Rect r = mSlotView.getSlotRect(slotIndex);
1797260f6f74d465520e4497b23fe56f98abb0c15a2Owen Lin        int scrollX = mSlotView.getScrollX();
1807260f6f74d465520e4497b23fe56f98abb0c15a2Owen Lin        int scrollY = mSlotView.getScrollY();
181f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        center[0] = offset.left + (r.left + r.right) / 2 - scrollX;
182f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        center[1] = offset.top + (r.top + r.bottom) / 2 - scrollY;
183f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
184f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
185f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public void onSingleTapUp(int slotIndex) {
186cf06397b2bc65335fb97d5788f18cad4897126a2Owen Lin        if (!mIsActive) return;
18790fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang
18890fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang        if (mSelectionManager.inSelectionMode()) {
18990fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang            MediaSet targetSet = mAlbumSetDataAdapter.getMediaSet(slotIndex);
19090fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang            if (targetSet == null) return; // Content is dirty, we shall reload soon
19190fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang            mSelectionManager.toggle(targetSet.getPath());
19290fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang            mSlotView.invalidate();
19390fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang        } else {
19490fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang            // Show pressed-up animation for the single-tap.
19590fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang            mAlbumSetView.setPressedIndex(slotIndex);
19690fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang            mAlbumSetView.setPressedUp();
19790fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang            mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_PICK_ALBUM, slotIndex, 0),
19890fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang                    FadeTexture.DURATION);
19990fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang        }
20090fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang    }
20190fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang
20290fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang    private void pickAlbum(int slotIndex) {
20390fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang        if (!mIsActive) return;
20490fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang
205f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        MediaSet targetSet = mAlbumSetDataAdapter.getMediaSet(slotIndex);
206f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        if (targetSet == null) return; // Content is dirty, we shall reload soon
20790fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang        String mediaPath = targetSet.getPath().toString();
208f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
20990fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang        Bundle data = new Bundle(getData());
21090fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang        int[] center = new int[2];
21190fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang        getSlotCenter(slotIndex, center);
21290fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang        data.putIntArray(AlbumPage.KEY_SET_CENTER, center);
21390fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang        if (mGetAlbum && targetSet.isLeafAlbum()) {
214b21b8e58a604f6c701245d84b141b5b87663192bOwen Lin            Activity activity = mActivity;
21590fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang            Intent result = new Intent()
21690fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang                    .putExtra(AlbumPicker.KEY_ALBUM_PATH, targetSet.getPath().toString());
21790fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang            activity.setResult(Activity.RESULT_OK, result);
21890fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang            activity.finish();
21990fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang        } else if (targetSet.getSubMediaSetCount() > 0) {
22090fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang            data.putString(AlbumSetPage.KEY_MEDIA_PATH, mediaPath);
22190fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang            mActivity.getStateManager().startStateForResult(
22290fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang                    AlbumSetPage.class, REQUEST_DO_ANIMATION, data);
223f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        } else {
22490fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang            if (!mGetContent && (targetSet.getSupportedOperations()
22590fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang                    & MediaObject.SUPPORT_IMPORT) != 0) {
22690fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang                data.putBoolean(AlbumPage.KEY_AUTO_SELECT_ALL, true);
22790fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang            }
22890fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang            data.putString(AlbumPage.KEY_MEDIA_PATH, mediaPath);
22990fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang            boolean inAlbum = mActivity.getStateManager().hasStateClass(AlbumPage.class);
23090fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang            // We only show cluster menu in the first AlbumPage in stack
23190fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang            data.putBoolean(AlbumPage.KEY_SHOW_CLUSTER_MENU, !inAlbum);
23290fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang            mActivity.getStateManager().startStateForResult(
23390fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang                    AlbumPage.class, REQUEST_DO_ANIMATION, data);
234f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
235f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
236f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
237bc2154199aee16762e3758ad0cfed685323d9a9fChih-Chung Chang    private void onDown(int index) {
23831cac30e46a293f6d0901e22c6ab0d083cae7021Owen Lin        mAlbumSetView.setPressedIndex(index);
239bc2154199aee16762e3758ad0cfed685323d9a9fChih-Chung Chang    }
240bc2154199aee16762e3758ad0cfed685323d9a9fChih-Chung Chang
24190fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang    private void onUp(boolean followedByLongPress) {
24290fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang        if (followedByLongPress) {
24390fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang            // Avoid showing press-up animations for long-press.
24490fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang            mAlbumSetView.setPressedIndex(-1);
24590fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang        } else {
24690fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang            mAlbumSetView.setPressedUp();
24790fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang        }
248bc2154199aee16762e3758ad0cfed685323d9a9fChih-Chung Chang    }
249bc2154199aee16762e3758ad0cfed685323d9a9fChih-Chung Chang
250f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public void onLongTap(int slotIndex) {
251f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        if (mGetContent || mGetAlbum) return;
25290fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang        MediaSet set = mAlbumSetDataAdapter.getMediaSet(slotIndex);
25390fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang        if (set == null) return;
25490fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang        mSelectionManager.setAutoLeaveSelectionMode(true);
25590fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang        mSelectionManager.toggle(set.getPath());
25690fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang        mSlotView.invalidate();
257f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
258f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
2592341c197b0becf99422e8ad305def77df6161714Owen Lin    @Override
260f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public void doCluster(int clusterType) {
261f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        String basePath = mMediaSet.getPath().toString();
262f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        String newPath = FilterUtils.switchClusterPath(basePath, clusterType);
263f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        Bundle data = new Bundle(getData());
264f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        data.putString(AlbumSetPage.KEY_MEDIA_PATH, newPath);
265b5f8d908c5dd287052cd49eddaf1f82d858cca03Ray Chen        data.putInt(KEY_SELECTED_CLUSTER_TYPE, clusterType);
266f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mActivity.getStateManager().switchState(this, AlbumSetPage.class, data);
267f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
268f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
269f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    @Override
270f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public void onCreate(Bundle data, Bundle restoreState) {
271f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        initializeViews();
272f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        initializeData(data);
2731f4e6d14bba7290ea0268fbde28ffc664d4f7004Ray Chen        Context context = mActivity.getAndroidContext();
274f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mGetContent = data.getBoolean(Gallery.KEY_GET_CONTENT, false);
275f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mGetAlbum = data.getBoolean(Gallery.KEY_GET_ALBUM, false);
2769c21268fa8d394cca6cab78dd023a52e0b147a6eRay Chen        mTitle = data.getString(AlbumSetPage.KEY_SET_TITLE);
277f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mSubtitle = data.getString(AlbumSetPage.KEY_SET_SUBTITLE);
2781f4e6d14bba7290ea0268fbde28ffc664d4f7004Ray Chen        mEyePosition = new EyePosition(context, this);
2794105e22d72d7a44e67cba4a58ad88018ed664d10Ray Chen        mDetailsSource = new MyDetailsSource();
2801f4e6d14bba7290ea0268fbde28ffc664d4f7004Ray Chen        mVibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
2818cab3e872dd95e55ba34fdb94269a0c5069e72aeRay Chen        mActionBar = mActivity.getGalleryActionBar();
2828cab3e872dd95e55ba34fdb94269a0c5069e72aeRay Chen        mSelectedAction = data.getInt(AlbumSetPage.KEY_SELECTED_CLUSTER_TYPE,
2838cab3e872dd95e55ba34fdb94269a0c5069e72aeRay Chen                FilterUtils.CLUSTER_BY_ALBUM);
28490fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang
28590fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang        mHandler = new SynchronizedHandler(mActivity.getGLRoot()) {
28690fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang            @Override
28790fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang            public void handleMessage(Message message) {
28890fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang                switch (message.what) {
28990fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang                    case MSG_PICK_ALBUM: {
29090fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang                        pickAlbum(message.arg1);
29190fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang                        break;
29290fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang                    }
29390fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang                    default: throw new AssertionError(message.what);
29490fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang                }
29590fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang            }
29690fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang        };
297f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
298f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
299fbdd338d83596ba545a8a7c8105d2ad7b5df56e6Owen Lin    private void clearLoadingBit(int loadingBit) {
300fbdd338d83596ba545a8a7c8105d2ad7b5df56e6Owen Lin        mLoadingBits &= ~loadingBit;
301d05b0be120bb217b4f56add24a4b31bee92455b2Chih-Chung Chang        if (mLoadingBits == 0 && mIsActive) {
302fbdd338d83596ba545a8a7c8105d2ad7b5df56e6Owen Lin            // Only show toast when there's no album and we are going to finish
303fbdd338d83596ba545a8a7c8105d2ad7b5df56e6Owen Lin            // the page. Toast is redundant if we are going to stay on this page.
304fbdd338d83596ba545a8a7c8105d2ad7b5df56e6Owen Lin            if ((mAlbumSetDataAdapter.size() == 0)) {
305fbdd338d83596ba545a8a7c8105d2ad7b5df56e6Owen Lin                if (mActivity.getStateManager().getStateCount() > 1) {
306b21b8e58a604f6c701245d84b141b5b87663192bOwen Lin                    Toast.makeText(mActivity,
307e8c1e69f85efb8673d0606f3aca729a366038753Ray Chen                            R.string.empty_album, Toast.LENGTH_LONG).show();
308fbdd338d83596ba545a8a7c8105d2ad7b5df56e6Owen Lin                    mActivity.getStateManager().finishState(this);
309fbdd338d83596ba545a8a7c8105d2ad7b5df56e6Owen Lin                }
310fbdd338d83596ba545a8a7c8105d2ad7b5df56e6Owen Lin            }
311fbdd338d83596ba545a8a7c8105d2ad7b5df56e6Owen Lin        }
312fbdd338d83596ba545a8a7c8105d2ad7b5df56e6Owen Lin    }
313fbdd338d83596ba545a8a7c8105d2ad7b5df56e6Owen Lin
314fbdd338d83596ba545a8a7c8105d2ad7b5df56e6Owen Lin    private void setLoadingBit(int loadingBit) {
315fbdd338d83596ba545a8a7c8105d2ad7b5df56e6Owen Lin        mLoadingBits |= loadingBit;
316fbdd338d83596ba545a8a7c8105d2ad7b5df56e6Owen Lin    }
317fbdd338d83596ba545a8a7c8105d2ad7b5df56e6Owen Lin
318f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    @Override
319f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public void onPause() {
320f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        super.onPause();
321f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mIsActive = false;
322f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mActionModeHandler.pause();
323f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mAlbumSetDataAdapter.pause();
324f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mAlbumSetView.pause();
325f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mEyePosition.pause();
3264105e22d72d7a44e67cba4a58ad88018ed664d10Ray Chen        DetailsHelper.pause();
327fe1625c46f8258be4cd5e5e1ba69b584c1fe1a49Ray Chen        // Call disableClusterMenu to avoid receiving callback after paused.
328fe1625c46f8258be4cd5e5e1ba69b584c1fe1a49Ray Chen        // Don't hide menu here otherwise the list menu will disappear earlier than
329fe1625c46f8258be4cd5e5e1ba69b584c1fe1a49Ray Chen        // the action bar, which is janky and unwanted behavior.
3308cab3e872dd95e55ba34fdb94269a0c5069e72aeRay Chen        mActionBar.disableClusterMenu(false);
33157cbaa1ef40d2215c6400f5ae4af3a09e67abb2dHung-ying Tyan        if (mSyncTask != null) {
33257cbaa1ef40d2215c6400f5ae4af3a09e67abb2dHung-ying Tyan            mSyncTask.cancel();
33357cbaa1ef40d2215c6400f5ae4af3a09e67abb2dHung-ying Tyan            mSyncTask = null;
334fbdd338d83596ba545a8a7c8105d2ad7b5df56e6Owen Lin            clearLoadingBit(BIT_LOADING_SYNC);
33557cbaa1ef40d2215c6400f5ae4af3a09e67abb2dHung-ying Tyan        }
336f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
337f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
338f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    @Override
339f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public void onResume() {
340f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        super.onResume();
341f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mIsActive = true;
342f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        setContentPane(mRootPane);
343fe49be45412f8d0f68343662318e73822da486c8Owen Lin
344fe49be45412f8d0f68343662318e73822da486c8Owen Lin        // Set the reload bit here to prevent it exit this page in clearLoadingBit().
345fe49be45412f8d0f68343662318e73822da486c8Owen Lin        setLoadingBit(BIT_LOADING_RELOAD);
346f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mAlbumSetDataAdapter.resume();
347fe49be45412f8d0f68343662318e73822da486c8Owen Lin
348f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mAlbumSetView.resume();
349f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mEyePosition.resume();
350f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mActionModeHandler.resume();
3518cab3e872dd95e55ba34fdb94269a0c5069e72aeRay Chen        if (mShowClusterMenu) {
3528cab3e872dd95e55ba34fdb94269a0c5069e72aeRay Chen            mActionBar.enableClusterMenu(mSelectedAction, this);
353dbf4ba12afba115888493caa34937643257e2bb1Ray Chen        }
354fbdd338d83596ba545a8a7c8105d2ad7b5df56e6Owen Lin        if (!mInitialSynced) {
355fbdd338d83596ba545a8a7c8105d2ad7b5df56e6Owen Lin            setLoadingBit(BIT_LOADING_SYNC);
356fe49be45412f8d0f68343662318e73822da486c8Owen Lin            mSyncTask = mMediaSet.requestSync(AlbumSetPage.this);
357fbdd338d83596ba545a8a7c8105d2ad7b5df56e6Owen Lin        }
358f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
359f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
360f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private void initializeData(Bundle data) {
361f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        String mediaPath = data.getString(AlbumSetPage.KEY_MEDIA_PATH);
362f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mMediaSet = mActivity.getDataManager().getMediaSet(mediaPath);
363f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mSelectionManager.setSourceMediaSet(mMediaSet);
364c3d8ac3b9504346dafc49e006b5f732dd1db21e8Owen Lin        mAlbumSetDataAdapter = new AlbumSetDataLoader(
365f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                mActivity, mMediaSet, DATA_CACHE_SIZE);
366f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mAlbumSetDataAdapter.setLoadingListener(new MyLoadingListener());
367f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mAlbumSetView.setModel(mAlbumSetDataAdapter);
368f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
369f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
370f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private void initializeViews() {
371f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mSelectionManager = new SelectionManager(mActivity, true);
372f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mSelectionManager.setSelectionListener(this);
373f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
374b21b8e58a604f6c701245d84b141b5b87663192bOwen Lin        mConfig = Config.AlbumSetPage.get(mActivity);
375f0c89374bfc008fb79ac3cb91cfd6d565d203041Bobby Georgescu        mSlotView = new SlotView(mActivity, mConfig.slotViewSpec);
376c3d8ac3b9504346dafc49e006b5f732dd1db21e8Owen Lin        mAlbumSetView = new AlbumSetSlotRenderer(
377915c2c5b2c367df71599370613af0924bd7c4887Bobby Georgescu                mActivity, mSelectionManager, mSlotView, mConfig.labelSpec,
378915c2c5b2c367df71599370613af0924bd7c4887Bobby Georgescu                mConfig.placeholderColor);
3797260f6f74d465520e4497b23fe56f98abb0c15a2Owen Lin        mSlotView.setSlotRenderer(mAlbumSetView);
3807260f6f74d465520e4497b23fe56f98abb0c15a2Owen Lin        mSlotView.setListener(new SlotView.SimpleListener() {
381f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            @Override
382bc2154199aee16762e3758ad0cfed685323d9a9fChih-Chung Chang            public void onDown(int index) {
383bc2154199aee16762e3758ad0cfed685323d9a9fChih-Chung Chang                AlbumSetPage.this.onDown(index);
384bc2154199aee16762e3758ad0cfed685323d9a9fChih-Chung Chang            }
385bc2154199aee16762e3758ad0cfed685323d9a9fChih-Chung Chang
386bc2154199aee16762e3758ad0cfed685323d9a9fChih-Chung Chang            @Override
38790fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang            public void onUp(boolean followedByLongPress) {
38890fe70f11b0961e1e5ae353cdf563236a55f502dYuli Huang                AlbumSetPage.this.onUp(followedByLongPress);
389bc2154199aee16762e3758ad0cfed685323d9a9fChih-Chung Chang            }
390bc2154199aee16762e3758ad0cfed685323d9a9fChih-Chung Chang
391bc2154199aee16762e3758ad0cfed685323d9a9fChih-Chung Chang            @Override
392f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            public void onSingleTapUp(int slotIndex) {
393f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                AlbumSetPage.this.onSingleTapUp(slotIndex);
394f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
395bc2154199aee16762e3758ad0cfed685323d9a9fChih-Chung Chang
396f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            @Override
397f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            public void onLongTap(int slotIndex) {
398f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                AlbumSetPage.this.onLongTap(slotIndex);
399f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
400f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        });
401f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
402f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mActionModeHandler = new ActionModeHandler(mActivity, mSelectionManager);
403f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mActionModeHandler.setActionModeListener(new ActionModeListener() {
4042341c197b0becf99422e8ad305def77df6161714Owen Lin            @Override
405f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            public boolean onActionItemClicked(MenuItem item) {
406f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                return onItemSelected(item);
407f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
408f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        });
4097260f6f74d465520e4497b23fe56f98abb0c15a2Owen Lin        mRootPane.addComponent(mSlotView);
410f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
411f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
412f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    @Override
413f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    protected boolean onCreateActionBar(Menu menu) {
414b21b8e58a604f6c701245d84b141b5b87663192bOwen Lin        Activity activity = mActivity;
4152bb717f1ea38e2ce33dd102a23afe6bfacb5675cOwen Lin        final boolean inAlbum = mActivity.getStateManager().hasStateClass(AlbumPage.class);
416b21b8e58a604f6c701245d84b141b5b87663192bOwen Lin        MenuInflater inflater = getSupportMenuInflater();
417b21b8e58a604f6c701245d84b141b5b87663192bOwen Lin
418f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        if (mGetContent) {
419b21b8e58a604f6c701245d84b141b5b87663192bOwen Lin            inflater.inflate(R.menu.pickup, menu);
420f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            int typeBits = mData.getInt(
421f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                    Gallery.KEY_TYPE_BITS, DataManager.INCLUDE_IMAGE);
4229a93949a6ab6348b1a600496a7d52267620aab95Ahbong Chang            mActionBar.setTitle(GalleryUtils.getSelectionModePrompt(typeBits));
423f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        } else  if (mGetAlbum) {
424b21b8e58a604f6c701245d84b141b5b87663192bOwen Lin            inflater.inflate(R.menu.pickup, menu);
4258cab3e872dd95e55ba34fdb94269a0c5069e72aeRay Chen            mActionBar.setTitle(R.string.select_album);
426f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        } else {
427b21b8e58a604f6c701245d84b141b5b87663192bOwen Lin            inflater.inflate(R.menu.albumset, menu);
428b5f8d908c5dd287052cd49eddaf1f82d858cca03Ray Chen            mShowClusterMenu = !inAlbum;
4292bb717f1ea38e2ce33dd102a23afe6bfacb5675cOwen Lin            boolean selectAlbums = !inAlbum &&
4302bb717f1ea38e2ce33dd102a23afe6bfacb5675cOwen Lin                    mActionBar.getClusterTypeAction() == FilterUtils.CLUSTER_BY_ALBUM;
431b21b8e58a604f6c701245d84b141b5b87663192bOwen Lin            MenuItem selectItem = menu.findItem(R.id.action_select);
432b21b8e58a604f6c701245d84b141b5b87663192bOwen Lin            selectItem.setTitle(activity.getString(
4332bb717f1ea38e2ce33dd102a23afe6bfacb5675cOwen Lin                    selectAlbums ? R.string.select_album : R.string.select_group));
434f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
435b21b8e58a604f6c701245d84b141b5b87663192bOwen Lin            MenuItem cameraItem = menu.findItem(R.id.action_camera);
436b21b8e58a604f6c701245d84b141b5b87663192bOwen Lin            cameraItem.setVisible(GalleryUtils.isCameraAvailable(activity));
437f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
438b21b8e58a604f6c701245d84b141b5b87663192bOwen Lin            FilterUtils.setupMenuItems(mActionBar, mMediaSet.getPath(), false);
4392bb717f1ea38e2ce33dd102a23afe6bfacb5675cOwen Lin
4402bb717f1ea38e2ce33dd102a23afe6bfacb5675cOwen Lin            Intent helpIntent = HelpUtils.getHelpIntent(activity, R.string.help_url_gallery_main);
441b21b8e58a604f6c701245d84b141b5b87663192bOwen Lin
442b21b8e58a604f6c701245d84b141b5b87663192bOwen Lin            MenuItem helpItem = menu.findItem(R.id.action_general_help);
443b21b8e58a604f6c701245d84b141b5b87663192bOwen Lin            helpItem.setVisible(helpIntent != null);
444b21b8e58a604f6c701245d84b141b5b87663192bOwen Lin            if (helpIntent != null) helpItem.setIntent(helpIntent);
445b21b8e58a604f6c701245d84b141b5b87663192bOwen Lin
4468cab3e872dd95e55ba34fdb94269a0c5069e72aeRay Chen            mActionBar.setTitle(mTitle);
4478cab3e872dd95e55ba34fdb94269a0c5069e72aeRay Chen            mActionBar.setSubtitle(mSubtitle);
448f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
449b21b8e58a604f6c701245d84b141b5b87663192bOwen Lin        return true;
450f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
451f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
452f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    @Override
453f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    protected boolean onItemSelected(MenuItem item) {
454b21b8e58a604f6c701245d84b141b5b87663192bOwen Lin        Activity activity = mActivity;
455f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        switch (item.getItemId()) {
456bd8e025f1bb39b2be236b183ea8e78f93b308ad1Ray Chen            case R.id.action_cancel:
457bd8e025f1bb39b2be236b183ea8e78f93b308ad1Ray Chen                activity.setResult(Activity.RESULT_CANCELED);
458bd8e025f1bb39b2be236b183ea8e78f93b308ad1Ray Chen                activity.finish();
459bd8e025f1bb39b2be236b183ea8e78f93b308ad1Ray Chen                return true;
460f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            case R.id.action_select:
461f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                mSelectionManager.setAutoLeaveSelectionMode(false);
462f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                mSelectionManager.enterSelectionMode();
463f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                return true;
464f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            case R.id.action_details:
465f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                if (mAlbumSetDataAdapter.size() != 0) {
466f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                    if (mShowDetails) {
467f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                        hideDetails();
468f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                    } else {
469f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                        showDetails();
470f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                    }
471f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                } else {
472f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                    Toast.makeText(activity,
473f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                            activity.getText(R.string.no_albums_alert),
474f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                            Toast.LENGTH_SHORT).show();
475f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                }
476f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                return true;
477f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            case R.id.action_camera: {
478402237b43fd853377e5dba4e048839ad23b99d72Chih-Chung Chang                GalleryUtils.startCameraActivity(activity);
479f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                return true;
480f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
481f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            case R.id.action_manage_offline: {
4826cf807453fb58ccd4cc513ff187b306c7090e67cOwen Lin                Bundle data = new Bundle();
4836cf807453fb58ccd4cc513ff187b306c7090e67cOwen Lin                String mediaPath = mActivity.getDataManager().getTopSetPath(
4846cf807453fb58ccd4cc513ff187b306c7090e67cOwen Lin                    DataManager.INCLUDE_ALL);
4856cf807453fb58ccd4cc513ff187b306c7090e67cOwen Lin                data.putString(AlbumSetPage.KEY_MEDIA_PATH, mediaPath);
4866cf807453fb58ccd4cc513ff187b306c7090e67cOwen Lin                mActivity.getStateManager().startState(ManageCachePage.class, data);
487f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                return true;
488f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
489f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            case R.id.action_sync_picasa_albums: {
490f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                PicasaSource.requestSync(activity);
491f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                return true;
492f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
493f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            case R.id.action_settings: {
494f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                activity.startActivity(new Intent(activity, GallerySettings.class));
495f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                return true;
496f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
497f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            default:
498f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                return false;
499f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
500f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
501f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
502f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    @Override
503f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    protected void onStateResult(int requestCode, int resultCode, Intent data) {
504f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        switch (requestCode) {
505f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            case REQUEST_DO_ANIMATION: {
5062341c197b0becf99422e8ad305def77df6161714Owen Lin                mSlotView.startRisingAnimation();
507f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
508f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
509f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
510f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
511f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private String getSelectedString() {
512f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        int count = mSelectionManager.getSelectedCount();
5138cab3e872dd95e55ba34fdb94269a0c5069e72aeRay Chen        int action = mActionBar.getClusterTypeAction();
514f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        int string = action == FilterUtils.CLUSTER_BY_ALBUM
515f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                ? R.plurals.number_of_albums_selected
516f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                : R.plurals.number_of_groups_selected;
517f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        String format = mActivity.getResources().getQuantityString(string, count);
518f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        return String.format(format, count);
519f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
520f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
5212341c197b0becf99422e8ad305def77df6161714Owen Lin    @Override
522f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public void onSelectionModeChange(int mode) {
523f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        switch (mode) {
524f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            case SelectionManager.ENTER_SELECTION_MODE: {
5258cab3e872dd95e55ba34fdb94269a0c5069e72aeRay Chen                mActionBar.disableClusterMenu(true);
5262bb717f1ea38e2ce33dd102a23afe6bfacb5675cOwen Lin                mActionModeHandler.startActionMode();
5272bb717f1ea38e2ce33dd102a23afe6bfacb5675cOwen Lin                if (mHapticsEnabled) mVibrator.vibrate(100);
528f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                break;
529f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
530f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            case SelectionManager.LEAVE_SELECTION_MODE: {
5312bb717f1ea38e2ce33dd102a23afe6bfacb5675cOwen Lin                mActionModeHandler.finishActionMode();
5329c21268fa8d394cca6cab78dd023a52e0b147a6eRay Chen                if (mShowClusterMenu) {
5338cab3e872dd95e55ba34fdb94269a0c5069e72aeRay Chen                    mActionBar.enableClusterMenu(mSelectedAction, this);
5349c21268fa8d394cca6cab78dd023a52e0b147a6eRay Chen                }
535f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                mRootPane.invalidate();
536f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                break;
537f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
538f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            case SelectionManager.SELECT_ALL_MODE: {
53921c2e665fdc1d1af0c91ab9c104d13fb7dc2444eRay Chen                mActionModeHandler.updateSupportedOperation();
540f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                mRootPane.invalidate();
541f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                break;
542f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
543f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
544f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
545f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
5462341c197b0becf99422e8ad305def77df6161714Owen Lin    @Override
547f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    public void onSelectionChange(Path path, boolean selected) {
548f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mActionModeHandler.setTitle(getSelectedString());
549f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mActionModeHandler.updateSupportedOperation(path, selected);
550f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
551f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
552f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private void hideDetails() {
553f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mShowDetails = false;
5544105e22d72d7a44e67cba4a58ad88018ed664d10Ray Chen        mDetailsHelper.hide();
55531cac30e46a293f6d0901e22c6ab0d083cae7021Owen Lin        mAlbumSetView.setHighlightItemPath(null);
5567260f6f74d465520e4497b23fe56f98abb0c15a2Owen Lin        mSlotView.invalidate();
557f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
558f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
559f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private void showDetails() {
560f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        mShowDetails = true;
5614105e22d72d7a44e67cba4a58ad88018ed664d10Ray Chen        if (mDetailsHelper == null) {
5624105e22d72d7a44e67cba4a58ad88018ed664d10Ray Chen            mDetailsHelper = new DetailsHelper(mActivity, mRootPane, mDetailsSource);
5634105e22d72d7a44e67cba4a58ad88018ed664d10Ray Chen            mDetailsHelper.setCloseListener(new CloseListener() {
5642341c197b0becf99422e8ad305def77df6161714Owen Lin                @Override
565f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                public void onClose() {
566f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                    hideDetails();
567f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                }
568f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            });
569f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
5704105e22d72d7a44e67cba4a58ad88018ed664d10Ray Chen        mDetailsHelper.show();
571f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
572f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
57357cbaa1ef40d2215c6400f5ae4af3a09e67abb2dHung-ying Tyan    @Override
57457cbaa1ef40d2215c6400f5ae4af3a09e67abb2dHung-ying Tyan    public void onSyncDone(final MediaSet mediaSet, final int resultCode) {
57557cbaa1ef40d2215c6400f5ae4af3a09e67abb2dHung-ying Tyan        if (resultCode == MediaSet.SYNC_RESULT_ERROR) {
57657cbaa1ef40d2215c6400f5ae4af3a09e67abb2dHung-ying Tyan            Log.d(TAG, "onSyncDone: " + Utils.maskDebugInfo(mediaSet.getName()) + " result="
57757cbaa1ef40d2215c6400f5ae4af3a09e67abb2dHung-ying Tyan                    + resultCode);
57857cbaa1ef40d2215c6400f5ae4af3a09e67abb2dHung-ying Tyan        }
57957cbaa1ef40d2215c6400f5ae4af3a09e67abb2dHung-ying Tyan        ((Activity) mActivity).runOnUiThread(new Runnable() {
58057cbaa1ef40d2215c6400f5ae4af3a09e67abb2dHung-ying Tyan            @Override
58157cbaa1ef40d2215c6400f5ae4af3a09e67abb2dHung-ying Tyan            public void run() {
58271632ac6c1596dd1fd477f95e268f96ad72ea572Owen Lin                GLRoot root = mActivity.getGLRoot();
58371632ac6c1596dd1fd477f95e268f96ad72ea572Owen Lin                root.lockRenderThread();
58471632ac6c1596dd1fd477f95e268f96ad72ea572Owen Lin                try {
58571632ac6c1596dd1fd477f95e268f96ad72ea572Owen Lin                    if (resultCode == MediaSet.SYNC_RESULT_SUCCESS) {
58671632ac6c1596dd1fd477f95e268f96ad72ea572Owen Lin                        mInitialSynced = true;
58771632ac6c1596dd1fd477f95e268f96ad72ea572Owen Lin                    }
58871632ac6c1596dd1fd477f95e268f96ad72ea572Owen Lin                    clearLoadingBit(BIT_LOADING_SYNC);
58971632ac6c1596dd1fd477f95e268f96ad72ea572Owen Lin                    if (resultCode == MediaSet.SYNC_RESULT_ERROR && mIsActive) {
590e8c1e69f85efb8673d0606f3aca729a366038753Ray Chen                        Log.w(TAG, "failed to load album set");
59171632ac6c1596dd1fd477f95e268f96ad72ea572Owen Lin                    }
59271632ac6c1596dd1fd477f95e268f96ad72ea572Owen Lin                } finally {
59371632ac6c1596dd1fd477f95e268f96ad72ea572Owen Lin                    root.unlockRenderThread();
59457cbaa1ef40d2215c6400f5ae4af3a09e67abb2dHung-ying Tyan                }
59557cbaa1ef40d2215c6400f5ae4af3a09e67abb2dHung-ying Tyan            }
59657cbaa1ef40d2215c6400f5ae4af3a09e67abb2dHung-ying Tyan        });
59757cbaa1ef40d2215c6400f5ae4af3a09e67abb2dHung-ying Tyan    }
59857cbaa1ef40d2215c6400f5ae4af3a09e67abb2dHung-ying Tyan
599f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    private class MyLoadingListener implements LoadingListener {
6002341c197b0becf99422e8ad305def77df6161714Owen Lin        @Override
601f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        public void onLoadingStarted() {
602fbdd338d83596ba545a8a7c8105d2ad7b5df56e6Owen Lin            setLoadingBit(BIT_LOADING_RELOAD);
603f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
604f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
6052341c197b0becf99422e8ad305def77df6161714Owen Lin        @Override
606f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        public void onLoadingFinished() {
607fbdd338d83596ba545a8a7c8105d2ad7b5df56e6Owen Lin            clearLoadingBit(BIT_LOADING_RELOAD);
608f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
609f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
610f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
6114105e22d72d7a44e67cba4a58ad88018ed664d10Ray Chen    private class MyDetailsSource implements DetailsHelper.DetailsSource {
612f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        private int mIndex;
6132341c197b0becf99422e8ad305def77df6161714Owen Lin
6142341c197b0becf99422e8ad305def77df6161714Owen Lin        @Override
615f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        public int size() {
616f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            return mAlbumSetDataAdapter.size();
617f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
618f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
6192341c197b0becf99422e8ad305def77df6161714Owen Lin        @Override
620995c4566bed7df1aa48ba7e1351f964efa73880bMichael Kolb        public int setIndex() {
621995c4566bed7df1aa48ba7e1351f964efa73880bMichael Kolb            Path id = mSelectionManager.getSelected(false).get(0);
622995c4566bed7df1aa48ba7e1351f964efa73880bMichael Kolb            mIndex = mAlbumSetDataAdapter.findSet(id);
623f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            return mIndex;
624f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
625f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin
6262341c197b0becf99422e8ad305def77df6161714Owen Lin        @Override
627f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        public MediaDetails getDetails() {
628f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            MediaObject item = mAlbumSetDataAdapter.getMediaSet(mIndex);
629f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            if (item != null) {
63031cac30e46a293f6d0901e22c6ab0d083cae7021Owen Lin                mAlbumSetView.setHighlightItemPath(item.getPath());
631f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                return item.getDetails();
632f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            } else {
633f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin                return null;
634f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin            }
635f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin        }
636f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin    }
637f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin}
638