diff options
Diffstat (limited to 'src/com/android/gallery3d/ui/ActionModeHandler.java')
-rw-r--r-- | src/com/android/gallery3d/ui/ActionModeHandler.java | 501 |
1 files changed, 0 insertions, 501 deletions
diff --git a/src/com/android/gallery3d/ui/ActionModeHandler.java b/src/com/android/gallery3d/ui/ActionModeHandler.java deleted file mode 100644 index 6b4f10312..000000000 --- a/src/com/android/gallery3d/ui/ActionModeHandler.java +++ /dev/null @@ -1,501 +0,0 @@ -/* - * 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.annotation.TargetApi; -import android.app.Activity; -import android.content.Intent; -import android.net.Uri; -import android.nfc.NfcAdapter; -import android.os.Handler; -import android.view.ActionMode; -import android.view.ActionMode.Callback; -import android.view.LayoutInflater; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.widget.Button; -import android.widget.ShareActionProvider; -import android.widget.ShareActionProvider.OnShareTargetSelectedListener; - -import com.android.gallery3d.R; -import com.android.gallery3d.app.AbstractGalleryActivity; -import com.android.gallery3d.common.ApiHelper; -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.data.DataManager; -import com.android.gallery3d.data.MediaObject; -import com.android.gallery3d.data.MediaObject.PanoramaSupportCallback; -import com.android.gallery3d.data.Path; -import com.android.gallery3d.ui.MenuExecutor.ProgressListener; -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 ActionModeHandler implements Callback, PopupList.OnPopupItemClickListener { - - @SuppressWarnings("unused") - private static final String TAG = "ActionModeHandler"; - - private static final int MAX_SELECTED_ITEMS_FOR_SHARE_INTENT = 300; - private static final int MAX_SELECTED_ITEMS_FOR_PANORAMA_SHARE_INTENT = 10; - - private static final int SUPPORT_MULTIPLE_MASK = MediaObject.SUPPORT_DELETE - | MediaObject.SUPPORT_ROTATE | MediaObject.SUPPORT_SHARE - | MediaObject.SUPPORT_CACHE; - - public interface ActionModeListener { - public boolean onActionItemClicked(MenuItem item); - } - - private final AbstractGalleryActivity mActivity; - private final MenuExecutor mMenuExecutor; - private final SelectionManager mSelectionManager; - private final NfcAdapter mNfcAdapter; - private Menu mMenu; - private MenuItem mSharePanoramaMenuItem; - private MenuItem mShareMenuItem; - private ShareActionProvider mSharePanoramaActionProvider; - private ShareActionProvider mShareActionProvider; - private SelectionMenu mSelectionMenu; - private ActionModeListener mListener; - private Future<?> mMenuTask; - private final Handler mMainHandler; - private ActionMode mActionMode; - - private static class GetAllPanoramaSupports implements PanoramaSupportCallback { - private int mNumInfoRequired; - private JobContext mJobContext; - public boolean mAllPanoramas = true; - public boolean mAllPanorama360 = true; - public boolean mHasPanorama360 = false; - private Object mLock = new Object(); - - public GetAllPanoramaSupports(ArrayList<MediaObject> mediaObjects, JobContext jc) { - mJobContext = jc; - mNumInfoRequired = mediaObjects.size(); - for (MediaObject mediaObject : mediaObjects) { - mediaObject.getPanoramaSupport(this); - } - } - - @Override - public void panoramaInfoAvailable(MediaObject mediaObject, boolean isPanorama, - boolean isPanorama360) { - synchronized (mLock) { - mNumInfoRequired--; - mAllPanoramas = isPanorama && mAllPanoramas; - mAllPanorama360 = isPanorama360 && mAllPanorama360; - mHasPanorama360 = mHasPanorama360 || isPanorama360; - if (mNumInfoRequired == 0 || mJobContext.isCancelled()) { - mLock.notifyAll(); - } - } - } - - public void waitForPanoramaSupport() { - synchronized (mLock) { - while (mNumInfoRequired != 0 && !mJobContext.isCancelled()) { - try { - mLock.wait(); - } catch (InterruptedException e) { - // May be a cancelled job context - } - } - } - } - } - - public ActionModeHandler( - AbstractGalleryActivity activity, SelectionManager selectionManager) { - mActivity = Utils.checkNotNull(activity); - mSelectionManager = Utils.checkNotNull(selectionManager); - mMenuExecutor = new MenuExecutor(activity, selectionManager); - mMainHandler = new Handler(activity.getMainLooper()); - mNfcAdapter = NfcAdapter.getDefaultAdapter(mActivity.getAndroidContext()); - } - - public void startActionMode() { - Activity a = mActivity; - mActionMode = a.startActionMode(this); - View customView = LayoutInflater.from(a).inflate( - R.layout.action_mode, null); - mActionMode.setCustomView(customView); - mSelectionMenu = new SelectionMenu(a, - (Button) customView.findViewById(R.id.selection_menu), this); - updateSelectionMenu(); - } - - public void finishActionMode() { - mActionMode.finish(); - } - - public void setTitle(String title) { - mSelectionMenu.setTitle(title); - } - - public void setActionModeListener(ActionModeListener listener) { - mListener = listener; - } - - private WakeLockHoldingProgressListener mDeleteProgressListener; - - @Override - public boolean onActionItemClicked(ActionMode mode, MenuItem item) { - GLRoot root = mActivity.getGLRoot(); - root.lockRenderThread(); - try { - boolean result; - // Give listener a chance to process this command before it's routed to - // ActionModeHandler, which handles command only based on the action id. - // Sometimes the listener may have more background information to handle - // an action command. - if (mListener != null) { - result = mListener.onActionItemClicked(item); - if (result) { - mSelectionManager.leaveSelectionMode(); - return result; - } - } - ProgressListener listener = null; - String confirmMsg = null; - int action = item.getItemId(); - if (action == R.id.action_delete) { - confirmMsg = mActivity.getResources().getQuantityString( - R.plurals.delete_selection, mSelectionManager.getSelectedCount()); - if (mDeleteProgressListener == null) { - mDeleteProgressListener = new WakeLockHoldingProgressListener(mActivity, - "Gallery Delete Progress Listener"); - } - listener = mDeleteProgressListener; - } - mMenuExecutor.onMenuClicked(item, confirmMsg, listener); - } finally { - root.unlockRenderThread(); - } - return true; - } - - @Override - public boolean onPopupItemClick(int itemId) { - GLRoot root = mActivity.getGLRoot(); - root.lockRenderThread(); - try { - if (itemId == R.id.action_select_all) { - updateSupportedOperation(); - mMenuExecutor.onMenuClicked(itemId, null, false, true); - } - return true; - } finally { - root.unlockRenderThread(); - } - } - - private void updateSelectionMenu() { - // update title - int count = mSelectionManager.getSelectedCount(); - String format = mActivity.getResources().getQuantityString( - R.plurals.number_of_items_selected, count); - setTitle(String.format(format, count)); - - // For clients who call SelectionManager.selectAll() directly, we need to ensure the - // menu status is consistent with selection manager. - mSelectionMenu.updateSelectAllMode(mSelectionManager.inSelectAllMode()); - } - - private final OnShareTargetSelectedListener mShareTargetSelectedListener = - new OnShareTargetSelectedListener() { - @Override - public boolean onShareTargetSelected(ShareActionProvider source, Intent intent) { - mSelectionManager.leaveSelectionMode(); - return false; - } - }; - - @Override - public boolean onPrepareActionMode(ActionMode mode, Menu menu) { - return false; - } - - @Override - public boolean onCreateActionMode(ActionMode mode, Menu menu) { - mode.getMenuInflater().inflate(R.menu.operation, menu); - - mMenu = menu; - mSharePanoramaMenuItem = menu.findItem(R.id.action_share_panorama); - if (mSharePanoramaMenuItem != null) { - mSharePanoramaActionProvider = (ShareActionProvider) mSharePanoramaMenuItem - .getActionProvider(); - mSharePanoramaActionProvider.setOnShareTargetSelectedListener( - mShareTargetSelectedListener); - mSharePanoramaActionProvider.setShareHistoryFileName("panorama_share_history.xml"); - } - mShareMenuItem = menu.findItem(R.id.action_share); - if (mShareMenuItem != null) { - mShareActionProvider = (ShareActionProvider) mShareMenuItem - .getActionProvider(); - mShareActionProvider.setOnShareTargetSelectedListener( - mShareTargetSelectedListener); - mShareActionProvider.setShareHistoryFileName("share_history.xml"); - } - return true; - } - - @Override - public void onDestroyActionMode(ActionMode mode) { - mSelectionManager.leaveSelectionMode(); - } - - private ArrayList<MediaObject> getSelectedMediaObjects(JobContext jc) { - ArrayList<Path> unexpandedPaths = mSelectionManager.getSelected(false); - if (unexpandedPaths.isEmpty()) { - // This happens when starting selection mode from overflow menu - // (instead of long press a media object) - return null; - } - ArrayList<MediaObject> selected = new ArrayList<MediaObject>(); - DataManager manager = mActivity.getDataManager(); - for (Path path : unexpandedPaths) { - if (jc.isCancelled()) { - return null; - } - selected.add(manager.getMediaObject(path)); - } - - return selected; - } - // Menu options are determined by selection set itself. - // We cannot expand it because MenuExecuter executes it based on - // the selection set instead of the expanded result. - // e.g. LocalImage can be rotated but collections of them (LocalAlbum) can't. - private int computeMenuOptions(ArrayList<MediaObject> selected) { - int operation = MediaObject.SUPPORT_ALL; - int type = 0; - for (MediaObject mediaObject: selected) { - int support = mediaObject.getSupportedOperations(); - type |= mediaObject.getMediaType(); - operation &= support; - } - - switch (selected.size()) { - case 1: - final String mimeType = MenuExecutor.getMimeType(type); - if (!GalleryUtils.isEditorAvailable(mActivity, mimeType)) { - operation &= ~MediaObject.SUPPORT_EDIT; - } - break; - default: - operation &= SUPPORT_MULTIPLE_MASK; - } - - return operation; - } - - @TargetApi(ApiHelper.VERSION_CODES.JELLY_BEAN) - private void setNfcBeamPushUris(Uri[] uris) { - if (mNfcAdapter != null && ApiHelper.HAS_SET_BEAM_PUSH_URIS) { - mNfcAdapter.setBeamPushUrisCallback(null, mActivity); - mNfcAdapter.setBeamPushUris(uris, mActivity); - } - } - - // Share intent needs to expand the selection set so we can get URI of - // each media item - private Intent computePanoramaSharingIntent(JobContext jc, int maxItems) { - ArrayList<Path> expandedPaths = mSelectionManager.getSelected(true, maxItems); - if (expandedPaths == null || expandedPaths.size() == 0) { - return new Intent(); - } - final ArrayList<Uri> uris = new ArrayList<Uri>(); - DataManager manager = mActivity.getDataManager(); - final Intent intent = new Intent(); - for (Path path : expandedPaths) { - if (jc.isCancelled()) return null; - uris.add(manager.getContentUri(path)); - } - - final int size = uris.size(); - if (size > 0) { - if (size > 1) { - intent.setAction(Intent.ACTION_SEND_MULTIPLE); - intent.setType(GalleryUtils.MIME_TYPE_PANORAMA360); - intent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris); - } else { - intent.setAction(Intent.ACTION_SEND); - intent.setType(GalleryUtils.MIME_TYPE_PANORAMA360); - intent.putExtra(Intent.EXTRA_STREAM, uris.get(0)); - } - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - } - - return intent; - } - - private Intent computeSharingIntent(JobContext jc, int maxItems) { - ArrayList<Path> expandedPaths = mSelectionManager.getSelected(true, maxItems); - if (expandedPaths == null || expandedPaths.size() == 0) { - setNfcBeamPushUris(null); - return new Intent(); - } - final ArrayList<Uri> uris = new ArrayList<Uri>(); - DataManager manager = mActivity.getDataManager(); - int type = 0; - final Intent intent = new Intent(); - for (Path path : expandedPaths) { - if (jc.isCancelled()) return null; - int support = manager.getSupportedOperations(path); - type |= manager.getMediaType(path); - - if ((support & MediaObject.SUPPORT_SHARE) != 0) { - uris.add(manager.getContentUri(path)); - } - } - - final int size = uris.size(); - if (size > 0) { - final String mimeType = MenuExecutor.getMimeType(type); - if (size > 1) { - intent.setAction(Intent.ACTION_SEND_MULTIPLE).setType(mimeType); - intent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris); - } else { - intent.setAction(Intent.ACTION_SEND).setType(mimeType); - intent.putExtra(Intent.EXTRA_STREAM, uris.get(0)); - } - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - setNfcBeamPushUris(uris.toArray(new Uri[uris.size()])); - } else { - setNfcBeamPushUris(null); - } - - return intent; - } - - public void updateSupportedOperation(Path path, boolean selected) { - // TODO: We need to improve the performance - updateSupportedOperation(); - } - - public void updateSupportedOperation() { - // Interrupt previous unfinished task, mMenuTask is only accessed in main thread - if (mMenuTask != null) mMenuTask.cancel(); - - updateSelectionMenu(); - - // Disable share actions until share intent is in good shape - if (mSharePanoramaMenuItem != null) mSharePanoramaMenuItem.setEnabled(false); - if (mShareMenuItem != null) mShareMenuItem.setEnabled(false); - - // Generate sharing intent and update supported operations in the background - // The task can take a long time and be canceled in the mean time. - mMenuTask = mActivity.getThreadPool().submit(new Job<Void>() { - @Override - public Void run(final JobContext jc) { - // Pass1: Deal with unexpanded media object list for menu operation. - ArrayList<MediaObject> selected = getSelectedMediaObjects(jc); - if (selected == null) { - mMainHandler.post(new Runnable() { - @Override - public void run() { - mMenuTask = null; - if (jc.isCancelled()) return; - // Disable all the operations when no item is selected - MenuExecutor.updateMenuOperation(mMenu, 0); - } - }); - return null; - } - final int operation = computeMenuOptions(selected); - if (jc.isCancelled()) { - return null; - } - int numSelected = selected.size(); - final boolean canSharePanoramas = - numSelected < MAX_SELECTED_ITEMS_FOR_PANORAMA_SHARE_INTENT; - final boolean canShare = - numSelected < MAX_SELECTED_ITEMS_FOR_SHARE_INTENT; - - final GetAllPanoramaSupports supportCallback = canSharePanoramas ? - new GetAllPanoramaSupports(selected, jc) - : null; - - // Pass2: Deal with expanded media object list for sharing operation. - final Intent share_panorama_intent = canSharePanoramas ? - computePanoramaSharingIntent(jc, MAX_SELECTED_ITEMS_FOR_PANORAMA_SHARE_INTENT) - : new Intent(); - final Intent share_intent = canShare ? - computeSharingIntent(jc, MAX_SELECTED_ITEMS_FOR_SHARE_INTENT) - : new Intent(); - - if (canSharePanoramas) { - supportCallback.waitForPanoramaSupport(); - } - if (jc.isCancelled()) { - return null; - } - mMainHandler.post(new Runnable() { - @Override - public void run() { - mMenuTask = null; - if (jc.isCancelled()) return; - MenuExecutor.updateMenuOperation(mMenu, operation); - MenuExecutor.updateMenuForPanorama(mMenu, - canSharePanoramas && supportCallback.mAllPanorama360, - canSharePanoramas && supportCallback.mHasPanorama360); - if (mSharePanoramaMenuItem != null) { - mSharePanoramaMenuItem.setEnabled(true); - if (canSharePanoramas && supportCallback.mAllPanorama360) { - mShareMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER); - mShareMenuItem.setTitle( - mActivity.getResources().getString(R.string.share_as_photo)); - } else { - mSharePanoramaMenuItem.setVisible(false); - mShareMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); - mShareMenuItem.setTitle( - mActivity.getResources().getString(R.string.share)); - } - mSharePanoramaActionProvider.setShareIntent(share_panorama_intent); - } - if (mShareMenuItem != null) { - mShareMenuItem.setEnabled(canShare); - mShareActionProvider.setShareIntent(share_intent); - } - } - }); - return null; - } - }); - } - - public void pause() { - if (mMenuTask != null) { - mMenuTask.cancel(); - mMenuTask = null; - } - mMenuExecutor.pause(); - } - - public void destroy() { - mMenuExecutor.destroy(); - } - - public void resume() { - if (mSelectionManager.inSelectionMode()) updateSupportedOperation(); - mMenuExecutor.resume(); - } -} |