Add ability to copy a single recipient chip.

Fixes b/5143564 implement single chip copy

Change-Id: I598a53a60ba29b99637b2d1633b3884811938317
diff --git a/chips/res/layout/copy_chip_dialog_layout.xml b/chips/res/layout/copy_chip_dialog_layout.xml
new file mode 100644
index 0000000..d5e072d
--- /dev/null
+++ b/chips/res/layout/copy_chip_dialog_layout.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 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.
+-->
+
+<Button xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:text="@string/copy"
+    android:id="@+android:id/button1"
+    android:background="@null"
+    android:layout_gravity="left"/>
\ No newline at end of file
diff --git a/chips/res/values/attrs.xml b/chips/res/values/attrs.xml
index d1e3582..ebf6936 100644
--- a/chips/res/values/attrs.xml
+++ b/chips/res/values/attrs.xml
@@ -23,5 +23,6 @@
     <add-resource type="color" name="chip_selected" />
     <add-resource type="string" name="more_string" />
     <add-resource type="string" name="chips_waiting_for_directory_result" />
+    <add-resource type="string" name="copy" />
     <add-resource type="style" name="RecipientEditTextView" />
 </resources>
diff --git a/chips/res/values/strings.xml b/chips/res/values/strings.xml
index 514615c..c1acaa0 100644
--- a/chips/res/values/strings.xml
+++ b/chips/res/values/strings.xml
@@ -20,4 +20,7 @@
     <!-- Text displayed when there are remote directories not returning results.
          [CHAR LIMIT=50] -->
     <string name="chips_waiting_for_directory_result">Waiting for more contacts</string>
+    <!-- Text displayed when the user long presses on a chip to copy the recipients email address.
+         [CHAR LIMIT=200] -->
+    <string name="copy">Copy email address</string>
 </resources>
diff --git a/chips/src/com/android/ex/chips/RecipientEditTextView.java b/chips/src/com/android/ex/chips/RecipientEditTextView.java
index 8855f83..d67c431 100644
--- a/chips/src/com/android/ex/chips/RecipientEditTextView.java
+++ b/chips/src/com/android/ex/chips/RecipientEditTextView.java
@@ -16,7 +16,12 @@
 
 package com.android.ex.chips;
 
+import android.app.Dialog;
+import android.content.ClipData;
+import android.content.ClipboardManager;
 import android.content.Context;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnDismissListener;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.graphics.Canvas;
@@ -45,6 +50,8 @@
 import android.util.Log;
 import android.view.ActionMode;
 import android.view.ActionMode.Callback;
+import android.view.View.OnClickListener;
+import android.view.GestureDetector;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
 import android.view.Menu;
@@ -73,7 +80,8 @@
  * that use the new Chips UI for addressing a message to recipients.
  */
 public class RecipientEditTextView extends MultiAutoCompleteTextView implements
