summaryrefslogtreecommitdiffstats
path: root/src/com/android/gallery3d/ui/MenuExecutor.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/gallery3d/ui/MenuExecutor.java')
-rw-r--r--src/com/android/gallery3d/ui/MenuExecutor.java448
1 files changed, 448 insertions, 0 deletions
diff --git a/src/com/android/gallery3d/ui/MenuExecutor.java b/src/com/android/gallery3d/ui/MenuExecutor.java
new file mode 100644
index 000000000..29def0527
--- /dev/null
+++ b/src/com/android/gallery3d/ui/MenuExecutor.java
@@ -0,0 +1,448 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.gallery3d.ui;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.ProgressDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnCancelListener;
+import android.content.DialogInterface.OnClickListener;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.Message;
+import android.view.Menu;
+import android.view.MenuItem;
+
+import com.android.gallery3d.R;
+import com.android.gallery3d.app.AbstractGalleryActivity;
+import com.android.gallery3d.common.Utils;
+import com.android.gallery3d.data.DataManager;
+import com.android.gallery3d.data.MediaItem;
+import com.android.gallery3d.data.MediaObject;
+import com.android.gallery3d.data.Path;
+import com.android.gallery3d.filtershow.crop.CropActivity;
+import com.android.gallery3d.util.Future;
+import com.android.gallery3d.util.GalleryUtils;
+import com.android.gallery3d.util.ThreadPool.Job;
+import com.android.gallery3d.util.ThreadPool.JobContext;
+
+import java.util.ArrayList;
+
+public class MenuExecutor {
+ @SuppressWarnings("unused")
+ private static final String TAG = "MenuExecutor";
+
+ private static final int MSG_TASK_COMPLETE = 1;
+ private static final int MSG_TASK_UPDATE = 2;
+ private static final int MSG_TASK_START = 3;
+ private static final int MSG_DO_SHARE = 4;
+
+ public static final int EXECUTION_RESULT_SUCCESS = 1;
+ public static final int EXECUTION_RESULT_FAIL = 2;
+ public static final int EXECUTION_RESULT_CANCEL = 3;
+
+ private ProgressDialog mDialog;
+ private Future<?> mTask;
+ // wait the operation to finish when we want to stop it.
+ private boolean mWaitOnStop;
+ private boolean mPaused;
+
+ private final AbstractGalleryActivity mActivity;
+ private final SelectionManager mSelectionManager;
+ private final Handler mHandler;
+
+ private static ProgressDialog createProgressDialog(
+ Context context, int titleId, int progressMax) {
+ ProgressDialog dialog = new ProgressDialog(context);
+ dialog.setTitle(titleId);
+ dialog.setMax(progressMax);
+ dialog.setCancelable(false);
+ dialog.setIndeterminate(false);
+ if (progressMax > 1) {
+ dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
+ }
+ return dialog;
+ }
+
+ public interface ProgressListener {
+ public void onConfirmDialogShown();
+ public void onConfirmDialogDismissed(boolean confirmed);
+ public void onProgressStart();
+ public void onProgressUpdate(int index);
+ public void onProgressComplete(int result);
+ }
+
+ public MenuExecutor(
+ AbstractGalleryActivity activity, SelectionManager selectionManager) {
+ mActivity = Utils.checkNotNull(activity);
+ mSelectionManager = Utils.checkNotNull(selectionManager);
+ mHandler = new SynchronizedHandler(mActivity.getGLRoot()) {
+ @Override
+ public void handleMessage(Message message) {
+ switch (message.what) {
+ case MSG_TASK_START: {
+ if (message.obj != null) {
+ ProgressListener listener = (ProgressListener) message.obj;
+ listener.onProgressStart();
+ }
+ break;
+ }
+ case MSG_TASK_COMPLETE: {
+ stopTaskAndDismissDialog();
+ if (message.obj != null) {
+ ProgressListener listener = (ProgressListener) message.obj;
+ listener.onProgressComplete(message.arg1);
+ }
+ mSelectionManager.leaveSelectionMode();
+ break;
+ }
+ case MSG_TASK_UPDATE: {
+ if (mDialog != null && !mPaused) mDialog.setProgress(message.arg1);
+ if (message.obj != null) {
+ ProgressListener listener = (ProgressListener) message.obj;
+ listener.onProgressUpdate(message.arg1);
+ }
+ break;
+ }
+ case MSG_DO_SHARE: {
+ ((Activity) mActivity).startActivity((Intent) message.obj);
+ break;
+ }
+ }
+ }
+ };
+ }
+
+ private void stopTaskAndDismissDialog() {
+ if (mTask != null) {
+ if (!mWaitOnStop) mTask.cancel();
+ if (mDialog != null && mDialog.isShowing()) mDialog.dismiss();
+ mDialog = null;
+ mTask = null;
+ }
+ }
+
+ public void resume() {
+ mPaused = false;
+ if (mDialog != null) mDialog.show();
+ }
+
+ public void pause() {
+ mPaused = true;
+ if (mDialog != null && mDialog.isShowing()) mDialog.hide();
+ }
+
+ public void destroy() {
+ stopTaskAndDismissDialog();
+ }
+
+ private void onProgressUpdate(int index, ProgressListener listener) {
+ mHandler.sendMessage(
+ mHandler.obtainMessage(MSG_TASK_UPDATE, index, 0, listener));
+ }
+
+ private void onProgressStart(ProgressListener listener) {
+ mHandler.sendMessage(mHandler.obtainMessage(MSG_TASK_START, listener));
+ }
+
+ private void onProgressComplete(int result, ProgressListener listener) {
+ mHandler.sendMessage(mHandler.obtainMessage(MSG_TASK_COMPLETE, result, 0, listener));
+ }
+
+ public static void updateMenuOperation(Menu menu, int supported) {
+ boolean supportDelete = (supported & MediaObject.SUPPORT_DELETE) != 0;
+ boolean supportRotate = (supported & MediaObject.SUPPORT_ROTATE) != 0;
+ boolean supportCrop = (supported & MediaObject.SUPPORT_CROP) != 0;
+ boolean supportTrim = (supported & MediaObject.SUPPORT_TRIM) != 0;
+ boolean supportMute = (supported & MediaObject.SUPPORT_MUTE) != 0;
+ boolean supportShare = (supported & MediaObject.SUPPORT_SHARE) != 0;
+ boolean supportSetAs = (supported & MediaObject.SUPPORT_SETAS) != 0;
+ boolean supportShowOnMap = (supported & MediaObject.SUPPORT_SHOW_ON_MAP) != 0;
+ boolean supportCache = (supported & MediaObject.SUPPORT_CACHE) != 0;
+ boolean supportEdit = (supported & MediaObject.SUPPORT_EDIT) != 0;
+ boolean supportInfo = (supported & MediaObject.SUPPORT_INFO) != 0;
+
+ setMenuItemVisible(menu, R.id.action_delete, supportDelete);
+ setMenuItemVisible(menu, R.id.action_rotate_ccw, supportRotate);
+ setMenuItemVisible(menu, R.id.action_rotate_cw, supportRotate);
+ setMenuItemVisible(menu, R.id.action_crop, supportCrop);
+ setMenuItemVisible(menu, R.id.action_trim, supportTrim);
+ setMenuItemVisible(menu, R.id.action_mute, supportMute);
+ // Hide panorama until call to updateMenuForPanorama corrects it
+ setMenuItemVisible(menu, R.id.action_share_panorama, false);
+ setMenuItemVisible(menu, R.id.action_share, supportShare);
+ setMenuItemVisible(menu, R.id.action_setas, supportSetAs);
+ setMenuItemVisible(menu, R.id.action_show_on_map, supportShowOnMap);
+ setMenuItemVisible(menu, R.id.action_edit, supportEdit);
+ setMenuItemVisible(menu, R.id.action_simple_edit, supportEdit);
+ setMenuItemVisible(menu, R.id.action_details, supportInfo);
+ }
+
+ public static void updateMenuForPanorama(Menu menu, boolean shareAsPanorama360,
+ boolean disablePanorama360Options) {
+ setMenuItemVisible(menu, R.id.action_share_panorama, shareAsPanorama360);
+ if (disablePanorama360Options) {
+ setMenuItemVisible(menu, R.id.action_rotate_ccw, false);
+ setMenuItemVisible(menu, R.id.action_rotate_cw, false);
+ }
+ }
+
+ private static void setMenuItemVisible(Menu menu, int itemId, boolean visible) {
+ MenuItem item = menu.findItem(itemId);
+ if (item != null) item.setVisible(visible);
+ }
+
+ private Path getSingleSelectedPath() {
+ ArrayList<Path> ids = mSelectionManager.getSelected(true);
+ Utils.assertTrue(ids.size() == 1);
+ return ids.get(0);
+ }
+
+ private Intent getIntentBySingleSelectedPath(String action) {
+ DataManager manager = mActivity.getDataManager();
+ Path path = getSingleSelectedPath();
+ String mimeType = getMimeType(manager.getMediaType(path));
+ return new Intent(action).setDataAndType(manager.getContentUri(path), mimeType);
+ }
+
+ private void onMenuClicked(int action, ProgressListener listener) {
+ onMenuClicked(action, listener, false, true);
+ }
+
+ public void onMenuClicked(int action, ProgressListener listener,
+ boolean waitOnStop, boolean showDialog) {
+ int title;
+ switch (action) {
+ case R.id.action_select_all:
+ if (mSelectionManager.inSelectAllMode()) {
+ mSelectionManager.deSelectAll();
+ } else {
+ mSelectionManager.selectAll();
+ }
+ return;
+ case R.id.action_crop: {
+ Intent intent = getIntentBySingleSelectedPath(CropActivity.CROP_ACTION);
+ ((Activity) mActivity).startActivity(intent);
+ return;
+ }
+ case R.id.action_edit: {
+ Intent intent = getIntentBySingleSelectedPath(Intent.ACTION_EDIT)
+ .setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ ((Activity) mActivity).startActivity(Intent.createChooser(intent, null));
+ return;
+ }
+ case R.id.action_setas: {
+ Intent intent = getIntentBySingleSelectedPath(Intent.ACTION_ATTACH_DATA)
+ .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ intent.putExtra("mimeType", intent.getType());
+ Activity activity = mActivity;
+ activity.startActivity(Intent.createChooser(
+ intent, activity.getString(R.string.set_as)));
+ return;
+ }
+ case R.id.action_delete:
+ title = R.string.delete;
+ break;
+ case R.id.action_rotate_cw:
+ title = R.string.rotate_right;
+ break;
+ case R.id.action_rotate_ccw:
+ title = R.string.rotate_left;
+ break;
+ case R.id.action_show_on_map:
+ title = R.string.show_on_map;
+ break;
+ default:
+ return;
+ }
+ startAction(action, title, listener, waitOnStop, showDialog);
+ }
+
+ private class ConfirmDialogListener implements OnClickListener, OnCancelListener {
+ private final int mActionId;
+ private final ProgressListener mListener;
+
+ public ConfirmDialogListener(int actionId, ProgressListener listener) {
+ mActionId = actionId;
+ mListener = listener;
+ }
+
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ if (which == DialogInterface.BUTTON_POSITIVE) {
+ if (mListener != null) {
+ mListener.onConfirmDialogDismissed(true);
+ }
+ onMenuClicked(mActionId, mListener);
+ } else {
+ if (mListener != null) {
+ mListener.onConfirmDialogDismissed(false);
+ }
+ }
+ }
+
+ @Override
+ public void onCancel(DialogInterface dialog) {
+ if (mListener != null) {
+ mListener.onConfirmDialogDismissed(false);
+ }
+ }
+ }
+
+ public void onMenuClicked(MenuItem menuItem, String confirmMsg,
+ final ProgressListener listener) {
+ final int action = menuItem.getItemId();
+
+ if (confirmMsg != null) {
+ if (listener != null) listener.onConfirmDialogShown();
+ ConfirmDialogListener cdl = new ConfirmDialogListener(action, listener);
+ new AlertDialog.Builder(mActivity.getAndroidContext())
+ .setMessage(confirmMsg)
+ .setOnCancelListener(cdl)
+ .setPositiveButton(R.string.ok, cdl)
+ .setNegativeButton(R.string.cancel, cdl)
+ .create().show();
+ } else {
+ onMenuClicked(action, listener);
+ }
+ }
+
+ public void startAction(int action, int title, ProgressListener listener) {
+ startAction(action, title, listener, false, true);
+ }
+
+ public void startAction(int action, int title, ProgressListener listener,
+ boolean waitOnStop, boolean showDialog) {
+ ArrayList<Path> ids = mSelectionManager.getSelected(false);
+ stopTaskAndDismissDialog();
+
+ Activity activity = mActivity;
+ if (showDialog) {
+ mDialog = createProgressDialog(activity, title, ids.size());
+ mDialog.show();
+ } else {
+ mDialog = null;
+ }
+ MediaOperation operation = new MediaOperation(action, ids, listener);
+ mTask = mActivity.getBatchServiceThreadPoolIfAvailable().submit(operation, null);
+ mWaitOnStop = waitOnStop;
+ }
+
+ public void startSingleItemAction(int action, Path targetPath) {
+ ArrayList<Path> ids = new ArrayList<Path>(1);
+ ids.add(targetPath);
+ mDialog = null;
+ MediaOperation operation = new MediaOperation(action, ids, null);
+ mTask = mActivity.getBatchServiceThreadPoolIfAvailable().submit(operation, null);
+ mWaitOnStop = false;
+ }
+
+ public static String getMimeType(int type) {
+ switch (type) {
+ case MediaObject.MEDIA_TYPE_IMAGE :
+ return GalleryUtils.MIME_TYPE_IMAGE;
+ case MediaObject.MEDIA_TYPE_VIDEO :
+ return GalleryUtils.MIME_TYPE_VIDEO;
+ default: return GalleryUtils.MIME_TYPE_ALL;
+ }
+ }
+
+ private boolean execute(
+ DataManager manager, JobContext jc, int cmd, Path path) {
+ boolean result = true;
+ Log.v(TAG, "Execute cmd: " + cmd + " for " + path);
+ long startTime = System.currentTimeMillis();
+
+ switch (cmd) {
+ case R.id.action_delete:
+ manager.delete(path);
+ break;
+ case R.id.action_rotate_cw:
+ manager.rotate(path, 90);
+ break;
+ case R.id.action_rotate_ccw:
+ manager.rotate(path, -90);
+ break;
+ case R.id.action_toggle_full_caching: {
+ MediaObject obj = manager.getMediaObject(path);
+ int cacheFlag = obj.getCacheFlag();
+ if (cacheFlag == MediaObject.CACHE_FLAG_FULL) {
+ cacheFlag = MediaObject.CACHE_FLAG_SCREENNAIL;
+ } else {
+ cacheFlag = MediaObject.CACHE_FLAG_FULL;
+ }
+ obj.cache(cacheFlag);
+ break;
+ }
+ case R.id.action_show_on_map: {
+ MediaItem item = (MediaItem) manager.getMediaObject(path);
+ double latlng[] = new double[2];
+ item.getLatLong(latlng);
+ if (GalleryUtils.isValidLocation(latlng[0], latlng[1])) {
+ GalleryUtils.showOnMap(mActivity, latlng[0], latlng[1]);
+ }
+ break;
+ }
+ default:
+ throw new AssertionError();
+ }
+ Log.v(TAG, "It takes " + (System.currentTimeMillis() - startTime) +
+ " ms to execute cmd for " + path);
+ return result;
+ }
+
+ private class MediaOperation implements Job<Void> {
+ private final ArrayList<Path> mItems;
+ private final int mOperation;
+ private final ProgressListener mListener;
+
+ public MediaOperation(int operation, ArrayList<Path> items,
+ ProgressListener listener) {
+ mOperation = operation;
+ mItems = items;
+ mListener = listener;
+ }
+
+ @Override
+ public Void run(JobContext jc) {
+ int index = 0;
+ DataManager manager = mActivity.getDataManager();
+ int result = EXECUTION_RESULT_SUCCESS;
+ try {
+ onProgressStart(mListener);
+ for (Path id : mItems) {
+ if (jc.isCancelled()) {
+ result = EXECUTION_RESULT_CANCEL;
+ break;
+ }
+ if (!execute(manager, jc, mOperation, id)) {
+ result = EXECUTION_RESULT_FAIL;
+ }
+ onProgressUpdate(index++, mListener);
+ }
+ } catch (Throwable th) {
+ Log.e(TAG, "failed to execute operation " + mOperation
+ + " : " + th);
+ } finally {
+ onProgressComplete(result, mListener);
+ }
+ return null;
+ }
+ }
+}