diff options
Diffstat (limited to 'src/com/android/gallery3d/ui/ActionModeHandler.java')
-rw-r--r-- | src/com/android/gallery3d/ui/ActionModeHandler.java | 246 |
1 files changed, 246 insertions, 0 deletions
diff --git a/src/com/android/gallery3d/ui/ActionModeHandler.java b/src/com/android/gallery3d/ui/ActionModeHandler.java new file mode 100644 index 000000000..6c81a3f6a --- /dev/null +++ b/src/com/android/gallery3d/ui/ActionModeHandler.java @@ -0,0 +1,246 @@ +/* + * 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 com.android.gallery3d.R; +import com.android.gallery3d.app.GalleryActionBar; +import com.android.gallery3d.app.GalleryActivity; +import com.android.gallery3d.common.Utils; +import com.android.gallery3d.data.DataManager; +import com.android.gallery3d.data.MediaObject; +import com.android.gallery3d.data.Path; +import com.android.gallery3d.ui.CustomMenu.DropDownMenu; +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 android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.os.Handler; +import android.view.ActionMode; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.View; +import android.widget.Button; +import android.widget.PopupMenu.OnMenuItemClickListener; +import android.widget.ShareActionProvider; + +import java.util.ArrayList; + +public class ActionModeHandler implements ActionMode.Callback { + private static final String TAG = "ActionModeHandler"; + private static final int SUPPORT_MULTIPLE_MASK = MediaObject.SUPPORT_DELETE + | MediaObject.SUPPORT_ROTATE | MediaObject.SUPPORT_SHARE + | MediaObject.SUPPORT_CACHE | MediaObject.SUPPORT_IMPORT; + + public interface ActionModeListener { + public boolean onActionItemClicked(MenuItem item); + } + + private final GalleryActivity mActivity; + private final MenuExecutor mMenuExecutor; + private final SelectionManager mSelectionManager; + private Menu mMenu; + private DropDownMenu mSelectionMenu; + private ActionModeListener mListener; + private Future<?> mMenuTask; + private Handler mMainHandler; + private ShareActionProvider mShareActionProvider; + + public ActionModeHandler( + GalleryActivity activity, SelectionManager selectionManager) { + mActivity = Utils.checkNotNull(activity); + mSelectionManager = Utils.checkNotNull(selectionManager); + mMenuExecutor = new MenuExecutor(activity, selectionManager); + mMainHandler = new Handler(activity.getMainLooper()); + } + + public ActionMode startActionMode() { + Activity a = (Activity) mActivity; + final ActionMode actionMode = a.startActionMode(this); + CustomMenu customMenu = new CustomMenu(a); + View customView = LayoutInflater.from(a).inflate( + R.layout.action_mode, null); + actionMode.setCustomView(customView); + mSelectionMenu = customMenu.addDropDownMenu( + (Button) customView.findViewById(R.id.selection_menu), + R.menu.selection); + customMenu.setOnMenuItemClickListener(new OnMenuItemClickListener() { + public boolean onMenuItemClick(MenuItem item) { + return onActionItemClicked(actionMode, item); + } + }); + return actionMode; + } + + public void setTitle(String title) { + mSelectionMenu.setTitle(title); + } + + public void setActionModeListener(ActionModeListener listener) { + mListener = listener; + } + + public boolean onActionItemClicked(ActionMode mode, MenuItem item) { + boolean result; + if (mListener != null) { + result = mListener.onActionItemClicked(item); + if (result) { + mSelectionManager.leaveSelectionMode(); + return result; + } + } + ProgressListener listener = null; + if (item.getItemId() == R.id.action_import) { + listener = new ImportCompleteListener(mActivity); + } + result = mMenuExecutor.onMenuClicked(item, listener); + if (item.getItemId() == R.id.action_select_all) { + updateSupportedOperation(); + + // For clients who call SelectionManager.selectAll() directly, we need to ensure the + // menu status is consistent with selection manager. + item = mSelectionMenu.findItem(R.id.action_select_all); + if (item != null) { + if (mSelectionManager.inSelectAllMode()) { + item.setChecked(true); + item.setTitle(R.string.deselect_all); + } else { + item.setChecked(false); + item.setTitle(R.string.select_all); + } + } + } + return result; + } + + public boolean onCreateActionMode(ActionMode mode, Menu menu) { + MenuInflater inflater = mode.getMenuInflater(); + inflater.inflate(R.menu.operation, menu); + + mShareActionProvider = GalleryActionBar.initializeShareActionProvider(menu); + + mMenu = menu; + return true; + } + + public void onDestroyActionMode(ActionMode mode) { + mSelectionManager.leaveSelectionMode(); + } + + public boolean onPrepareActionMode(ActionMode mode, Menu menu) { + return true; + } + + private void updateMenuOptionsAndSharingIntent(JobContext jc) { + ArrayList<Path> paths = mSelectionManager.getSelected(true); + if (paths.size() == 0) return; + + int operation = MediaObject.SUPPORT_ALL; + DataManager manager = mActivity.getDataManager(); + final ArrayList<Uri> uris = new ArrayList<Uri>(); + int type = 0; + for (Path path : paths) { + if (jc.isCancelled()) return; + int support = manager.getSupportedOperations(path); + type |= manager.getMediaType(path); + operation &= support; + if ((support & MediaObject.SUPPORT_SHARE) != 0) { + uris.add(manager.getContentUri(path)); + } + } + final Intent intent = new Intent(); + final String mimeType = MenuExecutor.getMimeType(type); + + if (paths.size() == 1) { + if (!GalleryUtils.isEditorAvailable((Context) mActivity, mimeType)) { + operation &= ~MediaObject.SUPPORT_EDIT; + } + } else { + operation &= SUPPORT_MULTIPLE_MASK; + } + + + Log.v(TAG, "Sharing intent MIME type=" + mimeType + ", uri size = "+ uris.size()); + if (uris.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.setType(mimeType); + + final int supportedOperation = operation; + + mMainHandler.post(new Runnable() { + @Override + public void run() { + mMenuTask = null; + MenuExecutor.updateMenuOperation(mMenu, supportedOperation); + + if (mShareActionProvider != null) { + Log.v(TAG, "Sharing intent is ready: action = " + intent.getAction()); + mShareActionProvider.setShareIntent(intent); + } + } + }); + } + + public void updateSupportedOperation(Path path, boolean selected) { + // TODO: We need to improve the performance + updateSupportedOperation(); + } + + public void updateSupportedOperation() { + if (mMenuTask != null) { + mMenuTask.cancel(); + } + + // Disable share action until share intent is in good shape + if (mShareActionProvider != null) { + Log.v(TAG, "Disable sharing until intent is ready"); + mShareActionProvider.setShareIntent(null); + } + + // Generate sharing intent and update supported operations in the background + mMenuTask = mActivity.getThreadPool().submit(new Job<Void>() { + public Void run(JobContext jc) { + updateMenuOptionsAndSharingIntent(jc); + return null; + } + }); + } + + public void pause() { + if (mMenuTask != null) { + mMenuTask.cancel(); + mMenuTask = null; + } + mMenuExecutor.pause(); + } + + public void resume() { + updateSupportedOperation(); + } +} |