OSDN Git Service

am 870e62ac: Handle the case where the orientation column is not here...
[android-x86/packages-apps-Gallery2.git] / src / com / android / gallery3d / ui / MenuExecutor.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.ui;
18
19 import android.app.Activity;
20 import android.app.AlertDialog;
21 import android.app.ProgressDialog;
22 import android.content.Context;
23 import android.content.DialogInterface;
24 import android.content.DialogInterface.OnCancelListener;
25 import android.content.DialogInterface.OnClickListener;
26 import android.content.Intent;
27 import android.os.Handler;
28 import android.os.Message;
29 import android.view.Menu;
30 import android.view.MenuItem;
31
32 import com.android.gallery3d.R;
33 import com.android.gallery3d.app.AbstractGalleryActivity;
34 import com.android.gallery3d.app.CropImage;
35 import com.android.gallery3d.common.Utils;
36 import com.android.gallery3d.data.DataManager;
37 import com.android.gallery3d.data.MediaItem;
38 import com.android.gallery3d.data.MediaObject;
39 import com.android.gallery3d.data.Path;
40 import com.android.gallery3d.filtershow.FilterShowActivity;
41 import com.android.gallery3d.util.Future;
42 import com.android.gallery3d.util.GalleryUtils;
43 import com.android.gallery3d.util.ThreadPool.Job;
44 import com.android.gallery3d.util.ThreadPool.JobContext;
45
46 import java.util.ArrayList;
47
48 public class MenuExecutor {
49     @SuppressWarnings("unused")
50     private static final String TAG = "MenuExecutor";
51
52     private static final int MSG_TASK_COMPLETE = 1;
53     private static final int MSG_TASK_UPDATE = 2;
54     private static final int MSG_TASK_START = 3;
55     private static final int MSG_DO_SHARE = 4;
56
57     public static final int EXECUTION_RESULT_SUCCESS = 1;
58     public static final int EXECUTION_RESULT_FAIL = 2;
59     public static final int EXECUTION_RESULT_CANCEL = 3;
60
61     private ProgressDialog mDialog;
62     private Future<?> mTask;
63     // wait the operation to finish when we want to stop it.
64     private boolean mWaitOnStop;
65
66     private final AbstractGalleryActivity mActivity;
67     private final SelectionManager mSelectionManager;
68     private final Handler mHandler;
69
70     private static ProgressDialog createProgressDialog(
71             Context context, int titleId, int progressMax) {
72         ProgressDialog dialog = new ProgressDialog(context);
73         dialog.setTitle(titleId);
74         dialog.setMax(progressMax);
75         dialog.setCancelable(false);
76         dialog.setIndeterminate(false);
77         if (progressMax > 1) {
78             dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
79         }
80         return dialog;
81     }
82
83     public interface ProgressListener {
84         public void onConfirmDialogShown();
85         public void onConfirmDialogDismissed(boolean confirmed);
86         public void onProgressStart();
87         public void onProgressUpdate(int index);
88         public void onProgressComplete(int result);
89     }
90
91     public MenuExecutor(
92             AbstractGalleryActivity activity, SelectionManager selectionManager) {
93         mActivity = Utils.checkNotNull(activity);
94         mSelectionManager = Utils.checkNotNull(selectionManager);
95         mHandler = new SynchronizedHandler(mActivity.getGLRoot()) {
96             @Override
97             public void handleMessage(Message message) {
98                 switch (message.what) {
99                     case MSG_TASK_START: {
100                         if (message.obj != null) {
101                             ProgressListener listener = (ProgressListener) message.obj;
102                             listener.onProgressStart();
103                         }
104                         break;
105                     }
106                     case MSG_TASK_COMPLETE: {
107                         stopTaskAndDismissDialog();
108                         if (message.obj != null) {
109                             ProgressListener listener = (ProgressListener) message.obj;
110                             listener.onProgressComplete(message.arg1);
111                         }
112                         mSelectionManager.leaveSelectionMode();
113                         break;
114                     }
115                     case MSG_TASK_UPDATE: {
116                         if (mDialog != null) mDialog.setProgress(message.arg1);
117                         if (message.obj != null) {
118                             ProgressListener listener = (ProgressListener) message.obj;
119                             listener.onProgressUpdate(message.arg1);
120                         }
121                         break;
122                     }
123                     case MSG_DO_SHARE: {
124                         ((Activity) mActivity).startActivity((Intent) message.obj);
125                         break;
126                     }
127                 }
128             }
129         };
130     }
131
132     private void stopTaskAndDismissDialog() {
133         if (mTask != null) {
134             if (!mWaitOnStop) mTask.cancel();
135             mTask.waitDone();
136             mDialog.dismiss();
137             mDialog = null;
138             mTask = null;
139         }
140     }
141
142     public void pause() {
143         stopTaskAndDismissDialog();
144     }
145
146     private void onProgressUpdate(int index, ProgressListener listener) {
147         mHandler.sendMessage(
148                 mHandler.obtainMessage(MSG_TASK_UPDATE, index, 0, listener));
149     }
150
151     private void onProgressStart(ProgressListener listener) {
152         mHandler.sendMessage(mHandler.obtainMessage(MSG_TASK_START, listener));
153     }
154
155     private void onProgressComplete(int result, ProgressListener listener) {
156         mHandler.sendMessage(mHandler.obtainMessage(MSG_TASK_COMPLETE, result, 0, listener));
157     }
158
159     public static void updateMenuOperation(Menu menu, int supported) {
160         boolean supportDelete = (supported & MediaObject.SUPPORT_DELETE) != 0;
161         boolean supportRotate = (supported & MediaObject.SUPPORT_ROTATE) != 0;
162         boolean supportCrop = (supported & MediaObject.SUPPORT_CROP) != 0;
163         boolean supportTrim = (supported & MediaObject.SUPPORT_TRIM) != 0;
164         boolean supportShare = (supported & MediaObject.SUPPORT_SHARE) != 0;
165         boolean supportSetAs = (supported & MediaObject.SUPPORT_SETAS) != 0;
166         boolean supportShowOnMap = (supported & MediaObject.SUPPORT_SHOW_ON_MAP) != 0;
167         boolean supportCache = (supported & MediaObject.SUPPORT_CACHE) != 0;
168         boolean supportEdit = (supported & MediaObject.SUPPORT_EDIT) != 0;
169         boolean supportInfo = (supported & MediaObject.SUPPORT_INFO) != 0;
170         boolean supportImport = (supported & MediaObject.SUPPORT_IMPORT) != 0;
171
172         setMenuItemVisible(menu, R.id.action_delete, supportDelete);
173         setMenuItemVisible(menu, R.id.action_rotate_ccw, supportRotate);
174         setMenuItemVisible(menu, R.id.action_rotate_cw, supportRotate);
175         setMenuItemVisible(menu, R.id.action_crop, supportCrop);
176         setMenuItemVisible(menu, R.id.action_trim, supportTrim);
177         // Hide panorama until call to updateMenuForPanorama corrects it
178         setMenuItemVisible(menu, R.id.action_share_panorama, false);
179         setMenuItemVisible(menu, R.id.action_share, supportShare);
180         setMenuItemVisible(menu, R.id.action_setas, supportSetAs);
181         setMenuItemVisible(menu, R.id.action_show_on_map, supportShowOnMap);
182         setMenuItemVisible(menu, R.id.action_edit, supportEdit);
183         setMenuItemVisible(menu, R.id.action_details, supportInfo);
184         setMenuItemVisible(menu, R.id.action_import, supportImport);
185     }
186
187     public static void updateMenuForPanorama(Menu menu, boolean shareAsPanorama360,
188             boolean disablePanorama360Options) {
189         setMenuItemVisible(menu, R.id.action_share_panorama, shareAsPanorama360);
190         if (disablePanorama360Options) {
191             setMenuItemVisible(menu, R.id.action_rotate_ccw, false);
192             setMenuItemVisible(menu, R.id.action_rotate_cw, false);
193         }
194     }
195
196     private static void setMenuItemVisible(Menu menu, int itemId, boolean visible) {
197         MenuItem item = menu.findItem(itemId);
198         if (item != null) item.setVisible(visible);
199     }
200
201     private Path getSingleSelectedPath() {
202         ArrayList<Path> ids = mSelectionManager.getSelected(true);
203         Utils.assertTrue(ids.size() == 1);
204         return ids.get(0);
205     }
206
207     private Intent getIntentBySingleSelectedPath(String action) {
208         DataManager manager = mActivity.getDataManager();
209         Path path = getSingleSelectedPath();
210         String mimeType = getMimeType(manager.getMediaType(path));
211         return new Intent(action).setDataAndType(manager.getContentUri(path), mimeType);
212     }
213
214     private void onMenuClicked(int action, ProgressListener listener) {
215         onMenuClicked(action, listener, false, true);
216     }
217
218     public void onMenuClicked(int action, ProgressListener listener,
219             boolean waitOnStop, boolean showDialog) {
220         int title;
221         switch (action) {
222             case R.id.action_select_all:
223                 if (mSelectionManager.inSelectAllMode()) {
224                     mSelectionManager.deSelectAll();
225                 } else {
226                     mSelectionManager.selectAll();
227                 }
228                 return;
229             case R.id.action_crop: {
230                 Intent intent = getIntentBySingleSelectedPath(FilterShowActivity.CROP_ACTION)
231                         .setClass((Activity) mActivity, FilterShowActivity.class);
232                 ((Activity) mActivity).startActivity(intent);
233                 return;
234             }
235             case R.id.action_edit: {
236                 Intent intent = getIntentBySingleSelectedPath(Intent.ACTION_EDIT)
237                         .setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
238                 ((Activity) mActivity).startActivity(Intent.createChooser(intent, null));
239                 return;
240             }
241             case R.id.action_setas: {
242                 Intent intent = getIntentBySingleSelectedPath(Intent.ACTION_ATTACH_DATA)
243                         .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
244                 intent.putExtra("mimeType", intent.getType());
245                 Activity activity = mActivity;
246                 activity.startActivity(Intent.createChooser(
247                         intent, activity.getString(R.string.set_as)));
248                 return;
249             }
250             case R.id.action_delete:
251                 title = R.string.delete;
252                 break;
253             case R.id.action_rotate_cw:
254                 title = R.string.rotate_right;
255                 break;
256             case R.id.action_rotate_ccw:
257                 title = R.string.rotate_left;
258                 break;
259             case R.id.action_show_on_map:
260                 title = R.string.show_on_map;
261                 break;
262             case R.id.action_import:
263                 title = R.string.Import;
264                 break;
265             default:
266                 return;
267         }
268         startAction(action, title, listener, waitOnStop, showDialog);
269     }
270
271     private class ConfirmDialogListener implements OnClickListener, OnCancelListener {
272         private final int mActionId;
273         private final ProgressListener mListener;
274
275         public ConfirmDialogListener(int actionId, ProgressListener listener) {
276             mActionId = actionId;
277             mListener = listener;
278         }
279
280         @Override
281         public void onClick(DialogInterface dialog, int which) {
282             if (which == DialogInterface.BUTTON_POSITIVE) {
283                 if (mListener != null) {
284                     mListener.onConfirmDialogDismissed(true);
285                 }
286                 onMenuClicked(mActionId, mListener);
287             } else {
288                 if (mListener != null) {
289                     mListener.onConfirmDialogDismissed(false);
290                 }
291             }
292         }
293
294         @Override
295         public void onCancel(DialogInterface dialog) {
296             if (mListener != null) {
297                 mListener.onConfirmDialogDismissed(false);
298             }
299         }
300     }
301
302     public void onMenuClicked(MenuItem menuItem, String confirmMsg,
303             final ProgressListener listener) {
304         final int action = menuItem.getItemId();
305
306         if (confirmMsg != null) {
307             if (listener != null) listener.onConfirmDialogShown();
308             ConfirmDialogListener cdl = new ConfirmDialogListener(action, listener);
309             new AlertDialog.Builder(mActivity.getAndroidContext())
310                     .setMessage(confirmMsg)
311                     .setOnCancelListener(cdl)
312                     .setPositiveButton(R.string.ok, cdl)
313                     .setNegativeButton(R.string.cancel, cdl)
314                     .create().show();
315         } else {
316             onMenuClicked(action, listener);
317         }
318     }
319
320     public void startAction(int action, int title, ProgressListener listener) {
321         startAction(action, title, listener, false, true);
322     }
323
324     public void startAction(int action, int title, ProgressListener listener,
325             boolean waitOnStop, boolean showDialog) {
326         ArrayList<Path> ids = mSelectionManager.getSelected(false);
327         stopTaskAndDismissDialog();
328
329         Activity activity = mActivity;
330         mDialog = createProgressDialog(activity, title, ids.size());
331         if (showDialog) {
332             mDialog.show();
333         }
334         MediaOperation operation = new MediaOperation(action, ids, listener);
335         mTask = mActivity.getThreadPool().submit(operation, null);
336         mWaitOnStop = waitOnStop;
337     }
338
339     public static String getMimeType(int type) {
340         switch (type) {
341             case MediaObject.MEDIA_TYPE_IMAGE :
342                 return GalleryUtils.MIME_TYPE_IMAGE;
343             case MediaObject.MEDIA_TYPE_VIDEO :
344                 return GalleryUtils.MIME_TYPE_VIDEO;
345             default: return GalleryUtils.MIME_TYPE_ALL;
346         }
347     }
348
349     private boolean execute(
350             DataManager manager, JobContext jc, int cmd, Path path) {
351         boolean result = true;
352         Log.v(TAG, "Execute cmd: " + cmd + " for " + path);
353         long startTime = System.currentTimeMillis();
354
355         switch (cmd) {
356             case R.id.action_delete:
357                 manager.delete(path);
358                 break;
359             case R.id.action_rotate_cw:
360                 manager.rotate(path, 90);
361                 break;
362             case R.id.action_rotate_ccw:
363                 manager.rotate(path, -90);
364                 break;
365             case R.id.action_toggle_full_caching: {
366                 MediaObject obj = manager.getMediaObject(path);
367                 int cacheFlag = obj.getCacheFlag();
368                 if (cacheFlag == MediaObject.CACHE_FLAG_FULL) {
369                     cacheFlag = MediaObject.CACHE_FLAG_SCREENNAIL;
370                 } else {
371                     cacheFlag = MediaObject.CACHE_FLAG_FULL;
372                 }
373                 obj.cache(cacheFlag);
374                 break;
375             }
376             case R.id.action_show_on_map: {
377                 MediaItem item = (MediaItem) manager.getMediaObject(path);
378                 double latlng[] = new double[2];
379                 item.getLatLong(latlng);
380                 if (GalleryUtils.isValidLocation(latlng[0], latlng[1])) {
381                     GalleryUtils.showOnMap(mActivity, latlng[0], latlng[1]);
382                 }
383                 break;
384             }
385             case R.id.action_import: {
386                 MediaObject obj = manager.getMediaObject(path);
387                 result = obj.Import();
388                 break;
389             }
390             default:
391                 throw new AssertionError();
392         }
393         Log.v(TAG, "It takes " + (System.currentTimeMillis() - startTime) +
394                 " ms to execute cmd for " + path);
395         return result;
396     }
397
398     private class MediaOperation implements Job<Void> {
399         private final ArrayList<Path> mItems;
400         private final int mOperation;
401         private final ProgressListener mListener;
402
403         public MediaOperation(int operation, ArrayList<Path> items,
404                 ProgressListener listener) {
405             mOperation = operation;
406             mItems = items;
407             mListener = listener;
408         }
409
410         @Override
411         public Void run(JobContext jc) {
412             int index = 0;
413             DataManager manager = mActivity.getDataManager();
414             int result = EXECUTION_RESULT_SUCCESS;
415             try {
416                 onProgressStart(mListener);
417                 for (Path id : mItems) {
418                     if (jc.isCancelled()) {
419                         result = EXECUTION_RESULT_CANCEL;
420                         break;
421                     }
422                     if (!execute(manager, jc, mOperation, id)) {
423                         result = EXECUTION_RESULT_FAIL;
424                     }
425                     onProgressUpdate(++index, mListener);
426                 }
427             } catch (Throwable th) {
428                 Log.e(TAG, "failed to execute operation " + mOperation
429                         + " : " + th);
430             } finally {
431                onProgressComplete(result, mListener);
432             }
433             return null;
434         }
435     }
436 }