Make the space part of the replacement image span.

This eliminates the need for manually adding extra spaces at the end.
This also fixes bug:5323325 Chips sometimes have no spacing between them on deleting
since now the space is ALWAYS deleted when the chip is deleted.

Change-Id: I8923940a070bcc1ce6894af3efa1449e98aa4830
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 9127f7c..d00e36a 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -24,5 +24,6 @@
         <item name="android:dropDownVerticalOffset">-6dip</item>
         <item name="android:dropDownHorizontalOffset">0dip</item>
         <item name="android:minHeight">48dip</item>
+        <item name="android:lineSpacingExtra">4dip</item>
     </style>
 </resources>
\ No newline at end of file
diff --git a/src/com/android/ex/chips/RecipientChip.java b/src/com/android/ex/chips/RecipientChip.java
index 41d950f..29ee4d0 100644
--- a/src/com/android/ex/chips/RecipientChip.java
+++ b/src/com/android/ex/chips/RecipientChip.java
@@ -16,6 +16,7 @@
 
 package com.android.ex.chips;
 
+import android.graphics.Paint;
 import android.graphics.drawable.Drawable;
 import android.text.TextUtils;
 import android.text.style.DynamicDrawableSpan;
@@ -41,7 +42,7 @@
     private CharSequence mOriginalText;
 
     public RecipientChip(Drawable drawable, RecipientEntry entry, int offset) {
-        super(drawable, DynamicDrawableSpan.ALIGN_BASELINE);
+        super(drawable, DynamicDrawableSpan.ALIGN_BOTTOM);
         mDisplay = entry.getDisplayName();
         mValue = entry.getDestination().trim();
         mContactId = entry.getContactId();
@@ -100,13 +101,16 @@
     }
 
     public void setOriginalText(String text) {
-        if (!TextUtils.isEmpty(text)) {
-            text = text.trim();
-        }
         mOriginalText = text;
     }
 
     public CharSequence getOriginalText() {
         return !TextUtils.isEmpty(mOriginalText) ? mOriginalText : mEntry.getDestination();
     }
+
+    @Override
+    public int getSize(Paint paint, CharSequence text, int start, int end,
+            Paint.FontMetricsInt fm) {
+        return super.getSize(paint, text, start, end, fm) + (int) paint.measureText(" ");
+    }
 }
