Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(405)

Unified Diff: content/public/android/java/src/org/chromium/content/browser/SelectActionModeCallback.java

Issue 10828098: Upstreaming Select Action (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Oli's and Min's nits fixed Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/public/android/java/src/org/chromium/content/browser/SelectActionModeCallback.java
diff --git a/content/public/android/java/src/org/chromium/content/browser/SelectActionModeCallback.java b/content/public/android/java/src/org/chromium/content/browser/SelectActionModeCallback.java
new file mode 100644
index 0000000000000000000000000000000000000000..ba7c4e15d865093d39807ebcc0138873f0f815b1
--- /dev/null
+++ b/content/public/android/java/src/org/chromium/content/browser/SelectActionModeCallback.java
@@ -0,0 +1,258 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.content.browser;
+
+import android.app.SearchManager;
+import android.content.ClipboardManager;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.res.TypedArray;
+import android.provider.Browser;
+import android.text.TextUtils;
+import android.view.ActionMode;
+import android.view.Menu;
+import android.view.MenuItem;
+
+import org.chromium.content.app.AppResource;
+
+/**
+ * An ActionMode.Callback for in-page selection. This class handles both the editable and
+ * non-editable cases.
+ */
+public class SelectActionModeCallback implements ActionMode.Callback {
+ private static final int SELECT_ALL_ATTR_INDEX = 0;
+ private static final int CUT_ATTR_INDEX = 1;
+ private static final int COPY_ATTR_INDEX = 2;
+ private static final int PASTE_ATTR_INDEX = 3;
+ private static final int[] ACTION_MODE_ATTRS = {
+ android.R.attr.actionModeSelectAllDrawable,
+ android.R.attr.actionModeCutDrawable,
+ android.R.attr.actionModeCopyDrawable,
+ android.R.attr.actionModePasteDrawable,
+ };
+
+ private static final int ID_SELECTALL = 0;
+ private static final int ID_COPY = 1;
+ private static final int ID_SHARE = 2;
+ private static final int ID_SEARCH = 3;
+ private static final int ID_CUT = 4;
+ private static final int ID_PASTE = 5;
+
+ /**
+ * An interface to retrieve information about the current selection, and also to perform
+ * actions based on the selection or when the action bar is dismissed.
+ */
+ public interface ActionHandler {
+ /**
+ * Perform a select all action.
+ * @return true iff the action was successful.
+ */
+ boolean selectAll();
+
+ /**
+ * Perform a copy (to clipboard) action.
+ * @return true iff the action was successful.
+ */
+ boolean copy();
+
+ /**
+ * Perform a cut (to clipboard) action.
+ * @return true iff the action was successful.
+ */
+ boolean cut();
+
+ /**
+ * Perform a paste action.
+ * @return true iff the action was successful.
+ */
+ boolean paste();
+
+ /**
+ * @return true iff the current selection is editable (e.g. text within an input field).
+ */
+ boolean isSelectionEditable();
+
+ /**
+ * @return the currently selected text String.
+ */
+ String getSelectedText();
+
+ /**
+ * Called when the onDestroyActionMode of the SelectActionmodeCallback is called.
+ */
+ void onDestroyActionMode();
+ }
+
+ private Context mContext;
+ private ActionHandler mActionHandler;
+ private final boolean mIncognito;
+ private boolean mEditable;
+
+ protected SelectActionModeCallback(
+ Context context, ActionHandler actionHandler, boolean incognito) {
+ mContext = context;
+ mActionHandler = actionHandler;
+ mIncognito = incognito;
+ }
+
+ protected Context getContext() {
+ return mContext;
+ }
+
+ @Override
+ public boolean onCreateActionMode(ActionMode mode, Menu menu) {
+ mode.setSubtitle(null);
+ mEditable = mActionHandler.isSelectionEditable();
+ createActionMenu(mode, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
+ boolean isEditableNow = mActionHandler.isSelectionEditable();
+ if (mEditable != isEditableNow) {
+ mEditable = isEditableNow;
+ menu.clear();
+ createActionMenu(mode, menu);
+ return true;
+ }
+ return false;
+ }
+
+ private void createActionMenu(ActionMode mode, Menu menu) {
+ TypedArray styledAttributes = getContext().obtainStyledAttributes(ACTION_MODE_ATTRS);
+
+ menu.add(Menu.NONE, ID_SELECTALL, Menu.NONE, android.R.string.selectAll).
+ setAlphabeticShortcut('a').
+ setIcon(styledAttributes.getResourceId(SELECT_ALL_ATTR_INDEX, 0)).
+ setShowAsAction(
+ MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
+
+ if (mEditable) {
+ menu.add(Menu.NONE, ID_CUT, Menu.NONE, android.R.string.cut).
+ setIcon(styledAttributes.getResourceId(CUT_ATTR_INDEX, 0)).
+ setAlphabeticShortcut('x').
+ setShowAsAction(
+ MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
+ }
+
+ menu.add(Menu.NONE, ID_COPY, Menu.NONE, android.R.string.copy).
+ setIcon(styledAttributes.getResourceId(COPY_ATTR_INDEX, 0)).
+ setAlphabeticShortcut('c').
+ setShowAsAction(
+ MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
+
+ if (mEditable && canPaste()) {
+ menu.add(Menu.NONE, ID_PASTE, Menu.NONE, android.R.string.paste).
+ setIcon(styledAttributes.getResourceId(PASTE_ATTR_INDEX, 0)).
+ setAlphabeticShortcut('v').
+ setShowAsAction(
+ MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
+ }
+
+ if (!mEditable) {
+ if (isShareHandlerAvailable()) {
+ assert AppResource.STRING_ACTION_BAR_SHARE != 0;
+ assert AppResource.DRAWABLE_ICON_ACTION_BAR_SHARE != 0;
+ menu.add(Menu.NONE, ID_SHARE, Menu.NONE, AppResource.STRING_ACTION_BAR_SHARE).
+ setIcon(AppResource.DRAWABLE_ICON_ACTION_BAR_SHARE).
+ setShowAsAction(
+ MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
+ }
+
+ if (!mIncognito && isWebSearchAvailable()) {
+ assert AppResource.STRING_ACTION_BAR_WEB_SEARCH != 0;
+ assert AppResource.DRAWABLE_ICON_ACTION_BAR_WEB_SEARCH != 0;
+ menu.add(Menu.NONE, ID_SEARCH, Menu.NONE,
+ AppResource.STRING_ACTION_BAR_WEB_SEARCH).
+ setIcon(AppResource.DRAWABLE_ICON_ACTION_BAR_WEB_SEARCH).
+ setShowAsAction(
+ MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
+ }
+ }
+
+ styledAttributes.recycle();
+ }
+
+ @Override
+ public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
+ String selection = mActionHandler.getSelectedText();
+ switch(item.getItemId()) {
+ case ID_SELECTALL:
+ mActionHandler.selectAll();
+ break;
+ case ID_CUT:
+ mActionHandler.cut();
+ break;
+ case ID_COPY:
+ mActionHandler.copy();
+ mode.finish();
+ break;
+ case ID_PASTE:
+ mActionHandler.paste();
+ break;
+ case ID_SHARE:
+ if (!TextUtils.isEmpty(selection)) {
+ Intent send = new Intent(Intent.ACTION_SEND);
+ send.setType("text/plain");
+ send.putExtra(Intent.EXTRA_TEXT, selection);
+ try {
+ assert AppResource.STRING_ACTION_BAR_SHARE != 0;
+ Intent i = Intent.createChooser(send, getContext().getString(
+ AppResource.STRING_ACTION_BAR_SHARE));
+ i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ getContext().startActivity(i);
+ } catch (android.content.ActivityNotFoundException ex) {
+ // If no app handles it, do nothing.
+ }
+ }
+ mode.finish();
+ break;
+ case ID_SEARCH:
+ if (!TextUtils.isEmpty(selection)) {
+ Intent i = new Intent(Intent.ACTION_WEB_SEARCH);
+ i.putExtra(SearchManager.EXTRA_NEW_SEARCH, true);
+ i.putExtra(SearchManager.QUERY, selection);
+ i.putExtra(Browser.EXTRA_APPLICATION_ID, getContext().getPackageName());
+ try {
+ getContext().startActivity(i);
+ } catch (android.content.ActivityNotFoundException ex) {
+ // If no app handles it, do nothing.
+ }
+ }
+ mode.finish();
+ break;
+ default:
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public void onDestroyActionMode(ActionMode mode) {
+ mActionHandler.onDestroyActionMode();
+ }
+
+ private boolean canPaste() {
+ ClipboardManager clipMgr = (ClipboardManager)
+ getContext().getSystemService(Context.CLIPBOARD_SERVICE);
+ return clipMgr.hasPrimaryClip();
+ }
+
+ private boolean isShareHandlerAvailable() {
+ Intent intent = new Intent(Intent.ACTION_SEND);
+ intent.setType("text/plain");
+ return getContext().getPackageManager()
+ .queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY).size() > 0;
+ }
+
+ private boolean isWebSearchAvailable() {
+ Intent intent = new Intent(Intent.ACTION_WEB_SEARCH);
+ intent.putExtra(SearchManager.EXTRA_NEW_SEARCH, true);
+ return getContext().getPackageManager()
+ .queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY).size() > 0;
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698