summaryrefslogtreecommitdiffstats
path: root/src/com/android/photos/MultiChoiceManager.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/photos/MultiChoiceManager.java')
-rw-r--r--src/com/android/photos/MultiChoiceManager.java295
1 files changed, 295 insertions, 0 deletions
diff --git a/src/com/android/photos/MultiChoiceManager.java b/src/com/android/photos/MultiChoiceManager.java
new file mode 100644
index 000000000..49519ca63
--- /dev/null
+++ b/src/com/android/photos/MultiChoiceManager.java
@@ -0,0 +1,295 @@
+/*
+ * Copyright (C) 2013 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.photos;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.provider.MediaStore.Files.FileColumns;
+import android.util.SparseBooleanArray;
+import android.view.ActionMode;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.widget.AbsListView.MultiChoiceModeListener;
+import android.widget.ShareActionProvider;
+import android.widget.ShareActionProvider.OnShareTargetSelectedListener;
+
+import com.android.gallery3d.R;
+import com.android.gallery3d.app.TrimVideo;
+import com.android.gallery3d.data.MediaObject;
+import com.android.gallery3d.filtershow.FilterShowActivity;
+import com.android.gallery3d.filtershow.crop.CropActivity;
+import com.android.gallery3d.util.GalleryUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class MultiChoiceManager implements MultiChoiceModeListener,
+ OnShareTargetSelectedListener, SelectionManager.SelectedUriSource {
+
+ public interface Provider {
+ public MultiChoiceManager getMultiChoiceManager();
+ }
+
+ public interface Delegate {
+ public SparseBooleanArray getSelectedItemPositions();
+ public int getSelectedItemCount();
+ public int getItemMediaType(Object item);
+ public int getItemSupportedOperations(Object item);
+ public ArrayList<Uri> getSubItemUrisForItem(Object item);
+ public Uri getItemUri(Object item);
+ public Object getItemAtPosition(int position);
+ public Object getPathForItemAtPosition(int position);
+ public void deleteItemWithPath(Object itemPath);
+ }
+
+ private SelectionManager mSelectionManager;
+ private ShareActionProvider mShareActionProvider;
+ private ActionMode mActionMode;
+ private Context mContext;
+ private Delegate mDelegate;
+
+ private ArrayList<Uri> mSelectedShareableUrisArray = new ArrayList<Uri>();
+
+ public MultiChoiceManager(Activity activity) {
+ mContext = activity;
+ mSelectionManager = new SelectionManager(activity);
+ }
+
+ public void setDelegate(Delegate delegate) {
+ if (mDelegate == delegate) {
+ return;
+ }
+ if (mActionMode != null) {
+ mActionMode.finish();
+ }
+ mDelegate = delegate;
+ }
+
+ @Override
+ public ArrayList<Uri> getSelectedShareableUris() {
+ return mSelectedShareableUrisArray;
+ }
+
+ private void updateSelectedTitle(ActionMode mode) {
+ int count = mDelegate.getSelectedItemCount();
+ mode.setTitle(mContext.getResources().getQuantityString(
+ R.plurals.number_of_items_selected, count, count));
+ }
+
+ private String getItemMimetype(Object item) {
+ int type = mDelegate.getItemMediaType(item);
+ if (type == FileColumns.MEDIA_TYPE_IMAGE) {
+ return GalleryUtils.MIME_TYPE_IMAGE;
+ } else if (type == FileColumns.MEDIA_TYPE_VIDEO) {
+ return GalleryUtils.MIME_TYPE_VIDEO;
+ } else {
+ return GalleryUtils.MIME_TYPE_ALL;
+ }
+ }
+
+ @Override
+ public void onItemCheckedStateChanged(ActionMode mode, int position, long id,
+ boolean checked) {
+ updateSelectedTitle(mode);
+ Object item = mDelegate.getItemAtPosition(position);
+
+ int supported = mDelegate.getItemSupportedOperations(item);
+
+ if ((supported & MediaObject.SUPPORT_SHARE) > 0) {
+ ArrayList<Uri> subItems = mDelegate.getSubItemUrisForItem(item);
+ if (checked) {
+ mSelectedShareableUrisArray.addAll(subItems);
+ } else {
+ mSelectedShareableUrisArray.removeAll(subItems);
+ }
+ }
+
+ mSelectionManager.onItemSelectedStateChanged(mShareActionProvider,
+ mDelegate.getItemMediaType(item),
+ supported,
+ checked);
+ updateActionItemVisibilities(mode.getMenu(),
+ mSelectionManager.getSupportedOperations());
+ }
+
+ private void updateActionItemVisibilities(Menu menu, int supportedOperations) {
+ MenuItem editItem = menu.findItem(R.id.menu_edit);
+ MenuItem deleteItem = menu.findItem(R.id.menu_delete);
+ MenuItem shareItem = menu.findItem(R.id.menu_share);
+ MenuItem cropItem = menu.findItem(R.id.menu_crop);
+ MenuItem trimItem = menu.findItem(R.id.menu_trim);
+ MenuItem muteItem = menu.findItem(R.id.menu_mute);
+ MenuItem setAsItem = menu.findItem(R.id.menu_set_as);
+
+ editItem.setVisible((supportedOperations & MediaObject.SUPPORT_EDIT) > 0);
+ deleteItem.setVisible((supportedOperations & MediaObject.SUPPORT_DELETE) > 0);
+ shareItem.setVisible((supportedOperations & MediaObject.SUPPORT_SHARE) > 0);
+ cropItem.setVisible((supportedOperations & MediaObject.SUPPORT_CROP) > 0);
+ trimItem.setVisible((supportedOperations & MediaObject.SUPPORT_TRIM) > 0);
+ muteItem.setVisible((supportedOperations & MediaObject.SUPPORT_MUTE) > 0);
+ setAsItem.setVisible((supportedOperations & MediaObject.SUPPORT_SETAS) > 0);
+ }
+
+ @Override
+ public boolean onCreateActionMode(ActionMode mode, Menu menu) {
+ mSelectionManager.setSelectedUriSource(this);
+ mActionMode = mode;
+ MenuInflater inflater = mode.getMenuInflater();
+ inflater.inflate(R.menu.gallery_multiselect, menu);
+ MenuItem menuItem = menu.findItem(R.id.menu_share);
+ mShareActionProvider = (ShareActionProvider) menuItem.getActionProvider();
+ mShareActionProvider.setOnShareTargetSelectedListener(this);
+ updateSelectedTitle(mode);
+ return true;
+ }
+
+ @Override
+ public void onDestroyActionMode(ActionMode mode) {
+ // onDestroyActionMode gets called when the share target was selected,
+ // but apparently before the ArrayList is serialized in the intent
+ // so we can't clear the old one here.
+ mSelectedShareableUrisArray = new ArrayList<Uri>();
+ mSelectionManager.onClearSelection();
+ mSelectionManager.setSelectedUriSource(null);
+ mShareActionProvider = null;
+ mActionMode = null;
+ }
+
+ @Override
+ public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
+ updateSelectedTitle(mode);
+ return false;
+ }
+
+ @Override
+ public boolean onShareTargetSelected(ShareActionProvider provider, Intent intent) {
+ mActionMode.finish();
+ return false;
+ }
+
+ private static class BulkDeleteTask extends AsyncTask<Void, Void, Void> {
+ private Delegate mDelegate;
+ private List<Object> mPaths;
+
+ public BulkDeleteTask(Delegate delegate, List<Object> paths) {
+ mDelegate = delegate;
+ mPaths = paths;
+ }
+
+ @Override
+ protected Void doInBackground(Void... ignored) {
+ for (Object path : mPaths) {
+ mDelegate.deleteItemWithPath(path);
+ }
+ return null;
+ }
+ }
+
+ @Override
+ public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
+ int actionItemId = item.getItemId();
+ switch (actionItemId) {
+ case R.id.menu_delete:
+ BulkDeleteTask deleteTask = new BulkDeleteTask(mDelegate,
+ getPathsForSelectedItems());
+ deleteTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ mode.finish();
+ return true;
+ case R.id.menu_edit:
+ case R.id.menu_crop:
+ case R.id.menu_trim:
+ case R.id.menu_mute:
+ case R.id.menu_set_as:
+ singleItemAction(getSelectedItem(), actionItemId);
+ mode.finish();
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ private void singleItemAction(Object item, int actionItemId) {
+ Intent intent = new Intent();
+ String mime = getItemMimetype(item);
+ Uri uri = mDelegate.getItemUri(item);
+ switch (actionItemId) {
+ case R.id.menu_edit:
+ intent.setDataAndType(uri, mime)
+ .setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
+ .setAction(Intent.ACTION_EDIT);
+ mContext.startActivity(Intent.createChooser(intent, null));
+ return;
+ case R.id.menu_crop:
+ intent.setDataAndType(uri, mime)
+ .setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
+ .setAction(CropActivity.CROP_ACTION)
+ .setClass(mContext, FilterShowActivity.class);
+ mContext.startActivity(intent);
+ return;
+ case R.id.menu_trim:
+ intent.setData(uri)
+ .setClass(mContext, TrimVideo.class);
+ mContext.startActivity(intent);
+ return;
+ case R.id.menu_mute:
+ /* TODO need a way to get the file path of an item
+ MuteVideo muteVideo = new MuteVideo(filePath,
+ uri, (Activity) mContext);
+ muteVideo.muteInBackground();
+ */
+ return;
+ case R.id.menu_set_as:
+ intent.setDataAndType(uri, mime)
+ .setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
+ .setAction(Intent.ACTION_ATTACH_DATA)
+ .putExtra("mimeType", mime);
+ mContext.startActivity(Intent.createChooser(
+ intent, mContext.getString(R.string.set_as)));
+ return;
+ default:
+ return;
+ }
+ }
+
+ private List<Object> getPathsForSelectedItems() {
+ List<Object> paths = new ArrayList<Object>();
+ SparseBooleanArray selected = mDelegate.getSelectedItemPositions();
+ for (int i = 0; i < selected.size(); i++) {
+ if (selected.valueAt(i)) {
+ paths.add(mDelegate.getPathForItemAtPosition(i));
+ }
+ }
+ return paths;
+ }
+
+ public Object getSelectedItem() {
+ if (mDelegate.getSelectedItemCount() != 1) {
+ return null;
+ }
+ SparseBooleanArray selected = mDelegate.getSelectedItemPositions();
+ for (int i = 0; i < selected.size(); i++) {
+ if (selected.valueAt(i)) {
+ return mDelegate.getItemAtPosition(selected.keyAt(i));
+ }
+ }
+ return null;
+ }
+}