| 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;
|
| + }
|
| +}
|
|
|