blob: 7daf5df0cc5c0b67da171cafdb5b76b787396cf8 [file] [log] [blame]
Owen Lina2fba682011-08-17 22:07:43 +08001/*
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
17package com.android.gallery3d.app;
18
Ray Chen09efcf92011-10-21 16:07:12 +080019import android.app.ActionBar.OnMenuVisibilityListener;
Owen Linc907c322011-11-17 15:26:56 +080020import android.app.Activity;
Ray Chen09efcf92011-10-21 16:07:12 +080021import android.content.ActivityNotFoundException;
Ray Chenf3f7f562012-03-06 17:24:28 +080022import android.content.ContentResolver;
Ray Chen09efcf92011-10-21 16:07:12 +080023import android.content.Context;
24import android.content.Intent;
Yuli Huang54fe02f2012-03-20 16:37:05 +080025import android.graphics.Rect;
Ray Chen09efcf92011-10-21 16:07:12 +080026import android.net.Uri;
27import android.os.Bundle;
28import android.os.Handler;
29import android.os.Message;
30import android.view.Menu;
31import android.view.MenuInflater;
32import android.view.MenuItem;
33import android.view.View;
Chih-Chung Chang706a7cf2012-03-15 16:38:45 +080034import android.view.ViewGroup;
Ray Chen09efcf92011-10-21 16:07:12 +080035import android.view.View.MeasureSpec;
Owen Linc907c322011-11-17 15:26:56 +080036import android.view.WindowManager;
Ray Chen09efcf92011-10-21 16:07:12 +080037import android.widget.ShareActionProvider;
38import android.widget.Toast;
39
Owen Lina2fba682011-08-17 22:07:43 +080040import com.android.gallery3d.R;
41import com.android.gallery3d.data.DataManager;
42import com.android.gallery3d.data.MediaDetails;
43import com.android.gallery3d.data.MediaItem;
44import com.android.gallery3d.data.MediaObject;
45import com.android.gallery3d.data.MediaSet;
46import com.android.gallery3d.data.MtpDevice;
47import com.android.gallery3d.data.Path;
Chih-Chung Chang706a7cf2012-03-15 16:38:45 +080048import com.android.gallery3d.data.SnailSource;
Owen Lina2fba682011-08-17 22:07:43 +080049import com.android.gallery3d.picasasource.PicasaSource;
Ray Chen327eeb82011-08-24 11:40:04 +080050import com.android.gallery3d.ui.DetailsHelper;
51import com.android.gallery3d.ui.DetailsHelper.CloseListener;
52import com.android.gallery3d.ui.DetailsHelper.DetailsSource;
Owen Lina2fba682011-08-17 22:07:43 +080053import com.android.gallery3d.ui.FilmStripView;
54import com.android.gallery3d.ui.GLCanvas;
55import com.android.gallery3d.ui.GLView;
56import com.android.gallery3d.ui.ImportCompleteListener;
57import com.android.gallery3d.ui.MenuExecutor;
58import com.android.gallery3d.ui.PhotoView;
59import com.android.gallery3d.ui.PositionRepository;
60import com.android.gallery3d.ui.PositionRepository.Position;
61import com.android.gallery3d.ui.SelectionManager;
62import com.android.gallery3d.ui.SynchronizedHandler;
63import com.android.gallery3d.ui.UserInteractionListener;
64import com.android.gallery3d.util.GalleryUtils;
65
Owen Lina2fba682011-08-17 22:07:43 +080066public class PhotoPage extends ActivityState
67 implements PhotoView.PhotoTapListener, FilmStripView.Listener,
68 UserInteractionListener {
69 private static final String TAG = "PhotoPage";
70
71 private static final int MSG_HIDE_BARS = 1;
Owen Lin44aac4b2011-08-28 10:50:21 +080072
Owen Lina2fba682011-08-17 22:07:43 +080073 private static final int HIDE_BARS_TIMEOUT = 3500;
74
75 private static final int REQUEST_SLIDESHOW = 1;
76 private static final int REQUEST_CROP = 2;
77 private static final int REQUEST_CROP_PICASA = 3;
78
79 public static final String KEY_MEDIA_SET_PATH = "media-set-path";
80 public static final String KEY_MEDIA_ITEM_PATH = "media-item-path";
81 public static final String KEY_INDEX_HINT = "index-hint";
Yuli Huang54fe02f2012-03-20 16:37:05 +080082 public static final String KEY_OPEN_ANIMATION_RECT = "open-animation-rect";
Owen Lina2fba682011-08-17 22:07:43 +080083
84 private GalleryApp mApplication;
85 private SelectionManager mSelectionManager;
86
87 private PhotoView mPhotoView;
88 private PhotoPage.Model mModel;
89 private FilmStripView mFilmStripView;
Ray Chen327eeb82011-08-24 11:40:04 +080090 private DetailsHelper mDetailsHelper;
Owen Lina2fba682011-08-17 22:07:43 +080091 private boolean mShowDetails;
Ray Chen41419072011-09-14 16:46:32 +080092 private Path mPendingSharePath;
Owen Lina2fba682011-08-17 22:07:43 +080093
94 // mMediaSet could be null if there is no KEY_MEDIA_SET_PATH supplied.
95 // E.g., viewing a photo in gmail attachment
96 private MediaSet mMediaSet;
97 private Menu mMenu;
98
Ray Chen09efcf92011-10-21 16:07:12 +080099 private final Intent mResultIntent = new Intent();
Owen Lina2fba682011-08-17 22:07:43 +0800100 private int mCurrentIndex = 0;
101 private Handler mHandler;
Owen Linace280a2011-08-30 10:38:59 +0800102 private boolean mShowBars = true;
Ray Chen9af4a902012-03-20 16:32:57 +0800103 private GalleryActionBar mActionBar;
Owen Lina2fba682011-08-17 22:07:43 +0800104 private MyMenuVisibilityListener mMenuVisibilityListener;
105 private boolean mIsMenuVisible;
106 private boolean mIsInteracting;
107 private MediaItem mCurrentPhoto = null;
108 private MenuExecutor mMenuExecutor;
109 private boolean mIsActive;
110 private ShareActionProvider mShareActionProvider;
Ray Chenf3f7f562012-03-06 17:24:28 +0800111 private String mSetPathString;
Owen Lina2fba682011-08-17 22:07:43 +0800112
Chih-Chung Chang706a7cf2012-03-15 16:38:45 +0800113 // This is for testing only. It should be removed once we have the real
114 // Camera view.
115 private CameraView mCameraView;
116 private ScreenNailBridge mScreenNail;
117
Owen Lina2fba682011-08-17 22:07:43 +0800118 public static interface Model extends PhotoView.Model {
119 public void resume();
120 public void pause();
121 public boolean isEmpty();
122 public MediaItem getCurrentMediaItem();
123 public int getCurrentIndex();
124 public void setCurrentPhoto(Path path, int indexHint);
125 }
126
127 private class MyMenuVisibilityListener implements OnMenuVisibilityListener {
128 public void onMenuVisibilityChanged(boolean isVisible) {
129 mIsMenuVisible = isVisible;
130 refreshHidingMessage();
131 }
132 }
133
Ray Chen09efcf92011-10-21 16:07:12 +0800134 private final GLView mRootPane = new GLView() {
Owen Lina2fba682011-08-17 22:07:43 +0800135
136 @Override
137 protected void renderBackground(GLCanvas view) {
138 view.clearBuffer();
139 }
140
141 @Override
142 protected void onLayout(
143 boolean changed, int left, int top, int right, int bottom) {
144 mPhotoView.layout(0, 0, right - left, bottom - top);
Yuli Huang54fe02f2012-03-20 16:37:05 +0800145 // Reset position offset after the layout is changed.
Owen Lina2fba682011-08-17 22:07:43 +0800146 PositionRepository.getInstance(mActivity).setOffset(0, 0);
147 int filmStripHeight = 0;
148 if (mFilmStripView != null) {
149 mFilmStripView.measure(
150 MeasureSpec.makeMeasureSpec(right - left, MeasureSpec.EXACTLY),
151 MeasureSpec.UNSPECIFIED);
152 filmStripHeight = mFilmStripView.getMeasuredHeight();
153 mFilmStripView.layout(0, bottom - top - filmStripHeight,
154 right - left, bottom - top);
155 }
156 if (mShowDetails) {
Ray Chen9af4a902012-03-20 16:32:57 +0800157 mDetailsHelper.layout(left, mActionBar.getHeight(), right, bottom);
Owen Lina2fba682011-08-17 22:07:43 +0800158 }
159 }
160 };
161
Owen Linace280a2011-08-30 10:38:59 +0800162 private void initFilmStripView() {
163 Config.PhotoPage config = Config.PhotoPage.get((Context) mActivity);
164 mFilmStripView = new FilmStripView(mActivity, mMediaSet,
165 config.filmstripTopMargin, config.filmstripMidMargin, config.filmstripBottomMargin,
166 config.filmstripContentSize, config.filmstripThumbSize, config.filmstripBarSize,
167 config.filmstripGripSize, config.filmstripGripWidth);
168 mRootPane.addComponent(mFilmStripView);
169 mFilmStripView.setListener(this);
170 mFilmStripView.setUserInteractionListener(this);
171 mFilmStripView.setFocusIndex(mCurrentIndex);
172 mFilmStripView.setStartIndex(mCurrentIndex);
173 mRootPane.requestLayout();
174 if (mIsActive) mFilmStripView.resume();
175 if (!mShowBars) mFilmStripView.setVisibility(GLView.INVISIBLE);
176 }
177
Owen Lina2fba682011-08-17 22:07:43 +0800178 @Override
179 public void onCreate(Bundle data, Bundle restoreState) {
Ray Chen9af4a902012-03-20 16:32:57 +0800180 mActionBar = mActivity.getGalleryActionBar();
Owen Lina2fba682011-08-17 22:07:43 +0800181 mSelectionManager = new SelectionManager(mActivity, false);
182 mMenuExecutor = new MenuExecutor(mActivity, mSelectionManager);
183
184 mPhotoView = new PhotoView(mActivity);
185 mPhotoView.setPhotoTapListener(this);
186 mRootPane.addComponent(mPhotoView);
187 mApplication = (GalleryApp)((Activity) mActivity).getApplication();
188
Ray Chenf3f7f562012-03-06 17:24:28 +0800189 mSetPathString = data.getString(KEY_MEDIA_SET_PATH);
Owen Lina2fba682011-08-17 22:07:43 +0800190 Path itemPath = Path.fromString(data.getString(KEY_MEDIA_ITEM_PATH));
191
Ray Chenf3f7f562012-03-06 17:24:28 +0800192 if (mSetPathString != null) {
Chih-Chung Chang706a7cf2012-03-15 16:38:45 +0800193 // Uncomment the block below to test camera screennail.
194 /*
195 Path cameraScreenNailSetPath = addCameraScreenNail();
196
197 // Combine the original MediaSet with the one for camera ScreenNail.
198 mSetPathString = "/combo/item/{" + cameraScreenNailSetPath + "," +
199 mSetPathString + "}";
200 */
Ray Chenf3f7f562012-03-06 17:24:28 +0800201 mMediaSet = mActivity.getDataManager().getMediaSet(mSetPathString);
Owen Lina2fba682011-08-17 22:07:43 +0800202 mCurrentIndex = data.getInt(KEY_INDEX_HINT, 0);
203 mMediaSet = (MediaSet)
Ray Chenf3f7f562012-03-06 17:24:28 +0800204 mActivity.getDataManager().getMediaObject(mSetPathString);
Owen Lina2fba682011-08-17 22:07:43 +0800205 if (mMediaSet == null) {
Ray Chenf3f7f562012-03-06 17:24:28 +0800206 Log.w(TAG, "failed to restore " + mSetPathString);
Owen Lina2fba682011-08-17 22:07:43 +0800207 }
208 PhotoDataAdapter pda = new PhotoDataAdapter(
209 mActivity, mPhotoView, mMediaSet, itemPath, mCurrentIndex);
210 mModel = pda;
211 mPhotoView.setModel(mModel);
212
Owen Lina2fba682011-08-17 22:07:43 +0800213 mResultIntent.putExtra(KEY_INDEX_HINT, mCurrentIndex);
214 setStateResult(Activity.RESULT_OK, mResultIntent);
215
216 pda.setDataListener(new PhotoDataAdapter.DataListener() {
217
Owen Linace280a2011-08-30 10:38:59 +0800218 @Override
Owen Lina2fba682011-08-17 22:07:43 +0800219 public void onPhotoChanged(int index, Path item) {
Owen Linace280a2011-08-30 10:38:59 +0800220 if (mFilmStripView != null) mFilmStripView.setFocusIndex(index);
Owen Lina2fba682011-08-17 22:07:43 +0800221 mCurrentIndex = index;
222 mResultIntent.putExtra(KEY_INDEX_HINT, index);
223 if (item != null) {
224 mResultIntent.putExtra(KEY_MEDIA_ITEM_PATH, item.toString());
225 MediaItem photo = mModel.getCurrentMediaItem();
226 if (photo != null) updateCurrentPhoto(photo);
227 } else {
228 mResultIntent.removeExtra(KEY_MEDIA_ITEM_PATH);
229 }
230 setStateResult(Activity.RESULT_OK, mResultIntent);
231 }
232
233 @Override
234 public void onLoadingFinished() {
235 GalleryUtils.setSpinnerVisibility((Activity) mActivity, false);
236 if (!mModel.isEmpty()) {
237 MediaItem photo = mModel.getCurrentMediaItem();
238 if (photo != null) updateCurrentPhoto(photo);
239 } else if (mIsActive) {
240 mActivity.getStateManager().finishState(PhotoPage.this);
241 }
242 }
243
Owen Lina2fba682011-08-17 22:07:43 +0800244 @Override
245 public void onLoadingStarted() {
246 GalleryUtils.setSpinnerVisibility((Activity) mActivity, true);
247 }
Owen Linace280a2011-08-30 10:38:59 +0800248
249 @Override
250 public void onPhotoAvailable(long version, boolean fullImage) {
251 if (mFilmStripView == null) initFilmStripView();
252 }
Owen Lina2fba682011-08-17 22:07:43 +0800253 });
254 } else {
255 // Get default media set by the URI
256 MediaItem mediaItem = (MediaItem)
257 mActivity.getDataManager().getMediaObject(itemPath);
258 mModel = new SinglePhotoDataAdapter(mActivity, mPhotoView, mediaItem);
259 mPhotoView.setModel(mModel);
260 updateCurrentPhoto(mediaItem);
261 }
Ray Chen41419072011-09-14 16:46:32 +0800262
Owen Lina2fba682011-08-17 22:07:43 +0800263 mHandler = new SynchronizedHandler(mActivity.getGLRoot()) {
264 @Override
265 public void handleMessage(Message message) {
266 switch (message.what) {
267 case MSG_HIDE_BARS: {
268 hideBars();
269 break;
270 }
271 default: throw new AssertionError(message.what);
272 }
273 }
274 };
275
Yuli Huang54fe02f2012-03-20 16:37:05 +0800276 // start the opening animation only if it's not restored.
277 if (restoreState == null) {
278 mPhotoView.setOpenAnimationRect((Rect) data.getParcelable(KEY_OPEN_ANIMATION_RECT));
279 }
Owen Lina2fba682011-08-17 22:07:43 +0800280 }
281
Chih-Chung Chang706a7cf2012-03-15 16:38:45 +0800282 // We create a Camera View and a ScreenNail. The two work together
283 // to present the view together with other pictures. Returns the
284 // Path of the MediaItem hosting the ScreenNail.
285 private Path addCameraScreenNail() {
286 // Create a camera view and add it to the root.
287 Activity activity = (Activity) mActivity;
288 mCameraView = new CameraView(activity);
289 ViewGroup galleryRoot = (ViewGroup) activity.findViewById(R.id.gallery_root);
290 galleryRoot.addView(mCameraView);
291
292 // Create a ScreenNail and register it.
293 mScreenNail = new ScreenNailBridge(mCameraView);
294 mCameraView.setScreenNailBridge(mScreenNail);
295 return SnailSource.registerScreenNail(mScreenNail);
296 }
297
298 private void removeCameraScreenNail() {
299 if (mCameraView == null) return;
300
301 // Remove the camera view.
302 ((ViewGroup) mCameraView.getParent()).removeView(mCameraView);
303 mCameraView = null;
304
305 // Unregister the ScreenNail.
306 SnailSource.unregisterScreenNail(mScreenNail);
307 mScreenNail = null;
308 }
309
Ray Chen41419072011-09-14 16:46:32 +0800310 private void updateShareURI(Path path) {
311 if (mShareActionProvider != null) {
312 DataManager manager = mActivity.getDataManager();
313 int type = manager.getMediaType(path);
314 Intent intent = new Intent(Intent.ACTION_SEND);
315 intent.setType(MenuExecutor.getMimeType(type));
316 intent.putExtra(Intent.EXTRA_STREAM, manager.getContentUri(path));
317 mShareActionProvider.setShareIntent(intent);
318 mPendingSharePath = null;
319 } else {
320 // This happens when ActionBar is not created yet.
321 mPendingSharePath = path;
322 }
323 }
324
Ray Chen3f414cb2011-08-30 14:40:09 +0800325 private void setTitle(String title) {
326 if (title == null) return;
327 boolean showTitle = mActivity.getAndroidContext().getResources().getBoolean(
328 R.bool.show_action_bar_title);
329 if (showTitle)
330 mActionBar.setTitle(title);
331 else
332 mActionBar.setTitle("");
333 }
334
Owen Lina2fba682011-08-17 22:07:43 +0800335 private void updateCurrentPhoto(MediaItem photo) {
336 if (mCurrentPhoto == photo) return;
337 mCurrentPhoto = photo;
338 if (mCurrentPhoto == null) return;
339 updateMenuOperations();
340 if (mShowDetails) {
Ray Chen327eeb82011-08-24 11:40:04 +0800341 mDetailsHelper.reloadDetails(mModel.getCurrentIndex());
Owen Lina2fba682011-08-17 22:07:43 +0800342 }
Ray Chen3f414cb2011-08-30 14:40:09 +0800343 setTitle(photo.getName());
Ray Chen41419072011-09-14 16:46:32 +0800344 mPhotoView.showVideoPlayIcon(
345 photo.getMediaType() == MediaObject.MEDIA_TYPE_VIDEO);
Owen Lina2fba682011-08-17 22:07:43 +0800346
Chih-Chung Chang706a7cf2012-03-15 16:38:45 +0800347 if ((photo.getSupportedOperations() & MediaItem.SUPPORT_SHARE) != 0) {
348 updateShareURI(photo.getPath());
349 }
Owen Lina2fba682011-08-17 22:07:43 +0800350 }
351
352 private void updateMenuOperations() {
Chih-Chung Chang86024812011-11-18 18:04:10 +0800353 if (mMenu == null) return;
354 MenuItem item = mMenu.findItem(R.id.action_slideshow);
355 if (item != null) {
356 item.setVisible(canDoSlideShow());
357 }
358 if (mCurrentPhoto == null) return;
Owen Lina2fba682011-08-17 22:07:43 +0800359 int supportedOperations = mCurrentPhoto.getSupportedOperations();
360 if (!GalleryUtils.isEditorAvailable((Context) mActivity, "image/*")) {
361 supportedOperations &= ~MediaObject.SUPPORT_EDIT;
362 }
Ray Chen09efcf92011-10-21 16:07:12 +0800363
Owen Lina2fba682011-08-17 22:07:43 +0800364 MenuExecutor.updateMenuOperation(mMenu, supportedOperations);
365 }
366
Chih-Chung Chang86024812011-11-18 18:04:10 +0800367 private boolean canDoSlideShow() {
368 if (mMediaSet == null || mCurrentPhoto == null) {
369 return false;
370 }
371 if (mCurrentPhoto.getMediaType() != MediaObject.MEDIA_TYPE_IMAGE) {
372 return false;
373 }
374 if (mMediaSet instanceof MtpDevice) {
375 return false;
376 }
377 return true;
378 }
379
Owen Lina2fba682011-08-17 22:07:43 +0800380 private void showBars() {
381 if (mShowBars) return;
382 mShowBars = true;
383 mActionBar.show();
384 WindowManager.LayoutParams params = ((Activity) mActivity).getWindow().getAttributes();
385 params.systemUiVisibility = View.SYSTEM_UI_FLAG_VISIBLE;
386 ((Activity) mActivity).getWindow().setAttributes(params);
387 if (mFilmStripView != null) {
388 mFilmStripView.show();
389 }
390 }
391
392 private void hideBars() {
393 if (!mShowBars) return;
394 mShowBars = false;
395 mActionBar.hide();
396 WindowManager.LayoutParams params = ((Activity) mActivity).getWindow().getAttributes();
397 params.systemUiVisibility = View. SYSTEM_UI_FLAG_LOW_PROFILE;
398 ((Activity) mActivity).getWindow().setAttributes(params);
399 if (mFilmStripView != null) {
400 mFilmStripView.hide();
401 }
402 }
403
404 private void refreshHidingMessage() {
405 mHandler.removeMessages(MSG_HIDE_BARS);
406 if (!mIsMenuVisible && !mIsInteracting) {
407 mHandler.sendEmptyMessageDelayed(MSG_HIDE_BARS, HIDE_BARS_TIMEOUT);
408 }
409 }
410
Owen Linc907c322011-11-17 15:26:56 +0800411 @Override
Owen Lina2fba682011-08-17 22:07:43 +0800412 public void onUserInteraction() {
413 showBars();
414 refreshHidingMessage();
415 }
416
417 public void onUserInteractionTap() {
418 if (mShowBars) {
419 hideBars();
420 mHandler.removeMessages(MSG_HIDE_BARS);
421 } else {
422 showBars();
423 refreshHidingMessage();
424 }
425 }
426
Owen Linc907c322011-11-17 15:26:56 +0800427 @Override
Owen Lina2fba682011-08-17 22:07:43 +0800428 public void onUserInteractionBegin() {
429 showBars();
430 mIsInteracting = true;
431 refreshHidingMessage();
432 }
433
Owen Linc907c322011-11-17 15:26:56 +0800434 @Override
Owen Lina2fba682011-08-17 22:07:43 +0800435 public void onUserInteractionEnd() {
436 mIsInteracting = false;
Owen Linc907c322011-11-17 15:26:56 +0800437
438 // This function could be called from GL thread (in SlotView.render)
439 // and post to the main thread. So, it could be executed while the
440 // activity is paused.
441 if (mIsActive) refreshHidingMessage();
Owen Lina2fba682011-08-17 22:07:43 +0800442 }
443
444 @Override
445 protected void onBackPressed() {
446 if (mShowDetails) {
447 hideDetails();
448 } else {
449 PositionRepository repository = PositionRepository.getInstance(mActivity);
450 repository.clear();
451 if (mCurrentPhoto != null) {
452 Position position = new Position();
453 position.x = mRootPane.getWidth() / 2;
454 position.y = mRootPane.getHeight() / 2;
455 position.z = -1000;
456 repository.putPosition(
Chih-Chung Changad21fbe2012-02-15 08:19:50 +0800457 System.identityHashCode(mCurrentPhoto.getPath()),
Owen Lina2fba682011-08-17 22:07:43 +0800458 position);
459 }
460 super.onBackPressed();
461 }
462 }
463
464 @Override
465 protected boolean onCreateActionBar(Menu menu) {
466 MenuInflater inflater = ((Activity) mActivity).getMenuInflater();
467 inflater.inflate(R.menu.photo, menu);
Owen Lina2fba682011-08-17 22:07:43 +0800468 mShareActionProvider = GalleryActionBar.initializeShareActionProvider(menu);
Ray Chen41419072011-09-14 16:46:32 +0800469 if (mPendingSharePath != null) updateShareURI(mPendingSharePath);
Owen Lina2fba682011-08-17 22:07:43 +0800470 mMenu = menu;
471 mShowBars = true;
472 updateMenuOperations();
473 return true;
474 }
475
476 @Override
477 protected boolean onItemSelected(MenuItem item) {
478 MediaItem current = mModel.getCurrentMediaItem();
479
480 if (current == null) {
481 // item is not ready, ignore
482 return true;
483 }
484
485 int currentIndex = mModel.getCurrentIndex();
486 Path path = current.getPath();
487
488 DataManager manager = mActivity.getDataManager();
489 int action = item.getItemId();
490 switch (action) {
Ray Chenf3f7f562012-03-06 17:24:28 +0800491 case android.R.id.home: {
492 if (mSetPathString != null) {
493 if (mActivity.getStateManager().getStateCount() > 1) {
494 onBackPressed();
495 } else {
496 Activity a = (Activity) mActivity;
497 Uri uri = mActivity.getDataManager().getContentUri(
498 Path.fromString(mSetPathString));
499 Intent intent = new Intent(Intent.ACTION_VIEW)
500 .setClass(a, Gallery.class)
501 .setDataAndType(uri, ContentResolver.CURSOR_DIR_BASE_TYPE)
502 .setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP |
503 Intent.FLAG_ACTIVITY_NEW_TASK);
504 a.startActivity(intent);
505 }
506 }
507 return true;
508 }
Owen Lina2fba682011-08-17 22:07:43 +0800509 case R.id.action_slideshow: {
510 Bundle data = new Bundle();
Owen Lin44aac4b2011-08-28 10:50:21 +0800511 data.putString(SlideshowPage.KEY_SET_PATH, mMediaSet.getPath().toString());
Ray Chen09efcf92011-10-21 16:07:12 +0800512 data.putString(SlideshowPage.KEY_ITEM_PATH, path.toString());
Owen Lina2fba682011-08-17 22:07:43 +0800513 data.putInt(SlideshowPage.KEY_PHOTO_INDEX, currentIndex);
514 data.putBoolean(SlideshowPage.KEY_REPEAT, true);
515 mActivity.getStateManager().startStateForResult(
516 SlideshowPage.class, REQUEST_SLIDESHOW, data);
517 return true;
518 }
519 case R.id.action_crop: {
520 Activity activity = (Activity) mActivity;
521 Intent intent = new Intent(CropImage.CROP_ACTION);
522 intent.setClass(activity, CropImage.class);
523 intent.setData(manager.getContentUri(path));
524 activity.startActivityForResult(intent, PicasaSource.isPicasaImage(current)
525 ? REQUEST_CROP_PICASA
526 : REQUEST_CROP);
527 return true;
528 }
529 case R.id.action_details: {
530 if (mShowDetails) {
531 hideDetails();
532 } else {
533 showDetails(currentIndex);
534 }
535 return true;
536 }
537 case R.id.action_setas:
538 case R.id.action_confirm_delete:
539 case R.id.action_rotate_ccw:
540 case R.id.action_rotate_cw:
541 case R.id.action_show_on_map:
542 case R.id.action_edit:
543 mSelectionManager.deSelectAll();
544 mSelectionManager.toggle(path);
545 mMenuExecutor.onMenuClicked(item, null);
546 return true;
547 case R.id.action_import:
548 mSelectionManager.deSelectAll();
549 mSelectionManager.toggle(path);
550 mMenuExecutor.onMenuClicked(item,
551 new ImportCompleteListener(mActivity));
552 return true;
553 default :
554 return false;
555 }
556 }
557
558 private void hideDetails() {
559 mShowDetails = false;
Ray Chen327eeb82011-08-24 11:40:04 +0800560 mDetailsHelper.hide();
Owen Lina2fba682011-08-17 22:07:43 +0800561 }
562
563 private void showDetails(int index) {
564 mShowDetails = true;
Ray Chen327eeb82011-08-24 11:40:04 +0800565 if (mDetailsHelper == null) {
566 mDetailsHelper = new DetailsHelper(mActivity, mRootPane, new MyDetailsSource());
567 mDetailsHelper.setCloseListener(new CloseListener() {
Owen Lina2fba682011-08-17 22:07:43 +0800568 public void onClose() {
569 hideDetails();
570 }
571 });
Owen Lina2fba682011-08-17 22:07:43 +0800572 }
Ray Chen327eeb82011-08-24 11:40:04 +0800573 mDetailsHelper.reloadDetails(index);
574 mDetailsHelper.show();
Owen Lina2fba682011-08-17 22:07:43 +0800575 }
576
577 public void onSingleTapUp(int x, int y) {
578 MediaItem item = mModel.getCurrentMediaItem();
579 if (item == null) {
580 // item is not ready, ignore
581 return;
582 }
583
584 boolean playVideo =
585 (item.getSupportedOperations() & MediaItem.SUPPORT_PLAY) != 0;
586
587 if (playVideo) {
588 // determine if the point is at center (1/6) of the photo view.
589 // (The position of the "play" icon is at center (1/6) of the photo)
590 int w = mPhotoView.getWidth();
591 int h = mPhotoView.getHeight();
592 playVideo = (Math.abs(x - w / 2) * 12 <= w)
593 && (Math.abs(y - h / 2) * 12 <= h);
594 }
595
596 if (playVideo) {
597 playVideo((Activity) mActivity, item.getPlayUri(), item.getName());
598 } else {
599 onUserInteractionTap();
600 }
601 }
602
603 public static void playVideo(Activity activity, Uri uri, String title) {
604 try {
605 Intent intent = new Intent(Intent.ACTION_VIEW)
606 .setDataAndType(uri, "video/*");
607 intent.putExtra(Intent.EXTRA_TITLE, title);
608 activity.startActivity(intent);
609 } catch (ActivityNotFoundException e) {
610 Toast.makeText(activity, activity.getString(R.string.video_err),
611 Toast.LENGTH_SHORT).show();
612 }
613 }
614
Chih-Chung Chang36064d12011-09-14 12:07:17 +0800615 // Called by FileStripView.
616 // Returns false if it cannot jump to the specified index at this time.
617 public boolean onSlotSelected(int slotIndex) {
618 return mPhotoView.jumpTo(slotIndex);
Owen Lina2fba682011-08-17 22:07:43 +0800619 }
620
621 @Override
622 protected void onStateResult(int requestCode, int resultCode, Intent data) {
623 switch (requestCode) {
624 case REQUEST_CROP:
625 if (resultCode == Activity.RESULT_OK) {
626 if (data == null) break;
627 Path path = mApplication
628 .getDataManager().findPathByUri(data.getData());
629 if (path != null) {
630 mModel.setCurrentPhoto(path, mCurrentIndex);
631 }
632 }
633 break;
634 case REQUEST_CROP_PICASA: {
635 int message = resultCode == Activity.RESULT_OK
636 ? R.string.crop_saved
637 : R.string.crop_not_saved;
638 Toast.makeText(mActivity.getAndroidContext(),
639 message, Toast.LENGTH_SHORT).show();
640 break;
641 }
642 case REQUEST_SLIDESHOW: {
643 if (data == null) break;
644 String path = data.getStringExtra(SlideshowPage.KEY_ITEM_PATH);
645 int index = data.getIntExtra(SlideshowPage.KEY_PHOTO_INDEX, 0);
646 if (path != null) {
647 mModel.setCurrentPhoto(Path.fromString(path), index);
648 }
649 }
650 }
651 }
652
653 @Override
654 public void onPause() {
655 super.onPause();
656 mIsActive = false;
657 if (mFilmStripView != null) {
658 mFilmStripView.pause();
659 }
Ray Chen327eeb82011-08-24 11:40:04 +0800660 DetailsHelper.pause();
Owen Lina2fba682011-08-17 22:07:43 +0800661 mPhotoView.pause();
662 mModel.pause();
663 mHandler.removeMessages(MSG_HIDE_BARS);
664 mActionBar.removeOnMenuVisibilityListener(mMenuVisibilityListener);
Chih-Chung Chang377436d2011-09-08 11:51:11 +0800665 mMenuExecutor.pause();
Owen Lina2fba682011-08-17 22:07:43 +0800666 }
667
668 @Override
669 protected void onResume() {
670 super.onResume();
671 mIsActive = true;
672 setContentPane(mRootPane);
Yuli Huang54fe02f2012-03-20 16:37:05 +0800673 // Reset position offset for resuming.
674 PositionRepository.getInstance(mActivity).setOffset(
675 mPhotoView.bounds().left, mPhotoView.bounds().top);
676
Owen Lina2fba682011-08-17 22:07:43 +0800677 mModel.resume();
678 mPhotoView.resume();
679 if (mFilmStripView != null) {
680 mFilmStripView.resume();
681 }
682 if (mMenuVisibilityListener == null) {
683 mMenuVisibilityListener = new MyMenuVisibilityListener();
684 }
Ray Chen9af4a902012-03-20 16:32:57 +0800685 mActionBar.setDisplayOptions(mSetPathString != null, true);
Owen Lina2fba682011-08-17 22:07:43 +0800686 mActionBar.addOnMenuVisibilityListener(mMenuVisibilityListener);
687 onUserInteraction();
688 }
689
Chih-Chung Chang706a7cf2012-03-15 16:38:45 +0800690 @Override
691 protected void onDestroy() {
692 removeCameraScreenNail();
693 super.onDestroy();
694 }
695
Owen Lina2fba682011-08-17 22:07:43 +0800696 private class MyDetailsSource implements DetailsSource {
Ray Chen327eeb82011-08-24 11:40:04 +0800697 private int mIndex;
Owen Lin44aac4b2011-08-28 10:50:21 +0800698
699 @Override
Owen Lina2fba682011-08-17 22:07:43 +0800700 public MediaDetails getDetails() {
701 return mModel.getCurrentMediaItem().getDetails();
702 }
Owen Lin44aac4b2011-08-28 10:50:21 +0800703
704 @Override
Owen Lina2fba682011-08-17 22:07:43 +0800705 public int size() {
706 return mMediaSet != null ? mMediaSet.getMediaItemCount() : 1;
707 }
Owen Lin44aac4b2011-08-28 10:50:21 +0800708
709 @Override
Owen Lina2fba682011-08-17 22:07:43 +0800710 public int findIndex(int indexHint) {
Ray Chen327eeb82011-08-24 11:40:04 +0800711 mIndex = indexHint;
Owen Lina2fba682011-08-17 22:07:43 +0800712 return indexHint;
713 }
Ray Chen327eeb82011-08-24 11:40:04 +0800714
Owen Lin44aac4b2011-08-28 10:50:21 +0800715 @Override
Ray Chen327eeb82011-08-24 11:40:04 +0800716 public int getIndex() {
717 return mIndex;
718 }
Owen Lina2fba682011-08-17 22:07:43 +0800719 }
720}