-        OnItemClickListener, Callback, RecipientAlternatesAdapter.OnCheckedItemChangedListener {
+        OnItemClickListener, Callback, RecipientAlternatesAdapter.OnCheckedItemChangedListener,
+        GestureDetector.OnGestureListener, OnDismissListener, OnClickListener {
 
     private static final String TAG = "RecipientEditTextView";
 
@@ -136,6 +144,15 @@
 
     private boolean mShouldShrink = true;
 
+    // Chip copy fields.
+    private GestureDetector mGestureDetector;
+
+    private Dialog mCopyDialog;
+
+    private int mCopyViewRes;
+
+    private String mCopyAddress;
+
     /**
      * Used with {@link #mAlternatesPopup}. Handles clicks to alternate addresses for a
      * selected chip.
@@ -205,6 +222,7 @@
         };
         mTextWatcher = new RecipientTextWatcher();
         addTextChangedListener(mTextWatcher);
+        mGestureDetector = new GestureDetector(context, this);
     }
 
     @Override
@@ -492,10 +510,29 @@
      * @param alternatesLayout
      * @param chipHeight
      * @param padding Padding around the text in a chip
+     * @param chipFontSize
+     * @param copyViewRes
      */
     public void setChipDimensions(Drawable chipBackground, Drawable chipBackgroundPressed,
             Drawable invalidChip, Drawable chipDelete, Bitmap defaultContact, int moreResource,
             int alternatesLayout, float chipHeight, float padding,
+            float chipFontSize, int copyViewRes) {
+        mChipBackground = chipBackground;
+        mChipBackgroundPressed = chipBackgroundPressed;
+        mChipDelete = chipDelete;
+        mChipPadding = (int) padding;
+        mAlternatesLayout = alternatesLayout;
+        mDefaultContactPhoto = defaultContact;
+        mMoreItem = (TextView) LayoutInflater.from(getContext()).inflate(moreResource, null);
+        mChipHeight = chipHeight;
+        mChipFontSize = chipFontSize;
+        mInvalidChipBackground = invalidChip;
+        mCopyViewRes = copyViewRes;
+    }
+
+    public void setChipDimensions(Drawable chipBackground, Drawable chipBackgroundPressed,
+            Drawable invalidChip, Drawable chipDelete, Bitmap defaultContact, int moreResource,
+            int alternatesLayout, float chipHeight, float padding,
             float chipFontSize) {
         mChipBackground = chipBackground;
         mChipBackgroundPressed = chipBackgroundPressed;
@@ -507,6 +544,7 @@
         mChipHeight = chipHeight;
         mChipFontSize = chipFontSize;
         mInvalidChipBackground = invalidChip;
+        mCopyViewRes = -1;
     }
 
     /**
@@ -963,8 +1001,10 @@
         boolean handled = super.onTouchEvent(event);
         int action = event.getAction();
         boolean chipWasSelected = false;
-
-        if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_DOWN) {
+        if (action == MotionEvent.ACTION_DOWN && mSelectedChip == null) {
+            mGestureDetector.onTouchEvent(event);
+        }
+        if (mCopyDialog == null && action == MotionEvent.ACTION_UP) {
             float x = event.getX();
             float y = event.getY();
             int offset = putOffsetInRange(getOffsetForPosition(x, y));
@@ -1744,4 +1784,74 @@
             return null;
         }
     }
+
+    @Override
+    public boolean onDown(MotionEvent e) {
+        return false;
+    }
+
+    @Override
+    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
+        // Do nothing.
+        return false;
+    }
+
+    @Override
+    public void onLongPress(MotionEvent event) {
+        if (mSelectedChip != null) {
+            return;
+        }
+        float x = event.getX();
+        float y = event.getY();
+        int offset = putOffsetInRange(getOffsetForPosition(x, y));
+        RecipientChip currentChip = findChip(offset);
+        if (currentChip != null) {
+            // Copy the selected chip email address.
+            showCopyDialog(currentChip.getEntry().getDestination());
+        }
+    }
+
+    private void showCopyDialog(final String address) {
+        mCopyAddress = address;
+        mCopyDialog = new Dialog(getContext());
+        mCopyDialog.setTitle(address);
+        mCopyDialog.setContentView(mCopyViewRes);
+        mCopyDialog.setCancelable(true);
+        mCopyDialog.setCanceledOnTouchOutside(true);
+        mCopyDialog.findViewById(android.R.id.button1).setOnClickListener(this);
+        mCopyDialog.setOnDismissListener(this);
+        mCopyDialog.show();
+    }
+
+    @Override
+    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
+        // Do nothing.
+        return false;
+    }
+
+    @Override
+    public void onShowPress(MotionEvent e) {
+        // Do nothing.
+    }
+
+    @Override
+    public boolean onSingleTapUp(MotionEvent e) {
+        // Do nothing.
+        return false;
+    }
+
+    @Override
+    public void onDismiss(DialogInterface dialog) {
+        mCopyAddress = null;
+        mCopyDialog = null;
+    }
+
+    @Override
+    public void onClick(View v) {
+        // Copy this to the clipboard.
+        ClipboardManager clipboard = (ClipboardManager) getContext().getSystemService(
+                Context.CLIPBOARD_SERVICE);
+        clipboard.setPrimaryClip(ClipData.newPlainText("", mCopyAddress));
+        mCopyDialog.dismiss();
+    }
 }