diff --git a/src/com/android/ex/chips/RecipientEditTextView.java b/src/com/android/ex/chips/RecipientEditTextView.java
index 01c8d77..5a777b9 100644
--- a/src/com/android/ex/chips/RecipientEditTextView.java
+++ b/src/com/android/ex/chips/RecipientEditTextView.java
@@ -434,8 +434,9 @@
      * Get the background drawable for a RecipientChip.
      */
     public Drawable getChipBackground(RecipientEntry contact) {
-        return (mValidator != null && mValidator.isValid(contact.getDestination())) ?
-                mChipBackground : mInvalidChipBackground;
+        String destination = contact.getDestination();
+        return (mValidator != null && !TextUtils.isEmpty(destination) && mValidator
+                .isValid(destination)) ? mChipBackground : mInvalidChipBackground;
     }
 
     private Bitmap createUnselectedChip(RecipientEntry contact, TextPaint paint, Layout layout) {
@@ -739,7 +740,7 @@
         if (entry != null) {
             String destText = createDisplayText(entry);
             // Always leave a blank space at the end of a chip.
-            int textLength = destText.length() - 1;
+            int textLength = destText.length();
             SpannableString chipText = new SpannableString(destText);
             int end = getSelectionEnd();
             int start = mTokenizer.findTokenStart(getText(), end);
@@ -948,7 +949,7 @@
             if (editable.length() > tokenEnd && editable.charAt(tokenEnd) == ',') {
                 tokenEnd++;
             }
-            String text = editable.toString().substring(start, tokenEnd).trim();
+            String text = editable.toString().substring(start, tokenEnd);
             clearComposingText();
             if (text != null && text.length() > 0 && !text.equals(" ")) {
                 RecipientEntry entry = createTokenizedEntry(text);
@@ -1278,7 +1279,7 @@
     private CharSequence createChip(RecipientEntry entry, boolean pressed) {
         String displayText = createDisplayText(entry);
         // Always leave a blank space at the end of a chip.
-        int textLength = displayText.length()-1;
+        int textLength = displayText.length();
         SpannableString chipText = new SpannableString(displayText);
         int end = getSelectionEnd();
         int start = mTokenizer.findTokenStart(getText(), end);
diff --git a/tests/src/com/android/ex/chips/ChipsTest.java b/tests/src/com/android/ex/chips/ChipsTest.java
index f550e96..768e500 100644
--- a/tests/src/com/android/ex/chips/ChipsTest.java
+++ b/tests/src/com/android/ex/chips/ChipsTest.java
@@ -108,9 +108,9 @@
         mEditable = new SpannableStringBuilder();
         mEditable.append(first + extra + second);
         int firstStart = mEditable.toString().indexOf(first);
-        int firstEnd = firstStart + first.trim().length();
+        int firstEnd = firstStart + first.length();
         int secondStart = mEditable.toString().indexOf(second);
-        int secondEnd = secondStart + second.trim().length();
+        int secondEnd = secondStart + second.length();
         mEditable.setSpan(mMockRecips[mMockRecips.length - 2], firstStart, firstEnd, 0);
         mEditable.setSpan(mMockRecips[mMockRecips.length - 1], secondStart, secondEnd, 0);
         view.sanitizeBetween();
@@ -144,11 +144,11 @@
         mEditable.append(first+second+third);
 
         int firstStart = mEditable.toString().indexOf(first);
-        int firstEnd = firstStart + first.trim().length();
+        int firstEnd = firstStart + first.length();
         int secondStart = mEditable.toString().indexOf(second);
-        int secondEnd = secondStart + second.trim().length();
+        int secondEnd = secondStart + second.length();
         int thirdStart = mEditable.toString().indexOf(third);
-        int thirdEnd = thirdStart + third.trim().length();
+        int thirdEnd = thirdStart + third.length();
         mEditable.setSpan(mMockRecips[mMockRecips.length - 3], firstStart, firstEnd, 0);
         mEditable.setSpan(mMockRecips[mMockRecips.length - 2], secondStart, secondEnd, 0);
         mEditable.setSpan(mMockRecips[mMockRecips.length - 1], thirdStart, thirdEnd, 0);
@@ -211,25 +211,25 @@
         mEditable.append(first+second+third+fourth+fifth+sixth+seventh+eigth+ninth+tenth);
 
         int firstStart = mEditable.toString().indexOf(first);
-        int firstEnd = firstStart + first.trim().length();
+        int firstEnd = firstStart + first.length();
         int secondStart = mEditable.toString().indexOf(second);
-        int secondEnd = secondStart + second.trim().length();
+        int secondEnd = secondStart + second.length();
         int thirdStart = mEditable.toString().indexOf(third);
-        int thirdEnd = thirdStart + third.trim().length();
+        int thirdEnd = thirdStart + third.length();
         int fourthStart = mEditable.toString().indexOf(fourth);
-        int fourthEnd = fourthStart + fourth.trim().length();
+        int fourthEnd = fourthStart + fourth.length();
         int fifthStart = mEditable.toString().indexOf(fifth);
-        int fifthEnd = fifthStart + fifth.trim().length();
+        int fifthEnd = fifthStart + fifth.length();
         int sixthStart = mEditable.toString().indexOf(sixth);
-        int sixthEnd = sixthStart + sixth.trim().length();
+        int sixthEnd = sixthStart + sixth.length();
         int seventhStart = mEditable.toString().indexOf(seventh);
-        int seventhEnd = seventhStart + seventh.trim().length();
+        int seventhEnd = seventhStart + seventh.length();
         int eighthStart = mEditable.toString().indexOf(eigth);
-        int eighthEnd = eighthStart + eigth.trim().length();
+        int eighthEnd = eighthStart + eigth.length();
         int ninthStart = mEditable.toString().indexOf(ninth);
-        int ninthEnd = ninthStart + ninth.trim().length();
+        int ninthEnd = ninthStart + ninth.length();
         int tenthStart = mEditable.toString().indexOf(tenth);
-        int tenthEnd = tenthStart + tenth.trim().length();
+        int tenthEnd = tenthStart + tenth.length();
         mEditable.setSpan(mMockRecips[mMockRecips.length - 10], firstStart, firstEnd, 0);
         mEditable.setSpan(mMockRecips[mMockRecips.length - 9], secondStart, secondEnd, 0);
         mEditable.setSpan(mMockRecips[mMockRecips.length - 8], thirdStart, thirdEnd, 0);
@@ -281,11 +281,11 @@
         mEditable.append(first+second+third);
 
         int firstStart = mEditable.toString().indexOf(first);
-        int firstEnd = firstStart + first.trim().length();
+        int firstEnd = firstStart + first.length();
         int secondStart = mEditable.toString().indexOf(second);
-        int secondEnd = secondStart + second.trim().length();
+        int secondEnd = secondStart + second.length();
         int thirdStart = mEditable.toString().indexOf(third);
-        int thirdEnd = thirdStart + third.trim().length();
+        int thirdEnd = thirdStart + third.length();
         mEditable.setSpan(mMockRecips[mMockRecips.length - 3], firstStart, firstEnd, 0);
         mEditable.setSpan(mMockRecips[mMockRecips.length - 2], secondStart, secondEnd, 0);
         mEditable.setSpan(mMockRecips[mMockRecips.length - 1], thirdStart, thirdEnd, 0);
@@ -310,6 +310,51 @@
         assertEquals(mEditable.getSpanStart(moreChip), -1);
     }
 
+    public void testMoreChipDupes() {
+        populateMocks(4);
+        MockRecipientEditTextView view = createViewForTesting();
+        view.setMoreItem(createTestMoreItem());
+        String first = (String) mTokenizer.terminateToken("FIRST");
+        String second = (String) mTokenizer.terminateToken("SECOND");
+        String third = (String) mTokenizer.terminateToken("THIRD");
+        mEditable = new SpannableStringBuilder();
+        mEditable.append(first+second+third+third);
+
+        int firstStart = mEditable.toString().indexOf(first);
+        int firstEnd = firstStart + first.length();
+        int secondStart = mEditable.toString().indexOf(second);
+        int secondEnd = secondStart + second.length();
+        int thirdStart = mEditable.toString().indexOf(third);
+        int thirdEnd = thirdStart + third.length();
+        int thirdNextStart = mEditable.toString().indexOf(third, thirdEnd);
+        int thirdNextEnd = thirdNextStart + third.length();
+        mEditable.setSpan(mMockRecips[mMockRecips.length - 4], firstStart, firstEnd, 0);
+        mEditable.setSpan(mMockRecips[mMockRecips.length - 3], secondStart, secondEnd, 0);
+        mEditable.setSpan(mMockRecips[mMockRecips.length - 2], thirdStart, thirdEnd, 0);
+        mEditable.setSpan(mMockRecips[mMockRecips.length - 1], thirdNextStart, thirdNextEnd, 0);
+
+        view.createMoreChip();
+        assertEquals(mEditable.toString(), first+second+third+third);
+        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 4]), firstStart);
+        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 3]), secondStart);
+        // Find the more chip.
+        ImageSpan moreChip = view.getMoreChip();
+        assertEquals(mEditable.getSpanStart(moreChip), thirdStart);
+        assertEquals(mEditable.getSpanEnd(moreChip), thirdNextEnd);
+
+        view.removeMoreChip();
+        assertEquals(mEditable.toString(), first+second+third+third);
+        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 4]), firstStart);
+        assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 4]), firstEnd);
+        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 3]), secondStart);
+        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 2]), thirdStart);
+        assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 2]), thirdEnd);
+        assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 1]), thirdNextStart);
+        assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 1]), thirdNextEnd);
+        moreChip = view.getMoreChip();
+        assertEquals(mEditable.getSpanStart(moreChip), -1);
+    }
+
     private TextView createTestMoreItem() {
         TextView view = new TextView(getContext());
         view.setText("<xliff:g id='count'>%1$s</xliff:g> more...");