OSDN Git Service

Merge "Fix 5250813 Use new standardized no account screen on first launch"
[android-x86/packages-apps-Camera2.git] / src / com / android / gallery3d / app / AlbumSetPage.java
1 /*
2  * Copyright (C) 2010 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package com.android.gallery3d.app;
18
19 import android.app.Activity;
20 import android.content.Context;
21 import android.content.Intent;
22 import android.graphics.Rect;
23 import android.os.Bundle;
24 import android.os.Vibrator;
25 import android.provider.MediaStore;
26 import android.view.ActionMode;
27 import android.view.Menu;
28 import android.view.MenuInflater;
29 import android.view.MenuItem;
30 import android.widget.Toast;
31
32 import com.android.gallery3d.R;
33 import com.android.gallery3d.common.Utils;
34 import com.android.gallery3d.data.DataManager;
35 import com.android.gallery3d.data.MediaDetails;
36 import com.android.gallery3d.data.MediaObject;
37 import com.android.gallery3d.data.MediaSet;
38 import com.android.gallery3d.data.Path;
39 import com.android.gallery3d.picasasource.PicasaSource;
40 import com.android.gallery3d.settings.GallerySettings;
41 import com.android.gallery3d.ui.ActionModeHandler;
42 import com.android.gallery3d.ui.ActionModeHandler.ActionModeListener;
43 import com.android.gallery3d.ui.AlbumSetView;
44 import com.android.gallery3d.ui.DetailsHelper;
45 import com.android.gallery3d.ui.DetailsHelper.CloseListener;
46 import com.android.gallery3d.util.GalleryUtils;
47 import com.android.gallery3d.ui.GLCanvas;
48 import com.android.gallery3d.ui.GLView;
49 import com.android.gallery3d.ui.GridDrawer;
50 import com.android.gallery3d.ui.HighlightDrawer;
51 import com.android.gallery3d.ui.PositionProvider;
52 import com.android.gallery3d.ui.PositionRepository;
53 import com.android.gallery3d.ui.PositionRepository.Position;
54 import com.android.gallery3d.ui.SelectionManager;
55 import com.android.gallery3d.ui.SlotView;
56 import com.android.gallery3d.ui.StaticBackground;
57
58 public class AlbumSetPage extends ActivityState implements
59         SelectionManager.SelectionListener, GalleryActionBar.ClusterRunner,
60         EyePosition.EyePositionListener {
61     @SuppressWarnings("unused")
62     private static final String TAG = "AlbumSetPage";
63
64     public static final String KEY_MEDIA_PATH = "media-path";
65     public static final String KEY_SET_TITLE = "set-title";
66     public static final String KEY_SET_SUBTITLE = "set-subtitle";
67     public static final String KEY_SELECTED_CLUSTER_TYPE = "selected-cluster";
68
69     private static final int DATA_CACHE_SIZE = 256;
70     private static final int REQUEST_DO_ANIMATION = 1;
71     private static final int MSG_GOTO_MANAGE_CACHE_PAGE = 1;
72
73     private boolean mIsActive = false;
74     private StaticBackground mStaticBackground;
75     private AlbumSetView mAlbumSetView;
76
77     private MediaSet mMediaSet;
78     private String mSubtitle;
79     private boolean mShowClusterMenu;
80     private int mSelectedAction;
81     private Vibrator mVibrator;
82
83     protected SelectionManager mSelectionManager;
84     private AlbumSetDataAdapter mAlbumSetDataAdapter;
85     private GridDrawer mGridDrawer;
86     private HighlightDrawer mHighlightDrawer;
87
88     private boolean mGetContent;
89     private boolean mGetAlbum;
90     private ActionMode mActionMode;
91     private ActionModeHandler mActionModeHandler;
92     private DetailsHelper mDetailsHelper;
93     private MyDetailsSource mDetailsSource;
94     private boolean mShowDetails;
95     private EyePosition mEyePosition;
96
97     // The eyes' position of the user, the origin is at the center of the
98     // device and the unit is in pixels.
99     private float mX;
100     private float mY;
101     private float mZ;
102
103     private final GLView mRootPane = new GLView() {
104         private final float mMatrix[] = new float[16];
105
106         @Override
107         protected void onLayout(
108                 boolean changed, int left, int top, int right, int bottom) {
109             mStaticBackground.layout(0, 0, right - left, bottom - top);
110             mEyePosition.resetPosition();
111
112             int slotViewTop = GalleryActionBar.getHeight((Activity) mActivity);
113             int slotViewBottom = bottom - top;
114             int slotViewRight = right - left;
115
116             if (mShowDetails) {
117                 mDetailsHelper.layout(left, slotViewTop, right, bottom);
118             } else {
119                 mAlbumSetView.setSelectionDrawer(mGridDrawer);
120             }
121
122             mAlbumSetView.layout(0, slotViewTop, slotViewRight, slotViewBottom);
123             PositionRepository.getInstance(mActivity).setOffset(
124                     0, slotViewTop);
125         }
126
127         @Override
128         protected void render(GLCanvas canvas) {
129             canvas.save(GLCanvas.SAVE_FLAG_MATRIX);
130             GalleryUtils.setViewPointMatrix(mMatrix,
131                     getWidth() / 2 + mX, getHeight() / 2 + mY, mZ);
132             canvas.multiplyMatrix(mMatrix, 0);
133             super.render(canvas);
134             canvas.restore();
135         }
136     };
137
138     @Override
139     public void onEyePositionChanged(float x, float y, float z) {
140         mRootPane.lockRendering();
141         mX = x;
142         mY = y;
143         mZ = z;
144         mRootPane.unlockRendering();
145         mRootPane.invalidate();
146     }
147
148     @Override
149     public void onBackPressed() {
150         if (mShowDetails) {
151             hideDetails();
152         } else if (mSelectionManager.inSelectionMode()) {
153             mSelectionManager.leaveSelectionMode();
154         } else {
155             mAlbumSetView.savePositions(
156                     PositionRepository.getInstance(mActivity));
157             super.onBackPressed();
158         }
159     }
160
161     private void savePositions(int slotIndex, int center[]) {
162         Rect offset = new Rect();
163         mRootPane.getBoundsOf(mAlbumSetView, offset);
164         mAlbumSetView.savePositions(PositionRepository.getInstance(mActivity));
165         Rect r = mAlbumSetView.getSlotRect(slotIndex);
166         int scrollX = mAlbumSetView.getScrollX();
167         int scrollY = mAlbumSetView.getScrollY();
168         center[0] = offset.left + (r.left + r.right) / 2 - scrollX;
169         center[1] = offset.top + (r.top + r.bottom) / 2 - scrollY;
170     }
171
172     public void onSingleTapUp(int slotIndex) {
173         MediaSet targetSet = mAlbumSetDataAdapter.getMediaSet(slotIndex);
174         if (targetSet == null) return; // Content is dirty, we shall reload soon
175
176         if (mShowDetails) {
177             Path path = targetSet.getPath();
178             mHighlightDrawer.setHighlightItem(path);
179             mDetailsHelper.reloadDetails(slotIndex);
180         } else if (!mSelectionManager.inSelectionMode()) {
181             Bundle data = new Bundle(getData());
182             String mediaPath = targetSet.getPath().toString();
183             int[] center = new int[2];
184             savePositions(slotIndex, center);
185             data.putIntArray(AlbumPage.KEY_SET_CENTER, center);
186             if (mGetAlbum && targetSet.isLeafAlbum()) {
187                 Activity activity = (Activity) mActivity;
188                 Intent result = new Intent()
189                         .putExtra(AlbumPicker.KEY_ALBUM_PATH, targetSet.getPath().toString());
190                 activity.setResult(Activity.RESULT_OK, result);
191                 activity.finish();
192             } else if (targetSet.getSubMediaSetCount() > 0) {
193                 data.putString(AlbumSetPage.KEY_MEDIA_PATH, mediaPath);
194                 mActivity.getStateManager().startStateForResult(
195                         AlbumSetPage.class, REQUEST_DO_ANIMATION, data);
196             } else {
197                 if (!mGetContent && (targetSet.getSupportedOperations()
198                         & MediaObject.SUPPORT_IMPORT) != 0) {
199                     data.putBoolean(AlbumPage.KEY_AUTO_SELECT_ALL, true);
200                 }
201                 data.putString(AlbumPage.KEY_MEDIA_PATH, mediaPath);
202                 boolean inAlbum = mActivity.getStateManager().hasStateClass(AlbumPage.class);
203                 // We only show cluster menu in the first AlbumPage in stack
204                 data.putBoolean(AlbumPage.KEY_SHOW_CLUSTER_MENU, !inAlbum);
205                 mActivity.getStateManager().startStateForResult(
206                         AlbumPage.class, REQUEST_DO_ANIMATION, data);
207             }
208         } else {
209             mSelectionManager.toggle(targetSet.getPath());
210             mAlbumSetView.invalidate();
211         }
212     }
213
214     private void onDown(int index) {
215         MediaSet set = mAlbumSetDataAdapter.getMediaSet(index);
216         Path path = (set == null) ? null : set.getPath();
217         mSelectionManager.setPressedPath(path);
218         mAlbumSetView.invalidate();
219     }
220
221     private void onUp() {
222         mSelectionManager.setPressedPath(null);
223         mAlbumSetView.invalidate();
224     }
225
226     public void onLongTap(int slotIndex) {
227         if (mGetContent || mGetAlbum) return;
228         if (mShowDetails) {
229             onSingleTapUp(slotIndex);
230         } else {
231             MediaSet set = mAlbumSetDataAdapter.getMediaSet(slotIndex);
232             if (set == null) return;
233             mSelectionManager.setAutoLeaveSelectionMode(true);
234             mSelectionManager.toggle(set.getPath());
235             mDetailsSource.findIndex(slotIndex);
236             mAlbumSetView.invalidate();
237         }
238     }
239
240     public void doCluster(int clusterType) {
241         String basePath = mMediaSet.getPath().toString();
242         String newPath = FilterUtils.switchClusterPath(basePath, clusterType);
243         Bundle data = new Bundle(getData());
244         data.putString(AlbumSetPage.KEY_MEDIA_PATH, newPath);
245         data.putInt(KEY_SELECTED_CLUSTER_TYPE, clusterType);
246         mAlbumSetView.savePositions(PositionRepository.getInstance(mActivity));
247         mActivity.getStateManager().switchState(this, AlbumSetPage.class, data);
248     }
249
250     public void doFilter(int filterType) {
251         String basePath = mMediaSet.getPath().toString();
252         String newPath = FilterUtils.switchFilterPath(basePath, filterType);
253         Bundle data = new Bundle(getData());
254         data.putString(AlbumSetPage.KEY_MEDIA_PATH, newPath);
255         mAlbumSetView.savePositions(PositionRepository.getInstance(mActivity));
256         mActivity.getStateManager().switchState(this, AlbumSetPage.class, data);
257     }
258
259     public void onOperationComplete() {
260         mAlbumSetView.invalidate();
261         // TODO: enable animation
262     }
263
264     @Override
265     public void onCreate(Bundle data, Bundle restoreState) {
266         initializeViews();
267         initializeData(data);
268         Context context = mActivity.getAndroidContext();
269         mGetContent = data.getBoolean(Gallery.KEY_GET_CONTENT, false);
270         mGetAlbum = data.getBoolean(Gallery.KEY_GET_ALBUM, false);
271         mSubtitle = data.getString(AlbumSetPage.KEY_SET_SUBTITLE);
272         mEyePosition = new EyePosition(context, this);
273         mDetailsSource = new MyDetailsSource();
274         mVibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
275         GalleryActionBar actionBar = mActivity.getGalleryActionBar();
276         if (actionBar != null) {
277             mSelectedAction = data.getInt(
278                     AlbumSetPage.KEY_SELECTED_CLUSTER_TYPE, FilterUtils.CLUSTER_BY_ALBUM);
279         }
280         startTransition();
281     }
282
283     @Override
284     public void onPause() {
285         super.onPause();
286         mIsActive = false;
287         mActionModeHandler.pause();
288         mAlbumSetDataAdapter.pause();
289         mAlbumSetView.pause();
290         mEyePosition.pause();
291         DetailsHelper.pause();
292         GalleryActionBar actionBar = mActivity.getGalleryActionBar();
293         if (actionBar != null) actionBar.hideClusterMenu();
294     }
295
296     @Override
297     public void onResume() {
298         super.onResume();
299         mIsActive = true;
300         setContentPane(mRootPane);
301         mAlbumSetDataAdapter.resume();
302         mAlbumSetView.resume();
303         mEyePosition.resume();
304         mActionModeHandler.resume();
305         GalleryActionBar actionBar = mActivity.getGalleryActionBar();
306         if (mShowClusterMenu && actionBar != null) {
307             actionBar.showClusterMenu(mSelectedAction, this);
308         }
309     }
310
311     private void initializeData(Bundle data) {
312         String mediaPath = data.getString(AlbumSetPage.KEY_MEDIA_PATH);
313         mMediaSet = mActivity.getDataManager().getMediaSet(mediaPath);
314         mSelectionManager.setSourceMediaSet(mMediaSet);
315         mAlbumSetDataAdapter = new AlbumSetDataAdapter(
316                 mActivity, mMediaSet, DATA_CACHE_SIZE);
317         mAlbumSetDataAdapter.setLoadingListener(new MyLoadingListener());
318         mAlbumSetView.setModel(mAlbumSetDataAdapter);
319     }
320
321     private void initializeViews() {
322         mSelectionManager = new SelectionManager(mActivity, true);
323         mSelectionManager.setSelectionListener(this);
324         mStaticBackground = new StaticBackground(mActivity.getAndroidContext());
325         mRootPane.addComponent(mStaticBackground);
326
327         mGridDrawer = new GridDrawer((Context) mActivity, mSelectionManager);
328         Config.AlbumSetPage config = Config.AlbumSetPage.get((Context) mActivity);
329         mAlbumSetView = new AlbumSetView(mActivity, mGridDrawer,
330                 config.slotViewSpec, config.labelSpec);
331         mAlbumSetView.setListener(new SlotView.SimpleListener() {
332             @Override
333             public void onDown(int index) {
334                 AlbumSetPage.this.onDown(index);
335             }
336
337             @Override
338             public void onUp() {
339                 AlbumSetPage.this.onUp();
340             }
341
342             @Override
343             public void onSingleTapUp(int slotIndex) {
344                 AlbumSetPage.this.onSingleTapUp(slotIndex);
345             }
346
347             @Override
348             public void onLongTap(int slotIndex) {
349                 AlbumSetPage.this.onLongTap(slotIndex);
350             }
351         });
352
353         mActionModeHandler = new ActionModeHandler(mActivity, mSelectionManager);
354         mActionModeHandler.setActionModeListener(new ActionModeListener() {
355             public boolean onActionItemClicked(MenuItem item) {
356                 return onItemSelected(item);
357             }
358         });
359         mRootPane.addComponent(mAlbumSetView);
360
361         mStaticBackground.setImage(R.drawable.background,
362                 R.drawable.background_portrait);
363     }
364
365     @Override
366     protected boolean onCreateActionBar(Menu menu) {
367         Activity activity = (Activity) mActivity;
368         GalleryActionBar actionBar = mActivity.getGalleryActionBar();
369         MenuInflater inflater = activity.getMenuInflater();
370
371         final boolean inAlbum = mActivity.getStateManager().hasStateClass(
372                 AlbumPage.class);
373
374         if (mGetContent) {
375             inflater.inflate(R.menu.pickup, menu);
376             int typeBits = mData.getInt(
377                     Gallery.KEY_TYPE_BITS, DataManager.INCLUDE_IMAGE);
378             int id = R.string.select_image;
379             if ((typeBits & DataManager.INCLUDE_VIDEO) != 0) {
380                 id = (typeBits & DataManager.INCLUDE_IMAGE) == 0
381                         ? R.string.select_video
382                         : R.string.select_item;
383             }
384             actionBar.setTitle(id);
385         } else  if (mGetAlbum) {
386             inflater.inflate(R.menu.pickup, menu);
387             actionBar.setTitle(R.string.select_album);
388         } else {
389             mShowClusterMenu = !inAlbum;
390             inflater.inflate(R.menu.albumset, menu);
391             actionBar.setTitle(null);
392             MenuItem selectItem = menu.findItem(R.id.action_select);
393
394             if (selectItem != null) {
395                 boolean selectAlbums = !inAlbum &&
396                         actionBar.getClusterTypeAction() == FilterUtils.CLUSTER_BY_ALBUM;
397                 if (selectAlbums) {
398                     selectItem.setTitle(R.string.select_album);
399                 } else {
400                     selectItem.setTitle(R.string.select_group);
401                 }
402             }
403
404             MenuItem switchCamera = menu.findItem(R.id.action_camera);
405             if (switchCamera != null) {
406                 switchCamera.setVisible(GalleryUtils.isCameraAvailable(activity));
407             }
408
409             actionBar.setSubtitle(mSubtitle);
410         }
411         return true;
412     }
413
414     @Override
415     protected boolean onItemSelected(MenuItem item) {
416         Activity activity = (Activity) mActivity;
417         switch (item.getItemId()) {
418             case R.id.action_cancel:
419                 activity.setResult(Activity.RESULT_CANCELED);
420                 activity.finish();
421                 return true;
422             case R.id.action_select:
423                 mSelectionManager.setAutoLeaveSelectionMode(false);
424                 mSelectionManager.enterSelectionMode();
425                 return true;
426             case R.id.action_details:
427                 if (mAlbumSetDataAdapter.size() != 0) {
428                     if (mShowDetails) {
429                         hideDetails();
430                     } else {
431                         showDetails();
432                     }
433                 } else {
434                     Toast.makeText(activity,
435                             activity.getText(R.string.no_albums_alert),
436                             Toast.LENGTH_SHORT).show();
437                 }
438                 return true;
439             case R.id.action_camera: {
440                 Intent intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA)
441                         .setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
442                         | Intent.FLAG_ACTIVITY_NEW_TASK);
443                 activity.startActivity(intent);
444                 return true;
445             }
446             case R.id.action_manage_offline: {
447                 Bundle data = new Bundle();
448                 String mediaPath = mActivity.getDataManager().getTopSetPath(
449                     DataManager.INCLUDE_ALL);
450                 data.putString(AlbumSetPage.KEY_MEDIA_PATH, mediaPath);
451                 mActivity.getStateManager().startState(ManageCachePage.class, data);
452                 return true;
453             }
454             case R.id.action_sync_picasa_albums: {
455                 PicasaSource.requestSync(activity);
456                 return true;
457             }
458             case R.id.action_settings: {
459                 activity.startActivity(new Intent(activity, GallerySettings.class));
460                 return true;
461             }
462             default:
463                 return false;
464         }
465     }
466
467     @Override
468     protected void onStateResult(int requestCode, int resultCode, Intent data) {
469         switch (requestCode) {
470             case REQUEST_DO_ANIMATION: {
471                 startTransition();
472             }
473         }
474     }
475
476     private void startTransition() {
477         final PositionRepository repository =
478                 PositionRepository.getInstance(mActivity);
479         mAlbumSetView.startTransition(new PositionProvider() {
480             private final Position mTempPosition = new Position();
481             public Position getPosition(long identity, Position target) {
482                 Position p = repository.get(identity);
483                 if (p == null) {
484                     p = mTempPosition;
485                     p.set(target.x, target.y, 128, target.theta, 1);
486                 }
487                 return p;
488             }
489         });
490     }
491
492     private String getSelectedString() {
493         GalleryActionBar actionBar = mActivity.getGalleryActionBar();
494         int count = mSelectionManager.getSelectedCount();
495         int action = actionBar.getClusterTypeAction();
496         int string = action == FilterUtils.CLUSTER_BY_ALBUM
497                 ? R.plurals.number_of_albums_selected
498                 : R.plurals.number_of_groups_selected;
499         String format = mActivity.getResources().getQuantityString(string, count);
500         return String.format(format, count);
501     }
502
503     public void onSelectionModeChange(int mode) {
504
505         switch (mode) {
506             case SelectionManager.ENTER_SELECTION_MODE: {
507                 mActivity.getGalleryActionBar().hideClusterMenu();
508                 mActionMode = mActionModeHandler.startActionMode();
509                 mVibrator.vibrate(100);
510                 break;
511             }
512             case SelectionManager.LEAVE_SELECTION_MODE: {
513                 mActionMode.finish();
514                 mActivity.getGalleryActionBar().showClusterMenu(mSelectedAction, this);
515                 mRootPane.invalidate();
516                 break;
517             }
518             case SelectionManager.SELECT_ALL_MODE: {
519                 mActionModeHandler.setTitle(getSelectedString());
520                 mRootPane.invalidate();
521                 break;
522             }
523         }
524     }
525
526     public void onSelectionChange(Path path, boolean selected) {
527         Utils.assertTrue(mActionMode != null);
528         mActionModeHandler.setTitle(getSelectedString());
529         mActionModeHandler.updateSupportedOperation(path, selected);
530     }
531
532     private void hideDetails() {
533         mShowDetails = false;
534         mDetailsHelper.hide();
535         mAlbumSetView.setSelectionDrawer(mGridDrawer);
536         mAlbumSetView.invalidate();
537     }
538
539     private void showDetails() {
540         mShowDetails = true;
541         if (mDetailsHelper == null) {
542             mHighlightDrawer = new HighlightDrawer(mActivity.getAndroidContext(),
543                     mSelectionManager);
544             mDetailsHelper = new DetailsHelper(mActivity, mRootPane, mDetailsSource);
545             mDetailsHelper.setCloseListener(new CloseListener() {
546                 public void onClose() {
547                     hideDetails();
548                 }
549             });
550         }
551         mAlbumSetView.setSelectionDrawer(mHighlightDrawer);
552         mDetailsHelper.show();
553     }
554
555     private class MyLoadingListener implements LoadingListener {
556         public void onLoadingStarted() {
557             GalleryUtils.setSpinnerVisibility((Activity) mActivity, true);
558         }
559
560         public void onLoadingFinished() {
561             if (!mIsActive) return;
562             GalleryUtils.setSpinnerVisibility((Activity) mActivity, false);
563             if (mAlbumSetDataAdapter.size() == 0) {
564                 Toast.makeText((Context) mActivity,
565                         R.string.empty_album, Toast.LENGTH_LONG).show();
566                 if (mActivity.getStateManager().getStateCount() > 1) {
567                     mActivity.getStateManager().finishState(AlbumSetPage.this);
568                 }
569             }
570         }
571     }
572
573     private class MyDetailsSource implements DetailsHelper.DetailsSource {
574         private int mIndex;
575         public int size() {
576             return mAlbumSetDataAdapter.size();
577         }
578
579         public int getIndex() {
580             return mIndex;
581         }
582
583         // If requested index is out of active window, suggest a valid index.
584         // If there is no valid index available, return -1.
585         public int findIndex(int indexHint) {
586             if (mAlbumSetDataAdapter.isActive(indexHint)) {
587                 mIndex = indexHint;
588             } else {
589                 mIndex = mAlbumSetDataAdapter.getActiveStart();
590                 if (!mAlbumSetDataAdapter.isActive(mIndex)) {
591                     return -1;
592                 }
593             }
594             return mIndex;
595         }
596
597         public MediaDetails getDetails() {
598             MediaObject item = mAlbumSetDataAdapter.getMediaSet(mIndex);
599             if (item != null) {
600                 mHighlightDrawer.setHighlightItem(item.getPath());
601                 return item.getDetails();
602             } else {
603                 return null;
604             }
605         }
606     }
607 }