summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlice Yang <alice@google.com>2013-03-13 17:18:52 -0700
committerAlice Yang <alice@google.com>2013-03-13 17:18:52 -0700
commit4aa10b1bc14290397756b05e97ff9bc8a3b7564b (patch)
tree0a82e828153f83190ab6b640644889ee56316c8e
parent5ee4f94a5a4edfd18a69fbdc89786caec4cf3371 (diff)
parentf1d0416bad440e015c8f09c3827acc19d939d71a (diff)
downloadandroid_frameworks_ex-4aa10b1bc14290397756b05e97ff9bc8a3b7564b.tar.gz
android_frameworks_ex-4aa10b1bc14290397756b05e97ff9bc8a3b7564b.tar.bz2
android_frameworks_ex-4aa10b1bc14290397756b05e97ff9bc8a3b7564b.zip
Merge remote-tracking branch 'goog/jb-ub-mail-ur9' into merge
Merge UR8 into MR2. Change-Id: Ia04852cf84c05ab2ee4898662d347a06d40e5f11
-rw-r--r--chips/Android.mk7
-rw-r--r--chips/src/com/android/ex/chips/BaseRecipientAdapter.java18
-rw-r--r--chips/src/com/android/ex/chips/InvisibleRecipientChip.java155
-rw-r--r--chips/src/com/android/ex/chips/RecipientAlternatesAdapter.java9
-rw-r--r--chips/src/com/android/ex/chips/RecipientEditTextView.java343
-rw-r--r--chips/src/com/android/ex/chips/RecipientEntry.java9
-rw-r--r--chips/src/com/android/ex/chips/SingleRecipientArrayAdapter.java4
-rw-r--r--chips/src/com/android/ex/chips/recipientchip/BaseRecipientChip.java (renamed from chips/src/com/android/ex/chips/RecipientChip.java)41
-rw-r--r--chips/src/com/android/ex/chips/recipientchip/DrawableRecipientChip.java36
-rw-r--r--chips/src/com/android/ex/chips/recipientchip/InvisibleRecipientChip.java105
-rw-r--r--chips/src/com/android/ex/chips/recipientchip/SimpleRecipientChip.java (renamed from chips/src/com/android/ex/chips/VisibleRecipientChip.java)76
-rw-r--r--chips/src/com/android/ex/chips/recipientchip/VisibleRecipientChip.java99
-rw-r--r--chips/tests/Android.mk1
-rw-r--r--chips/tests/src/com/android/ex/chips/ChipsTest.java137
-rw-r--r--chips/tests/src/com/android/ex/chips/RecipientAlternatesAdapterTest.java56
15 files changed, 631 insertions, 465 deletions
diff --git a/chips/Android.mk b/chips/Android.mk
index 4a7977a..6aa8a01 100644
--- a/chips/Android.mk
+++ b/chips/Android.mk
@@ -21,4 +21,9 @@ LOCAL_SRC_FILES := \
$(call all-java-files-under, src) \
$(call all-logtags-files-under, src)
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-include $(BUILD_STATIC_JAVA_LIBRARY) \ No newline at end of file
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+##################################################
+# Build all sub-directories
+
+include $(call all-makefiles-under,$(LOCAL_PATH)) \ No newline at end of file
diff --git a/chips/src/com/android/ex/chips/BaseRecipientAdapter.java b/chips/src/com/android/ex/chips/BaseRecipientAdapter.java
index f742cf1..71b610e 100644
--- a/chips/src/com/android/ex/chips/BaseRecipientAdapter.java
+++ b/chips/src/com/android/ex/chips/BaseRecipientAdapter.java
@@ -234,8 +234,8 @@ public abstract class BaseRecipientAdapter extends BaseAdapter implements Filter
}
// We'll copy this result to mEntry in publicResults() (run in the UX thread).
- final List<RecipientEntry> entries = constructEntryList(false,
- entryMap, nonAggregatedEntries, existingDestinations);
+ final List<RecipientEntry> entries = constructEntryList(
+ entryMap, nonAggregatedEntries);
// After having local results, check the size of results. If the results are
// not enough, we search remote directories, which will take longer time.
@@ -424,8 +424,7 @@ public abstract class BaseRecipientAdapter extends BaseAdapter implements Filter
}
// Show the list again without "waiting" message.
- updateEntries(constructEntryList(false,
- mEntryMap, mNonAggregatedEntries, mExistingDestinations));
+ updateEntries(constructEntryList(mEntryMap, mNonAggregatedEntries));
}
}
@@ -482,8 +481,7 @@ public abstract class BaseRecipientAdapter extends BaseAdapter implements Filter
@Override
public void handleMessage(Message msg) {
if (mRemainingDirectoryCount > 0) {
- updateEntries(constructEntryList(true,
- mEntryMap, mNonAggregatedEntries, mExistingDestinations));
+ updateEntries(constructEntryList(mEntryMap, mNonAggregatedEntries));
}
}
@@ -634,7 +632,7 @@ public abstract class BaseRecipientAdapter extends BaseAdapter implements Filter
mDelayedMessageHandler.sendDelayedLoadMessage();
}
- private void putOneEntry(TemporaryEntry entry, boolean isAggregatedEntry,
+ private static void putOneEntry(TemporaryEntry entry, boolean isAggregatedEntry,
LinkedHashMap<Long, List<RecipientEntry>> entryMap,
List<RecipientEntry> nonAggregatedEntries,
Set<String> existingDestinations) {
@@ -675,10 +673,8 @@ public abstract class BaseRecipientAdapter extends BaseAdapter implements Filter
* thread to get one from directories.
*/
private List<RecipientEntry> constructEntryList(
- boolean showMessageIfDirectoryLoadRemaining,
LinkedHashMap<Long, List<RecipientEntry>> entryMap,
- List<RecipientEntry> nonAggregatedEntries,
- Set<String> existingDestinations) {
+ List<RecipientEntry> nonAggregatedEntries) {
final List<RecipientEntry> entries = new ArrayList<RecipientEntry>();
int validEntryCount = 0;
for (Map.Entry<Long, List<RecipientEntry>> mapEntry : entryMap.entrySet()) {
@@ -912,7 +908,7 @@ public abstract class BaseRecipientAdapter extends BaseAdapter implements Filter
if (imageView != null) {
imageView.setVisibility(View.VISIBLE);
final byte[] photoBytes = entry.getPhotoBytes();
- if (photoBytes != null && imageView != null) {
+ if (photoBytes != null) {
final Bitmap photo = BitmapFactory.decodeByteArray(photoBytes, 0,
photoBytes.length);
imageView.setImageBitmap(photo);
diff --git a/chips/src/com/android/ex/chips/InvisibleRecipientChip.java b/chips/src/com/android/ex/chips/InvisibleRecipientChip.java
deleted file mode 100644
index 83f7f8e..0000000
--- a/chips/src/com/android/ex/chips/InvisibleRecipientChip.java
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.ex.chips;
-
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.Rect;
-import android.text.TextUtils;
-import android.text.style.ReplacementSpan;
-
-/**
- * RecipientChip defines a span that contains information relevant to a
- * particular recipient.
- */
-/* package */class InvisibleRecipientChip extends ReplacementSpan implements RecipientChip {
- private final CharSequence mDisplay;
-
- private final CharSequence mValue;
-
- private final long mContactId;
-
- private final long mDataId;
-
- private RecipientEntry mEntry;
-
- private boolean mSelected = false;
-
- private CharSequence mOriginalText;
-
- /** <code>true</code> to display the original text, <code>false</code> to display nothing */
- private boolean mDisplayOriginalText = false;
-
- public InvisibleRecipientChip(RecipientEntry entry, int offset) {
- super();
- mDisplay = entry.getDisplayName();
- mValue = entry.getDestination().trim();
- mContactId = entry.getContactId();
- mDataId = entry.getDataId();
- mEntry = entry;
- }
-
- /**
- * Set the selected state of the chip.
- * @param selected
- */
- public void setSelected(boolean selected) {
- mSelected = selected;
- }
-
- /**
- * Return true if the chip is selected.
- */
- public boolean isSelected() {
- return mSelected;
- }
-
- /**
- * Get the text displayed in the chip.
- */
- public CharSequence getDisplay() {
- return mDisplay;
- }
-
- /**
- * Get the text value this chip represents.
- */
- public CharSequence getValue() {
- return mValue;
- }
-
- /**
- * Get the id of the contact associated with this chip.
- */
- public long getContactId() {
- return mContactId;
- }
-
- /**
- * Get the id of the data associated with this chip.
- */
- public long getDataId() {
- return mDataId;
- }
-
- /**
- * Get associated RecipientEntry.
- */
- public RecipientEntry getEntry() {
- return mEntry;
- }
-
- public void setOriginalText(String text) {
- if (!TextUtils.isEmpty(text)) {
- text = text.trim();
- }
- mOriginalText = text;
- }
-
- public CharSequence getOriginalText() {
- return !TextUtils.isEmpty(mOriginalText) ? mOriginalText : mEntry.getDestination();
- }
-
- public void setDisplayOriginalText(final boolean displayOriginalText) {
- mDisplayOriginalText = displayOriginalText;
- }
-
- @Override
- public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y,
- int bottom, Paint paint) {
- if (mDisplayOriginalText) {
- canvas.drawText(text, start, end, x, y, paint);
- } else {
- // Do nothing.
- }
- }
-
- @Override
- public int getSize(
- Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt fm) {
- if (mDisplayOriginalText) {
- return (int) paint.measureText(text, start, end);
- } else {
- return 0;
- }
- }
-
- @Override
- public Rect getBounds() {
- return new Rect(0, 0, 0, 0);
- }
-
- @Override
- public void draw(Canvas canvas) {
- // do nothing.
- }
-
- @Override
- public String toString() {
- return mDisplay + " <" + mValue + ">";
- }
-}
diff --git a/chips/src/com/android/ex/chips/RecipientAlternatesAdapter.java b/chips/src/com/android/ex/chips/RecipientAlternatesAdapter.java
index f825e93..465c90e 100644
--- a/chips/src/com/android/ex/chips/RecipientAlternatesAdapter.java
+++ b/chips/src/com/android/ex/chips/RecipientAlternatesAdapter.java
@@ -70,7 +70,7 @@ public class RecipientAlternatesAdapter extends CursorAdapter {
/**
* Called with all addresses that could not be resolved to valid recipients.
*/
- public void matchesNotFound(Set<String> addresses);
+ public void matchesNotFound(Set<String> unfoundAddresses);
}
public static void getMatchingRecipients(Context context, ArrayList<String> inAddresses,
@@ -229,7 +229,6 @@ public class RecipientAlternatesAdapter extends CursorAdapter {
* Given two {@link RecipientEntry}s for the same email address, this will return the one that
* contains more complete information for display purposes. Defaults to <code>entry2</code> if
* no significant differences are found.
- * TODO(skennedy) Add tests
*/
static RecipientEntry getBetterRecipient(final RecipientEntry entry1,
final RecipientEntry entry2) {
@@ -300,12 +299,12 @@ public class RecipientAlternatesAdapter extends CursorAdapter {
return cursor;
}
- public RecipientAlternatesAdapter(Context context, long contactId, long currentId, int viewId,
+ public RecipientAlternatesAdapter(Context context, long contactId, long currentId,
OnCheckedItemChangedListener listener) {
- this(context, contactId, currentId, viewId, QUERY_TYPE_EMAIL, listener);
+ this(context, contactId, currentId, QUERY_TYPE_EMAIL, listener);
}
- public RecipientAlternatesAdapter(Context context, long contactId, long currentId, int viewId,
+ public RecipientAlternatesAdapter(Context context, long contactId, long currentId,
int queryMode, OnCheckedItemChangedListener listener) {
super(context, getCursorForConstruction(context, contactId, queryMode), 0);
mLayoutInflater = LayoutInflater.from(context);
diff --git a/chips/src/com/android/ex/chips/RecipientEditTextView.java b/chips/src/com/android/ex/chips/RecipientEditTextView.java
index 551245c..67a5ca9 100644
--- a/chips/src/com/android/ex/chips/RecipientEditTextView.java
+++ b/chips/src/com/android/ex/chips/RecipientEditTextView.java
@@ -1,4 +1,5 @@
/*
+
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -16,6 +17,18 @@
package com.android.ex.chips;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
import android.app.Dialog;
import android.content.ClipData;
import android.content.ClipDescription;
@@ -81,18 +94,9 @@ import android.widget.ScrollView;
import android.widget.TextView;
import com.android.ex.chips.RecipientAlternatesAdapter.RecipientMatchCallback;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
+import com.android.ex.chips.recipientchip.DrawableRecipientChip;
+import com.android.ex.chips.recipientchip.InvisibleRecipientChip;
+import com.android.ex.chips.recipientchip.VisibleRecipientChip;
/**
* RecipientEditTextView is an auto complete text view for use with applications
@@ -105,8 +109,6 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
private static final char COMMIT_CHAR_COMMA = ',';
- private static final char NAME_WRAPPER_CHAR = '"';
-
private static final char COMMIT_CHAR_SEMICOLON = ';';
private static final char COMMIT_CHAR_SPACE = ' ';
@@ -149,7 +151,7 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
private Validator mValidator;
- private RecipientChip mSelectedChip;
+ private DrawableRecipientChip mSelectedChip;
private int mAlternatesLayout;
@@ -159,7 +161,8 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
private TextView mMoreItem;
- private final ArrayList<String> mPendingChips = new ArrayList<String>();
+ // VisibleForTesting
+ final ArrayList<String> mPendingChips = new ArrayList<String>();
private Handler mHandler;
@@ -171,9 +174,10 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
private ListPopupWindow mAddressPopup;
- private ArrayList<RecipientChip> mTemporaryRecipients;
+ // VisibleForTesting
+ ArrayList<DrawableRecipientChip> mTemporaryRecipients;
- private ArrayList<RecipientChip> mRemovedSpans;
+ private ArrayList<DrawableRecipientChip> mRemovedSpans;
private boolean mShouldShrink = true;
@@ -322,9 +326,9 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
return connection;
}
- /*package*/ RecipientChip getLastChip() {
- RecipientChip last = null;
- RecipientChip[] chips = getSortedRecipients();
+ /*package*/ DrawableRecipientChip getLastChip() {
+ DrawableRecipientChip last = null;
+ DrawableRecipientChip[] chips = getSortedRecipients();
if (chips != null && chips.length > 0) {
last = chips[chips.length - 1];
}
@@ -335,7 +339,7 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
public void onSelectionChanged(int start, int end) {
// When selection changes, see if it is inside the chips area.
// If so, move the cursor back after the chips again.
- RecipientChip last = getLastChip();
+ DrawableRecipientChip last = getLastChip();
if (last != null && start < getSpannable().getSpanEnd(last)) {
// Grab the last chip and set the cursor to after it.
setSelection(Math.min(getSpannable().getSpanEnd(last) + 1, getText().length()));
@@ -475,7 +479,8 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
Editable editable = getText();
int end = getSelectionEnd();
int start = mTokenizer.findTokenStart(editable, end);
- RecipientChip[] chips = getSpannable().getSpans(start, end, RecipientChip.class);
+ DrawableRecipientChip[] chips =
+ getSpannable().getSpans(start, end, DrawableRecipientChip.class);
if ((chips == null || chips.length == 0)) {
Editable text = getText();
int whatEnd = mTokenizer.findTokenEnd(text, start);
@@ -523,7 +528,7 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
TextUtils.TruncateAt.END);
}
- private Bitmap createSelectedChip(RecipientEntry contact, TextPaint paint, Layout layout) {
+ private Bitmap createSelectedChip(RecipientEntry contact, TextPaint paint) {
// Ellipsize the text so that it takes AT MOST the entire width of the
// autocomplete text entry area. Make sure to leave space for padding
// on the sides.
@@ -532,7 +537,7 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
float[] widths = new float[1];
paint.getTextWidths(" ", widths);
CharSequence ellipsizedText = ellipsizeText(createChipDisplayText(contact), paint,
- calculateAvailableWidth(true) - deleteWidth - widths[0]);
+ calculateAvailableWidth() - deleteWidth - widths[0]);
// Make sure there is a minimum chip width so the user can ALWAYS
// tap a chip without difficulty.
@@ -565,7 +570,7 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
}
- private Bitmap createUnselectedChip(RecipientEntry contact, TextPaint paint, Layout layout,
+ private Bitmap createUnselectedChip(RecipientEntry contact, TextPaint paint,
boolean leaveBlankIconSpacer) {
// Ellipsize the text so that it takes AT MOST the entire width of the
// autocomplete text entry area. Make sure to leave space for padding
@@ -575,7 +580,7 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
float[] widths = new float[1];
paint.getTextWidths(" ", widths);
CharSequence ellipsizedText = ellipsizeText(createChipDisplayText(contact), paint,
- calculateAvailableWidth(false) - iconWidth - widths[0]);
+ calculateAvailableWidth() - iconWidth - widths[0]);
// Make sure there is a minimum chip width so the user can ALWAYS
// tap a chip without difficulty.
int width = Math.max(iconWidth * 2, (int) Math.floor(paint.measureText(ellipsizedText, 0,
@@ -649,20 +654,19 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
return contact.isValid() ? mChipBackground : mInvalidChipBackground;
}
- private float getTextYOffset(String text, TextPaint paint, int height) {
+ private static float getTextYOffset(String text, TextPaint paint, int height) {
Rect bounds = new Rect();
paint.getTextBounds(text, 0, text.length(), bounds);
int textHeight = bounds.bottom - bounds.top ;
return height - ((height - textHeight) / 2) - (int)paint.descent();
}
- private RecipientChip constructChipSpan(RecipientEntry contact, int offset, boolean pressed,
+ private DrawableRecipientChip constructChipSpan(RecipientEntry contact, boolean pressed,
boolean leaveIconSpace) throws NullPointerException {
if (mChipBackground == null) {
throw new NullPointerException(
"Unable to render any chips as setChipDimensions was not called.");
}
- Layout layout = getLayout();
TextPaint paint = getPaint();
float defaultSize = paint.getTextSize();
@@ -670,16 +674,16 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
Bitmap tmpBitmap;
if (pressed) {
- tmpBitmap = createSelectedChip(contact, paint, layout);
+ tmpBitmap = createSelectedChip(contact, paint);
} else {
- tmpBitmap = createUnselectedChip(contact, paint, layout, leaveIconSpace);
+ tmpBitmap = createUnselectedChip(contact, paint, leaveIconSpace);
}
// Pass the full text, un-ellipsized, to the chip.
Drawable result = new BitmapDrawable(getResources(), tmpBitmap);
result.setBounds(0, 0, tmpBitmap.getWidth(), tmpBitmap.getHeight());
- RecipientChip recipientChip = new VisibleRecipientChip(result, contact, offset);
+ DrawableRecipientChip recipientChip = new VisibleRecipientChip(result, contact);
// Return text to the original size.
paint.setTextSize(defaultSize);
paint.setColor(defaultColor);
@@ -704,7 +708,7 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
* account the width of the EditTextView, any view padding, and padding
* that will be added to the chip.
*/
- private float calculateAvailableWidth(boolean pressed) {
+ private float calculateAvailableWidth() {
return getWidth() - getPaddingLeft() - getPaddingRight() - (mChipPadding * 2);
}
@@ -821,10 +825,10 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
private void checkChipWidths() {
// Check the widths of the associated chips.
- RecipientChip[] chips = getSortedRecipients();
+ DrawableRecipientChip[] chips = getSortedRecipients();
if (chips != null) {
Rect bounds;
- for (RecipientChip chip : chips) {
+ for (DrawableRecipientChip chip : chips) {
bounds = chip.getBounds();
if (getWidth() > 0 && bounds.right - bounds.left > getWidth()) {
// Need to redraw that chip.
@@ -880,10 +884,10 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
} else {
// Create the "more" chip
mIndividualReplacements = new IndividualReplacementTask();
- mIndividualReplacements.execute(new ArrayList<RecipientChip>(
+ mIndividualReplacements.execute(new ArrayList<DrawableRecipientChip>(
mTemporaryRecipients.subList(0, CHIP_LIMIT)));
if (mTemporaryRecipients.size() > CHIP_LIMIT) {
- mTemporaryRecipients = new ArrayList<RecipientChip>(
+ mTemporaryRecipients = new ArrayList<DrawableRecipientChip>(
mTemporaryRecipients.subList(CHIP_LIMIT,
mTemporaryRecipients.size()));
} else {
@@ -917,7 +921,7 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
return;
}
// Find the last chip; eliminate any commit characters after it.
- RecipientChip[] chips = getSortedRecipients();
+ DrawableRecipientChip[] chips = getSortedRecipients();
Spannable spannable = getSpannable();
if (chips != null && chips.length > 0) {
int end;
@@ -944,7 +948,8 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
* Create a chip that represents just the email address of a recipient. At some later
* point, this chip will be attached to a real contact entry, if one exists.
*/
- private void createReplacementChip(int tokenStart, int tokenEnd, Editable editable,
+ // VisibleForTesting
+ void createReplacementChip(int tokenStart, int tokenEnd, Editable editable,
boolean visible) {
if (alreadyHasChip(tokenStart, tokenEnd)) {
// There is already a chip present at this location.
@@ -952,15 +957,14 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
return;
}
String token = editable.toString().substring(tokenStart, tokenEnd);
- int commitCharIndex = token.trim().lastIndexOf(COMMIT_CHAR_COMMA);
- if (commitCharIndex == token.length() - 1) {
- token = token.substring(0, token.length() - 1);
+ final String trimmedToken = token.trim();
+ int commitCharIndex = trimmedToken.lastIndexOf(COMMIT_CHAR_COMMA);
+ if (commitCharIndex == trimmedToken.length() - 1) {
+ token = trimmedToken.substring(0, trimmedToken.length() - 1);
}
RecipientEntry entry = createTokenizedEntry(token);
if (entry != null) {
- String destText = createAddressText(entry);
- SpannableString chipText = new SpannableString(destText);
- RecipientChip chip = null;
+ DrawableRecipientChip chip = null;
try {
if (!mNoChips) {
/*
@@ -971,8 +975,8 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
|| TextUtils.equals(entry.getDisplayName(),
entry.getDestination());
chip = visible ?
- constructChipSpan(entry, tokenStart, false, leaveSpace)
- : new InvisibleRecipientChip(entry, commitCharIndex);
+ constructChipSpan(entry, false, leaveSpace)
+ : new InvisibleRecipientChip(entry);
}
} catch (NullPointerException e) {
Log.e(TAG, e.getMessage(), e);
@@ -981,7 +985,7 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
// Add this chip to the list of entries "to replace"
if (chip != null) {
if (mTemporaryRecipients == null) {
- mTemporaryRecipients = new ArrayList<RecipientChip>();
+ mTemporaryRecipients = new ArrayList<DrawableRecipientChip>();
}
chip.setOriginalText(token);
mTemporaryRecipients.add(chip);
@@ -1061,7 +1065,7 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
return mValidator == null ? true : mValidator.isValid(text);
}
- private String tokenizeAddress(String destination) {
+ private static String tokenizeAddress(String destination) {
Rfc822Token[] tokens = Rfc822Tokenizer.tokenize(destination);
if (tokens != null && tokens.length > 0) {
return tokens[0].getAddress();
@@ -1114,20 +1118,6 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
switch (keyCode) {
- case KeyEvent.KEYCODE_ENTER:
- case KeyEvent.KEYCODE_DPAD_CENTER:
- if (event.hasNoModifiers()) {
- if (commitDefault()) {
- return true;
- }
- if (mSelectedChip != null) {
- clearSelectedChip();
- return true;
- } else if (focusNext()) {
- return true;
- }
- }
- break;
case KeyEvent.KEYCODE_TAB:
if (event.hasNoModifiers()) {
if (mSelectedChip != null) {
@@ -1135,9 +1125,6 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
} else {
commitDefault();
}
- if (focusNext()) {
- return true;
- }
}
break;
}
@@ -1245,10 +1232,10 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
return;
}
// Find the last chip.
- RecipientChip[] recips = getSortedRecipients();
+ DrawableRecipientChip[] recips = getSortedRecipients();
if (recips != null && recips.length > 0) {
- RecipientChip last = recips[recips.length - 1];
- RecipientChip beforeLast = null;
+ DrawableRecipientChip last = recips[recips.length - 1];
+ DrawableRecipientChip beforeLast = null;
if (recips.length > 1) {
beforeLast = recips[recips.length - 2];
}
@@ -1279,7 +1266,8 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
if (mNoChips) {
return true;
}
- RecipientChip[] chips = getSpannable().getSpans(start, end, RecipientChip.class);
+ DrawableRecipientChip[] chips =
+ getSpannable().getSpans(start, end, DrawableRecipientChip.class);
if ((chips == null || chips.length == 0)) {
return false;
}
@@ -1322,6 +1310,23 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
removeChip(mSelectedChip);
}
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_ENTER:
+ case KeyEvent.KEYCODE_DPAD_CENTER:
+ if (event.hasNoModifiers()) {
+ if (commitDefault()) {
+ return true;
+ }
+ if (mSelectedChip != null) {
+ clearSelectedChip();
+ return true;
+ } else if (focusNext()) {
+ return true;
+ }
+ }
+ break;
+ }
+
return super.onKeyDown(keyCode, event);
}
@@ -1330,11 +1335,11 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
return getText();
}
- private int getChipStart(RecipientChip chip) {
+ private int getChipStart(DrawableRecipientChip chip) {
return getSpannable().getSpanStart(chip);
}
- private int getChipEnd(RecipientChip chip) {
+ private int getChipEnd(DrawableRecipientChip chip) {
return getSpannable().getSpanEnd(chip);
}
@@ -1354,7 +1359,7 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
// If this is a RecipientChip, don't filter
// on its contents.
Spannable span = getSpannable();
- RecipientChip[] chips = span.getSpans(start, end, RecipientChip.class);
+ DrawableRecipientChip[] chips = span.getSpans(start, end, DrawableRecipientChip.class);
if (chips != null && chips.length > 0) {
return;
}
@@ -1412,7 +1417,7 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
float x = event.getX();
float y = event.getY();
int offset = putOffsetInRange(getOffsetForPosition(x, y));
- RecipientChip currentChip = findChip(offset);
+ DrawableRecipientChip currentChip = findChip(offset);
if (currentChip != null) {
if (action == MotionEvent.ACTION_UP) {
if (mSelectedChip != null && mSelectedChip != currentChip) {
@@ -1444,8 +1449,8 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
}
}
- private void showAlternates(RecipientChip currentChip, ListPopupWindow alternatesPopup,
- int width, Context context) {
+ private void showAlternates(DrawableRecipientChip currentChip, ListPopupWindow alternatesPopup,
+ int width) {
int line = getLayout().getLineForOffset(getChipStart(currentChip));
int bottom;
if (line == getLineCount() -1) {
@@ -1476,12 +1481,12 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
}
}
- private ListAdapter createAlternatesAdapter(RecipientChip chip) {
+ private ListAdapter createAlternatesAdapter(DrawableRecipientChip chip) {
return new RecipientAlternatesAdapter(getContext(), chip.getContactId(), chip.getDataId(),
- mAlternatesLayout, ((BaseRecipientAdapter)getAdapter()).getQueryType(), this);
+ ((BaseRecipientAdapter)getAdapter()).getQueryType(), this);
}
- private ListAdapter createSingleAddressAdapter(RecipientChip currentChip) {
+ private ListAdapter createSingleAddressAdapter(DrawableRecipientChip currentChip) {
return new SingleRecipientArrayAdapter(getContext(), mAlternatesLayout, currentChip
.getEntry());
}
@@ -1525,18 +1530,19 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
return offset;
}
- private int findText(Editable text, int offset) {
+ private static int findText(Editable text, int offset) {
if (text.charAt(offset) != ' ') {
return offset;
}
return -1;
}
- private RecipientChip findChip(int offset) {
- RecipientChip[] chips = getSpannable().getSpans(0, getText().length(), RecipientChip.class);
+ private DrawableRecipientChip findChip(int offset) {
+ DrawableRecipientChip[] chips =
+ getSpannable().getSpans(0, getText().length(), DrawableRecipientChip.class);
// Find the chip that contains this offset.
for (int i = 0; i < chips.length; i++) {
- RecipientChip chip = chips[i];
+ DrawableRecipientChip chip = chips[i];
int start = getChipStart(chip);
int end = getChipEnd(chip);
if (offset >= start && offset <= end) {
@@ -1599,13 +1605,11 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
}
SpannableString chipText = null;
// Always leave a blank space at the end of a chip.
- int end = getSelectionEnd();
- int start = mTokenizer.findTokenStart(getText(), end);
- int textLength = displayText.length()-1;
+ int textLength = displayText.length() - 1;
chipText = new SpannableString(displayText);
if (!mNoChips) {
try {
- RecipientChip chip = constructChipSpan(entry, start, pressed,
+ DrawableRecipientChip chip = constructChipSpan(entry, pressed,
false /* leave space for contact icon */);
chipText.setSpan(chip, 0, textLength,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
@@ -1673,9 +1677,9 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
/** Returns a collection of contact Id for each chip inside this View. */
/* package */ Collection<Long> getContactIds() {
final Set<Long> result = new HashSet<Long>();
- RecipientChip[] chips = getSortedRecipients();
+ DrawableRecipientChip[] chips = getSortedRecipients();
if (chips != null) {
- for (RecipientChip chip : chips) {
+ for (DrawableRecipientChip chip : chips) {
result.add(chip.getContactId());
}
}
@@ -1686,9 +1690,9 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
/** Returns a collection of data Id for each chip inside this View. May be null. */
/* package */ Collection<Long> getDataIds() {
final Set<Long> result = new HashSet<Long>();
- RecipientChip [] chips = getSortedRecipients();
+ DrawableRecipientChip [] chips = getSortedRecipients();
if (chips != null) {
- for (RecipientChip chip : chips) {
+ for (DrawableRecipientChip chip : chips) {
result.add(chip.getDataId());
}
}
@@ -1696,16 +1700,16 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
}
// Visible for testing.
- /* package */RecipientChip[] getSortedRecipients() {
- RecipientChip[] recips = getSpannable()
- .getSpans(0, getText().length(), RecipientChip.class);
- ArrayList<RecipientChip> recipientsList = new ArrayList<RecipientChip>(Arrays
- .asList(recips));
+ /* package */DrawableRecipientChip[] getSortedRecipients() {
+ DrawableRecipientChip[] recips = getSpannable()
+ .getSpans(0, getText().length(), DrawableRecipientChip.class);
+ ArrayList<DrawableRecipientChip> recipientsList = new ArrayList<DrawableRecipientChip>(
+ Arrays.asList(recips));
final Spannable spannable = getSpannable();
- Collections.sort(recipientsList, new Comparator<RecipientChip>() {
+ Collections.sort(recipientsList, new Comparator<DrawableRecipientChip>() {
@Override
- public int compare(RecipientChip first, RecipientChip second) {
+ public int compare(DrawableRecipientChip first, DrawableRecipientChip second) {
int firstStart = spannable.getSpanStart(first);
int secondStart = spannable.getSpanStart(second);
if (firstStart < secondStart) {
@@ -1717,7 +1721,7 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
}
}
});
- return recipientsList.toArray(new RecipientChip[recipientsList.size()]);
+ return recipientsList.toArray(new DrawableRecipientChip[recipientsList.size()]);
}
@Override
@@ -1824,7 +1828,7 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
if (tempMore.length > 0) {
getSpannable().removeSpan(tempMore[0]);
}
- RecipientChip[] recipients = getSortedRecipients();
+ DrawableRecipientChip[] recipients = getSortedRecipients();
if (recipients == null || recipients.length <= CHIP_LIMIT) {
mMoreChip = null;
@@ -1834,7 +1838,7 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
int numRecipients = recipients.length;
int overage = numRecipients - CHIP_LIMIT;
MoreImageSpan moreSpan = createMoreSpan(overage);
- mRemovedSpans = new ArrayList<RecipientChip>();
+ mRemovedSpans = new ArrayList<DrawableRecipientChip>();
int totalReplaceStart = 0;
int totalReplaceEnd = 0;
Editable text = getText();
@@ -1881,7 +1885,7 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
// Re-add the spans that were removed.
if (mRemovedSpans != null && mRemovedSpans.size() > 0) {
// Recreate each removed span.
- RecipientChip[] recipients = getSortedRecipients();
+ DrawableRecipientChip[] recipients = getSortedRecipients();
// Start the search for tokens after the last currently visible
// chip.
if (recipients == null || recipients.length == 0) {
@@ -1889,7 +1893,7 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
}
int end = span.getSpanEnd(recipients[recipients.length - 1]);
Editable editable = getText();
- for (RecipientChip chip : mRemovedSpans) {
+ for (DrawableRecipientChip chip : mRemovedSpans) {
int chipStart;
int chipEnd;
String token;
@@ -1903,13 +1907,6 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
end = chipEnd = Math.min(editable.length(), chipStart + token.length());
// Only set the span if we found a matching token.
if (chipStart != -1) {
- if (chip instanceof InvisibleRecipientChip) {
- /*
- * We want the original text to be displayed until we can replace it
- * with a real chip
- */
- // ((InvisibleRecipientChip) chip).setDisplayOriginalText(true);
- }
editable.setSpan(chip, chipStart, chipEnd,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
@@ -1931,7 +1928,7 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
* @return A RecipientChip in the selected state or null if the chip
* just contained an email address.
*/
- private RecipientChip selectChip(RecipientChip currentChip) {
+ private DrawableRecipientChip selectChip(DrawableRecipientChip currentChip) {
if (shouldShowEditableText(currentChip)) {
CharSequence text = currentChip.getValue();
Editable editable = getText();
@@ -1945,17 +1942,17 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
editable.append(text);
return constructChipSpan(
RecipientEntry.constructFakeEntry((String) text, isValid(text.toString())),
- getSelectionStart(), true, false);
+ true, false);
} else if (currentChip.getContactId() == RecipientEntry.GENERATED_CONTACT) {
int start = getChipStart(currentChip);
int end = getChipEnd(currentChip);
getSpannable().removeSpan(currentChip);
- RecipientChip newChip;
+ DrawableRecipientChip newChip;
try {
if (mNoChips) {
return null;
}
- newChip = constructChipSpan(currentChip.getEntry(), start, true, false);
+ newChip = constructChipSpan(currentChip.getEntry(), true, false);
} catch (NullPointerException e) {
Log.e(TAG, e.getMessage(), e);
return null;
@@ -1971,16 +1968,16 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
if (shouldShowEditableText(newChip)) {
scrollLineIntoView(getLayout().getLineForOffset(getChipStart(newChip)));
}
- showAddress(newChip, mAddressPopup, getWidth(), getContext());
+ showAddress(newChip, mAddressPopup, getWidth());
setCursorVisible(false);
return newChip;
} else {
int start = getChipStart(currentChip);
int end = getChipEnd(currentChip);
getSpannable().removeSpan(currentChip);
- RecipientChip newChip;
+ DrawableRecipientChip newChip;
try {
- newChip = constructChipSpan(currentChip.getEntry(), start, true, false);
+ newChip = constructChipSpan(currentChip.getEntry(), true, false);
} catch (NullPointerException e) {
Log.e(TAG, e.getMessage(), e);
return null;
@@ -1996,20 +1993,20 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
if (shouldShowEditableText(newChip)) {
scrollLineIntoView(getLayout().getLineForOffset(getChipStart(newChip)));
}
- showAlternates(newChip, mAlternatesPopup, getWidth(), getContext());
+ showAlternates(newChip, mAlternatesPopup, getWidth());
setCursorVisible(false);
return newChip;
}
}
- private boolean shouldShowEditableText(RecipientChip currentChip) {
+ private boolean shouldShowEditableText(DrawableRecipientChip currentChip) {
long contactId = currentChip.getContactId();
return contactId == RecipientEntry.INVALID_CONTACT
|| (!isPhoneQuery() && contactId == RecipientEntry.GENERATED_CONTACT);
}
- private void showAddress(final RecipientChip currentChip, final ListPopupWindow popup,
- int width, Context context) {
+ private void showAddress(final DrawableRecipientChip currentChip, final ListPopupWindow popup,
+ int width) {
int line = getLayout().getLineForOffset(getChipStart(currentChip));
int bottom = calculateOffsetFromBottom(line);
// Align the alternates popup with the left side of the View,
@@ -2036,7 +2033,7 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
* the chip without a delete icon and with an unfocused background. This is
* called when the RecipientChip no longer has focus.
*/
- private void unselectChip(RecipientChip chip) {
+ private void unselectChip(DrawableRecipientChip chip) {
int start = getChipStart(chip);
int end = getChipEnd(chip);
Editable editable = getText();
@@ -2051,7 +2048,7 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
editable.removeSpan(chip);
try {
if (!mNoChips) {
- editable.setSpan(constructChipSpan(chip.getEntry(), start, false, false),
+ editable.setSpan(constructChipSpan(chip.getEntry(), false, false),
start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
} catch (NullPointerException e) {
@@ -2074,9 +2071,10 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
* right after the selected chip.
* @return boolean
*/
- private boolean isInDelete(RecipientChip chip, int offset, float x, float y) {
+ private boolean isInDelete(DrawableRecipientChip chip, int offset, float x, float y) {
// Figure out the bounds of this chip and whether or not
// the user clicked in the X portion.
+ // TODO: Should x and y be used, or removed?
return chip.isSelected() && offset == getChipEnd(chip);
}
@@ -2084,7 +2082,7 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
* Remove the chip and any text associated with it from the RecipientEditTextView.
*/
// Visible for testing.
- /*pacakge*/ void removeChip(RecipientChip chip) {
+ /*pacakge*/ void removeChip(DrawableRecipientChip chip) {
Spannable spannable = getSpannable();
int spanStart = spannable.getSpanStart(chip);
int spanEnd = spannable.getSpanEnd(chip);
@@ -2113,7 +2111,7 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
* that uses the contact data provided.
*/
// Visible for testing.
- /*package*/ void replaceChip(RecipientChip chip, RecipientEntry entry) {
+ /*package*/ void replaceChip(DrawableRecipientChip chip, RecipientEntry entry) {
boolean wasSelected = chip == mSelectedChip;
if (wasSelected) {
mSelectedChip = null;
@@ -2151,7 +2149,7 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
* event, see if that event was in the delete icon. If so, delete it.
* Otherwise, unselect the chip.
*/
- public void onClick(RecipientChip chip, int offset, float x, float y) {
+ public void onClick(DrawableRecipientChip chip, int offset, float x, float y) {
if (chip.isSelected()) {
if (isInDelete(chip, offset, x, y)) {
removeChip(chip);
@@ -2180,9 +2178,9 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
if (TextUtils.isEmpty(s)) {
// Remove all the chips spans.
Spannable spannable = getSpannable();
- RecipientChip[] chips = spannable.getSpans(0, getText().length(),
- RecipientChip.class);
- for (RecipientChip chip : chips) {
+ DrawableRecipientChip[] chips = spannable.getSpans(0, getText().length(),
+ DrawableRecipientChip.class);
+ for (DrawableRecipientChip chip : chips) {
spannable.removeSpan(chip);
}
if (mMoreChip != null) {
@@ -2247,8 +2245,8 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
// If the item deleted is a space, and the thing before the
// space is a chip, delete the entire span.
int selStart = getSelectionStart();
- RecipientChip[] repl = getSpannable().getSpans(selStart, selStart,
- RecipientChip.class);
+ DrawableRecipientChip[] repl = getSpannable().getSpans(selStart, selStart,
+ DrawableRecipientChip.class);
if (repl.length > 0) {
// There is a chip there! Just remove it.
Editable editable = getText();
@@ -2291,7 +2289,7 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
return last == COMMIT_CHAR_COMMA || last == COMMIT_CHAR_SEMICOLON;
}
- public boolean isGeneratedContact(RecipientChip chip) {
+ public boolean isGeneratedContact(DrawableRecipientChip chip) {
long contactId = chip.getContactId();
return contactId == RecipientEntry.INVALID_CONTACT
|| (!isPhoneQuery() && contactId == RecipientEntry.GENERATED_CONTACT);
@@ -2335,7 +2333,7 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
}
private void handlePasteAndReplace() {
- ArrayList<RecipientChip> created = handlePaste();
+ ArrayList<DrawableRecipientChip> created = handlePaste();
if (created != null && created.size() > 0) {
// Perform reverse lookups on the pasted contacts.
IndividualReplacementTask replace = new IndividualReplacementTask();
@@ -2344,14 +2342,14 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
}
// Visible for testing.
- /* package */ArrayList<RecipientChip> handlePaste() {
+ /* package */ArrayList<DrawableRecipientChip> handlePaste() {
String text = getText().toString();
int originalTokenStart = mTokenizer.findTokenStart(text, getSelectionEnd());
String lastAddress = text.substring(originalTokenStart);
int tokenStart = originalTokenStart;
int prevTokenStart = tokenStart;
- RecipientChip findChip = null;
- ArrayList<RecipientChip> created = new ArrayList<RecipientChip>();
+ DrawableRecipientChip findChip = null;
+ ArrayList<DrawableRecipientChip> created = new ArrayList<DrawableRecipientChip>();
if (tokenStart != 0) {
// There are things before this!
while (tokenStart != 0 && findChip == null) {
@@ -2367,7 +2365,7 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
tokenStart = prevTokenStart;
}
int tokenEnd;
- RecipientChip createdChip;
+ DrawableRecipientChip createdChip;
while (tokenStart < originalTokenStart) {
tokenEnd = movePastTerminators(mTokenizer.findTokenEnd(getText().toString(),
tokenStart));
@@ -2411,12 +2409,12 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
}
private class RecipientReplacementTask extends AsyncTask<Void, Void, Void> {
- private RecipientChip createFreeChip(RecipientEntry entry) {
+ private DrawableRecipientChip createFreeChip(RecipientEntry entry) {
try {
if (mNoChips) {
return null;
}
- return constructChipSpan(entry, -1, false,
+ return constructChipSpan(entry, false,
false /*leave space for contact icon */);
} catch (NullPointerException e) {
Log.e(TAG, e.getMessage(), e);
@@ -2428,8 +2426,9 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
protected void onPreExecute() {
// Ensure everything is in chip-form already, so we don't have text that slowly gets
// replaced
- final List<RecipientChip> originalRecipients = new ArrayList<RecipientChip>();
- final RecipientChip[] existingChips = getSortedRecipients();
+ final List<DrawableRecipientChip> originalRecipients =
+ new ArrayList<DrawableRecipientChip>();
+ final DrawableRecipientChip[] existingChips = getSortedRecipients();
for (int i = 0; i < existingChips.length; i++) {
originalRecipients.add(existingChips[i]);
}
@@ -2437,10 +2436,10 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
originalRecipients.addAll(mRemovedSpans);
}
- final List<RecipientChip> replacements =
- new ArrayList<RecipientChip>(originalRecipients.size());
+ final List<DrawableRecipientChip> replacements =
+ new ArrayList<DrawableRecipientChip>(originalRecipients.size());
- for (final RecipientChip chip : originalRecipients) {
+ for (final DrawableRecipientChip chip : originalRecipients) {
if (RecipientEntry.isCreatedRecipient(chip.getEntry().getContactId())
&& getSpannable().getSpanStart(chip) != -1) {
replacements.add(createFreeChip(chip.getEntry()));
@@ -2460,8 +2459,9 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
// For each chip in the list, look up the matching contact.
// If there is a match, replace that chip with the matching
// chip.
- final ArrayList<RecipientChip> recipients = new ArrayList<RecipientChip>();
- RecipientChip[] existingChips = getSortedRecipients();
+ final ArrayList<DrawableRecipientChip> recipients =
+ new ArrayList<DrawableRecipientChip>();
+ DrawableRecipientChip[] existingChips = getSortedRecipients();
for (int i = 0; i < existingChips.length; i++) {
recipients.add(existingChips[i]);
}
@@ -2469,7 +2469,7 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
recipients.addAll(mRemovedSpans);
}
ArrayList<String> addresses = new ArrayList<String>();
- RecipientChip chip;
+ DrawableRecipientChip chip;
for (int i = 0; i < recipients.size(); i++) {
chip = recipients.get(i);
if (chip != null) {
@@ -2482,9 +2482,9 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
@Override
public void matchesFound(Map<String, RecipientEntry> entries) {
- final ArrayList<RecipientChip> replacements =
- new ArrayList<RecipientChip>();
- for (final RecipientChip temp : recipients) {
+ final ArrayList<DrawableRecipientChip> replacements =
+ new ArrayList<DrawableRecipientChip>();
+ for (final DrawableRecipientChip temp : recipients) {
RecipientEntry entry = null;
if (temp != null && RecipientEntry.isCreatedRecipient(
temp.getEntry().getContactId())
@@ -2504,15 +2504,16 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
}
@Override
- public void matchesNotFound(final Set<String> addresses) {
- final List<RecipientChip> replacements =
- new ArrayList<RecipientChip>(addresses.size());
+ public void matchesNotFound(final Set<String> unfoundAddresses) {
+ final List<DrawableRecipientChip> replacements =
+ new ArrayList<DrawableRecipientChip>(unfoundAddresses.size());
- for (final RecipientChip temp : recipients) {
+ for (final DrawableRecipientChip temp : recipients) {
if (temp != null && RecipientEntry.isCreatedRecipient(
temp.getEntry().getContactId())
&& getSpannable().getSpanStart(temp) != -1) {
- if (addresses.contains(temp.getEntry().getDestination())) {
+ if (unfoundAddresses.contains(
+ temp.getEntry().getDestination())) {
replacements.add(createFreeChip(temp.getEntry()));
} else {
replacements.add(null);
@@ -2528,8 +2529,8 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
return null;
}
- private void processReplacements(final List<RecipientChip> recipients,
- final List<RecipientChip> replacements) {
+ private void processReplacements(final List<DrawableRecipientChip> recipients,
+ final List<DrawableRecipientChip> replacements) {
if (replacements != null && replacements.size() > 0) {
final Runnable runnable = new Runnable() {
@Override
@@ -2537,8 +2538,8 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
Editable oldText = getText();
int start, end;
int i = 0;
- for (RecipientChip chip : recipients) {
- RecipientChip replacement = replacements.get(i);
+ for (DrawableRecipientChip chip : recipients) {
+ DrawableRecipientChip replacement = replacements.get(i);
if (replacement != null) {
final RecipientEntry oldEntry = chip.getEntry();
final RecipientEntry newEntry = replacement.getEntry();
@@ -2589,15 +2590,15 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
}
private class IndividualReplacementTask
- extends AsyncTask<ArrayList<RecipientChip>, Void, Void> {
+ extends AsyncTask<ArrayList<DrawableRecipientChip>, Void, Void> {
@Override
- protected Void doInBackground(ArrayList<RecipientChip>... params) {
+ protected Void doInBackground(ArrayList<DrawableRecipientChip>... params) {
// For each chip in the list, look up the matching contact.
// If there is a match, replace that chip with the matching
// chip.
- final ArrayList<RecipientChip> originalRecipients = params[0];
+ final ArrayList<DrawableRecipientChip> originalRecipients = params[0];
ArrayList<String> addresses = new ArrayList<String>();
- RecipientChip chip;
+ DrawableRecipientChip chip;
for (int i = 0; i < originalRecipients.size(); i++) {
chip = originalRecipients.get(i);
if (chip != null) {
@@ -2610,7 +2611,7 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
@Override
public void matchesFound(Map<String, RecipientEntry> entries) {
- for (final RecipientChip temp : originalRecipients) {
+ for (final DrawableRecipientChip temp : originalRecipients) {
if (RecipientEntry.isCreatedRecipient(temp.getEntry()
.getContactId())
&& getSpannable().getSpanStart(temp) != -1) {
@@ -2638,7 +2639,7 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
}
@Override
- public void matchesNotFound(final Set<String> addresses) {
+ public void matchesNotFound(final Set<String> unfoundAddresses) {
// No action required
}
});
@@ -2676,7 +2677,7 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
float x = event.getX();
float y = event.getY();
int offset = putOffsetInRange(getOffsetForPosition(x, y));
- RecipientChip currentChip = findChip(offset);
+ DrawableRecipientChip currentChip = findChip(offset);
if (currentChip != null) {
if (mDragEnabled) {
// Start drag-and-drop for the selected chip.
@@ -2698,7 +2699,7 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
/**
* Starts drag-and-drop for the selected chip.
*/
- private void startDrag(RecipientChip currentChip) {
+ private void startDrag(DrawableRecipientChip currentChip) {
String address = currentChip.getEntry().getDestination();
ClipData data = ClipData.newPlainText(address, address + COMMIT_CHAR_COMMA);
@@ -2733,9 +2734,9 @@ public class RecipientEditTextView extends MultiAutoCompleteTextView implements
* Drag shadow for a {@link RecipientChip}.
*/
private final class RecipientChipShadow extends DragShadowBuilder {
- private final RecipientChip mChip;
+ private final DrawableRecipientChip mChip;
- public RecipientChipShadow(RecipientChip chip) {
+ public RecipientChipShadow(DrawableRecipientChip chip) {
mChip = chip;
}
diff --git a/chips/src/com/android/ex/chips/RecipientEntry.java b/chips/src/com/android/ex/chips/RecipientEntry.java
index 1a79f32..14b11e1 100644
--- a/chips/src/com/android/ex/chips/RecipientEntry.java
+++ b/chips/src/com/android/ex/chips/RecipientEntry.java
@@ -19,6 +19,8 @@ package com.android.ex.chips;
import android.net.Uri;
import android.provider.ContactsContract.CommonDataKinds.Email;
import android.provider.ContactsContract.DisplayNameSources;
+import android.text.util.Rfc822Token;
+import android.text.util.Rfc822Tokenizer;
/**
* Represents one entry inside recipient auto-complete list.
@@ -106,8 +108,11 @@ public class RecipientEntry {
* This address has not been resolved to a contact and therefore does not
* have a contact id or photo.
*/
- public static RecipientEntry constructFakeEntry(String address, boolean isValid) {
- return new RecipientEntry(ENTRY_TYPE_PERSON, address, address,
+ public static RecipientEntry constructFakeEntry(final String address, final boolean isValid) {
+ final Rfc822Token[] tokens = Rfc822Tokenizer.tokenize(address);
+ final String tokenizedAddress = tokens[0].getAddress();
+
+ return new RecipientEntry(ENTRY_TYPE_PERSON, tokenizedAddress, tokenizedAddress,
INVALID_DESTINATION_TYPE, null,
INVALID_CONTACT, INVALID_CONTACT, null, true, isValid);
}
diff --git a/chips/src/com/android/ex/chips/SingleRecipientArrayAdapter.java b/chips/src/com/android/ex/chips/SingleRecipientArrayAdapter.java
index 8131fc3..0571a4e 100644
--- a/chips/src/com/android/ex/chips/SingleRecipientArrayAdapter.java
+++ b/chips/src/com/android/ex/chips/SingleRecipientArrayAdapter.java
@@ -43,7 +43,7 @@ class SingleRecipientArrayAdapter extends ArrayAdapter<RecipientEntry> {
if (convertView == null) {
convertView = newView();
}
- bindView(convertView, convertView.getContext(), getItem(position));
+ bindView(convertView, getItem(position));
return convertView;
}
@@ -51,7 +51,7 @@ class SingleRecipientArrayAdapter extends ArrayAdapter<RecipientEntry> {
return mLayoutInflater.inflate(mLayoutId, null);
}
- private void bindView(View view, Context context, RecipientEntry entry) {
+ private static void bindView(View view, RecipientEntry entry) {
TextView display = (TextView) view.findViewById(android.R.id.title);
ImageView imageView = (ImageView) view.findViewById(android.R.id.icon);
display.setText(entry.getDisplayName());
diff --git a/chips/src/com/android/ex/chips/RecipientChip.java b/chips/src/com/android/ex/chips/recipientchip/BaseRecipientChip.java
index c7745c2..a080ee7 100644
--- a/chips/src/com/android/ex/chips/RecipientChip.java
+++ b/chips/src/com/android/ex/chips/recipientchip/BaseRecipientChip.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 The Android Open Source Project
+ * 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.
@@ -14,71 +14,60 @@
* limitations under the License.
*/
-package com.android.ex.chips;
+package com.android.ex.chips.recipientchip;
-import android.graphics.Canvas;
-import android.graphics.Rect;
+import com.android.ex.chips.RecipientEntry;
/**
- * RecipientChip defines a drawable object that contains information relevant to a
+ * BaseRecipientChip defines an object that contains information relevant to a
* particular recipient.
*/
-/* package */interface RecipientChip {
+interface BaseRecipientChip {
/**
* Set the selected state of the chip.
- * @param selected
*/
- public void setSelected(boolean selected);
+ void setSelected(boolean selected);
+
/**
* Return true if the chip is selected.
*/
- public boolean isSelected();
+ boolean isSelected();
/**
* Get the text displayed in the chip.
*/
- public CharSequence getDisplay();
+ CharSequence getDisplay();
/**
* Get the text value this chip represents.
*/
- public CharSequence getValue();
+ CharSequence getValue();
/**
* Get the id of the contact associated with this chip.
*/
- public long getContactId();
+ long getContactId();
/**
* Get the id of the data associated with this chip.
*/
- public long getDataId();
+ long getDataId();
/**
* Get associated RecipientEntry.
*/
- public RecipientEntry getEntry();
+ RecipientEntry getEntry();
/**
* Set the text in the edittextview originally associated with this chip
* before any reverse lookups.
*/
- public void setOriginalText(String text);
+ void setOriginalText(String text);
/**
* Set the text in the edittextview originally associated with this chip
* before any reverse lookups.
*/
- public CharSequence getOriginalText();
-
- /**
- * Get the bounds of the chip; may be 0,0 if it is not visibly rendered.
- */
- public Rect getBounds();
-
- /**
- * Draw the chip.
- */
- public void draw(Canvas canvas);
+ CharSequence getOriginalText();
}
diff --git a/chips/src/com/android/ex/chips/recipientchip/DrawableRecipientChip.java b/chips/src/com/android/ex/chips/recipientchip/DrawableRecipientChip.java
new file mode 100644
index 0000000..396a8ac
--- /dev/null
+++ b/chips/src/com/android/ex/chips/recipientchip/DrawableRecipientChip.java
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+package com.android.ex.chips.recipientchip;
+
+import android.graphics.Canvas;
+import android.graphics.Rect;
+
+/**
+ * RecipientChip defines a drawable object that contains information relevant to a
+ * particular recipient.
+ */
+public interface DrawableRecipientChip extends BaseRecipientChip {
+ /**
+ * Get the bounds of the chip; may be 0,0 if it is not visibly rendered.
+ */
+ Rect getBounds();
+
+ /**
+ * Draw the chip.
+ */
+ void draw(Canvas canvas);
+}
diff --git a/chips/src/com/android/ex/chips/recipientchip/InvisibleRecipientChip.java b/chips/src/com/android/ex/chips/recipientchip/InvisibleRecipientChip.java
new file mode 100644
index 0000000..0380a81
--- /dev/null
+++ b/chips/src/com/android/ex/chips/recipientchip/InvisibleRecipientChip.java
@@ -0,0 +1,105 @@
+/*
+ * 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.
+ */
+
+package com.android.ex.chips.recipientchip;
+
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.text.style.ReplacementSpan;
+
+import com.android.ex.chips.RecipientEntry;
+
+/**
+ * RecipientChip defines a span that contains information relevant to a
+ * particular recipient.
+ */
+public class InvisibleRecipientChip extends ReplacementSpan implements DrawableRecipientChip {
+ private final SimpleRecipientChip mDelegate;
+
+ public InvisibleRecipientChip(final RecipientEntry entry) {
+ super();
+
+ mDelegate = new SimpleRecipientChip(entry);
+ }
+
+ @Override
+ public void setSelected(final boolean selected) {
+ mDelegate.setSelected(selected);
+ }
+
+ @Override
+ public boolean isSelected() {
+ return mDelegate.isSelected();
+ }
+
+ @Override
+ public CharSequence getDisplay() {
+ return mDelegate.getDisplay();
+ }
+
+ @Override
+ public CharSequence getValue() {
+ return mDelegate.getValue();
+ }
+
+ @Override
+ public long getContactId() {
+ return mDelegate.getContactId();
+ }
+
+ @Override
+ public long getDataId() {
+ return mDelegate.getDataId();
+ }
+
+ @Override
+ public RecipientEntry getEntry() {
+ return mDelegate.getEntry();
+ }
+
+ @Override
+ public void setOriginalText(final String text) {
+ mDelegate.setOriginalText(text);
+ }
+
+ @Override
+ public CharSequence getOriginalText() {
+ return mDelegate.getOriginalText();
+ }
+
+ @Override
+ public void draw(final Canvas canvas, final CharSequence text, final int start, final int end,
+ final float x, final int top, final int y, final int bottom, final Paint paint) {
+ // Do nothing.
+ }
+
+ @Override
+ public int getSize(final Paint paint, final CharSequence text, final int start, final int end,
+ final Paint.FontMetricsInt fm) {
+ return 0;
+ }
+
+ @Override
+ public Rect getBounds() {
+ return new Rect(0, 0, 0, 0);
+ }
+
+ @Override
+ public void draw(final Canvas canvas) {
+ // do nothing.
+ }
+}
diff --git a/chips/src/com/android/ex/chips/VisibleRecipientChip.java b/chips/src/com/android/ex/chips/recipientchip/SimpleRecipientChip.java
index 49be32f..c04b3be 100644
--- a/chips/src/com/android/ex/chips/VisibleRecipientChip.java
+++ b/chips/src/com/android/ex/chips/recipientchip/SimpleRecipientChip.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 The Android Open Source Project
+ * 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.
@@ -14,20 +14,13 @@
* limitations under the License.
*/
-package com.android.ex.chips;
+package com.android.ex.chips.recipientchip;
+
+import com.android.ex.chips.RecipientEntry;
-import android.graphics.Canvas;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
import android.text.TextUtils;
-import android.text.style.DynamicDrawableSpan;
-import android.text.style.ImageSpan;
-/**
- * VisibleRecipientChip defines an ImageSpan that contains information relevant to a
- * particular recipient and renders a background asset to go with it.
- */
-/* package */class VisibleRecipientChip extends ImageSpan implements RecipientChip {
+class SimpleRecipientChip implements BaseRecipientChip {
private final CharSequence mDisplay;
private final CharSequence mValue;
@@ -36,14 +29,13 @@ import android.text.style.ImageSpan;
private final long mDataId;
- private RecipientEntry mEntry;
+ private final RecipientEntry mEntry;
private boolean mSelected = false;
private CharSequence mOriginalText;
- public VisibleRecipientChip(Drawable drawable, RecipientEntry entry, int offset) {
- super(drawable, DynamicDrawableSpan.ALIGN_BOTTOM);
+ public SimpleRecipientChip(final RecipientEntry entry) {
mDisplay = entry.getDisplayName();
mValue = entry.getDestination().trim();
mContactId = entry.getContactId();
@@ -51,79 +43,57 @@ import android.text.style.ImageSpan;
mEntry = entry;
}
- /**
- * Set the selected state of the chip.
- * @param selected
- */
- public void setSelected(boolean selected) {
+ @Override
+ public void setSelected(final boolean selected) {
mSelected = selected;
}
- /**
- * Return true if the chip is selected.
- */
+ @Override
public boolean isSelected() {
return mSelected;
}
- /**
- * Get the text displayed in the chip.
- */
+ @Override
public CharSequence getDisplay() {
return mDisplay;
}
- /**
- * Get the text value this chip represents.
- */
+ @Override
public CharSequence getValue() {
return mValue;
}
- /**
- * Get the id of the contact associated with this chip.
- */
+ @Override
public long getContactId() {
return mContactId;
}
- /**
- * Get the id of the data associated with this chip.
- */
+ @Override
public long getDataId() {
return mDataId;
}
- /**
- * Get associated RecipientEntry.
- */
+ @Override
public RecipientEntry getEntry() {
return mEntry;
}
- public void setOriginalText(String text) {
- if (!TextUtils.isEmpty(text)) {
- text = text.trim();
+ @Override
+ public void setOriginalText(final String text) {
+ if (TextUtils.isEmpty(text)) {
+ mOriginalText = text;
+ } else {
+ mOriginalText = text.trim();
}
- mOriginalText = text;
}
+ @Override
public CharSequence getOriginalText() {
return !TextUtils.isEmpty(mOriginalText) ? mOriginalText : mEntry.getDestination();
}
@Override
- public Rect getBounds() {
- return getDrawable().getBounds();
- }
-
- @Override
- public void draw(Canvas canvas) {
- getDrawable().draw(canvas);
- }
-
- @Override
public String toString() {
return mDisplay + " <" + mValue + ">";
}
-}
+} \ No newline at end of file
diff --git a/chips/src/com/android/ex/chips/recipientchip/VisibleRecipientChip.java b/chips/src/com/android/ex/chips/recipientchip/VisibleRecipientChip.java
new file mode 100644
index 0000000..acade7f
--- /dev/null
+++ b/chips/src/com/android/ex/chips/recipientchip/VisibleRecipientChip.java
@@ -0,0 +1,99 @@
+/*
+ * 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.
+ */
+
+package com.android.ex.chips.recipientchip;
+
+import android.graphics.Canvas;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.text.style.DynamicDrawableSpan;
+import android.text.style.ImageSpan;
+
+import com.android.ex.chips.RecipientEntry;
+
+/**
+ * VisibleRecipientChip defines an ImageSpan that contains information relevant to a
+ * particular recipient and renders a background asset to go with it.
+ */
+public class VisibleRecipientChip extends ImageSpan implements DrawableRecipientChip {
+ private final SimpleRecipientChip mDelegate;
+
+ public VisibleRecipientChip(final Drawable drawable, final RecipientEntry entry) {
+ super(drawable, DynamicDrawableSpan.ALIGN_BOTTOM);
+
+ mDelegate = new SimpleRecipientChip(entry);
+ }
+
+ @Override
+ public void setSelected(final boolean selected) {
+ mDelegate.setSelected(selected);
+ }
+
+ @Override
+ public boolean isSelected() {
+ return mDelegate.isSelected();
+ }
+
+ @Override
+ public CharSequence getDisplay() {
+ return mDelegate.getDisplay();
+ }
+
+ @Override
+ public CharSequence getValue() {
+ return mDelegate.getValue();
+ }
+
+ @Override
+ public long getContactId() {
+ return mDelegate.getContactId();
+ }
+
+ @Override
+ public long getDataId() {
+ return mDelegate.getDataId();
+ }
+
+ @Override
+ public RecipientEntry getEntry() {
+ return mDelegate.getEntry();
+ }
+
+ @Override
+ public void setOriginalText(final String text) {
+ mDelegate.setOriginalText(text);
+ }
+
+ @Override
+ public CharSequence getOriginalText() {
+ return mDelegate.getOriginalText();
+ }
+
+ @Override
+ public Rect getBounds() {
+ return getDrawable().getBounds();
+ }
+
+ @Override
+ public void draw(final Canvas canvas) {
+ getDrawable().draw(canvas);
+ }
+
+ @Override
+ public String toString() {
+ return mDelegate.toString();
+ }
+}
diff --git a/chips/tests/Android.mk b/chips/tests/Android.mk
index 313af7d..b01aa0c 100644
--- a/chips/tests/Android.mk
+++ b/chips/tests/Android.mk
@@ -20,7 +20,6 @@ LOCAL_PACKAGE_NAME := ChipsTests
LOCAL_MODULE_TAGS := tests
LOCAL_SDK_VERSION := current
LOCAL_CERTIFICATE := platform
-LOCAL_JAVA_LIBRARIES := android.test.runner
LOCAL_STATIC_JAVA_LIBRARIES += android-common-chips
LOCAL_RESOURCE_DIR := frameworks/ex/chips/res/
LOCAL_AAPT_FLAGS := --auto-add-overlay
diff --git a/chips/tests/src/com/android/ex/chips/ChipsTest.java b/chips/tests/src/com/android/ex/chips/ChipsTest.java
index 6639bcb..217594d 100644
--- a/chips/tests/src/com/android/ex/chips/ChipsTest.java
+++ b/chips/tests/src/com/android/ex/chips/ChipsTest.java
@@ -30,10 +30,12 @@ import android.widget.TextView;
import com.android.ex.chips.RecipientEditTextView;
import com.android.ex.chips.RecipientEntry;
+import com.android.ex.chips.recipientchip.DrawableRecipientChip;
+import com.android.ex.chips.recipientchip.VisibleRecipientChip;;
@SmallTest
public class ChipsTest extends AndroidTestCase {
- private RecipientChip[] mMockRecips;
+ private DrawableRecipientChip[] mMockRecips;
private RecipientEntry[] mMockEntries;
@@ -50,7 +52,7 @@ public class ChipsTest extends AndroidTestCase {
}
@Override
- public RecipientChip[] getSortedRecipients() {
+ public DrawableRecipientChip[] getSortedRecipients() {
return mMockRecips;
}
@@ -79,7 +81,7 @@ public class ChipsTest extends AndroidTestCase {
}
@Override
- public RecipientChip[] getSortedRecipients() {
+ public DrawableRecipientChip[] getSortedRecipients() {
return mMockRecips;
}
@@ -135,15 +137,15 @@ public class ChipsTest extends AndroidTestCase {
public void testCreateDisplayText() {
RecipientEditTextView view = createViewForTesting();
RecipientEntry entry = RecipientEntry.constructGeneratedEntry("User Name, Jr",
- "user@username.com");
+ "user@username.com", true);
String testAddress = view.createAddressText(entry);
String testDisplay = view.createChipDisplayText(entry);
assertEquals("Expected a properly formatted RFC email address",
"\"User Name, Jr\" <user@username.com>, ", testAddress);
assertEquals("Expected a displayable name", "User Name, Jr", testDisplay);
-
- RecipientEntry alreadyFormatted = RecipientEntry.constructFakeEntry("user@username.com, ");
+ RecipientEntry alreadyFormatted =
+ RecipientEntry.constructFakeEntry("user@username.com, ", true);
testAddress = view.createAddressText(alreadyFormatted);
testDisplay = view.createChipDisplayText(alreadyFormatted);
assertEquals("Expected a properly formatted RFC email address", "<user@username.com>, ",
@@ -151,13 +153,13 @@ public class ChipsTest extends AndroidTestCase {
assertEquals("Expected a displayable name", "user@username.com", testDisplay);
RecipientEntry alreadyFormattedNoSpace = RecipientEntry
- .constructFakeEntry("user@username.com,");
+ .constructFakeEntry("user@username.com,", true);
testAddress = view.createAddressText(alreadyFormattedNoSpace);
assertEquals("Expected a properly formatted RFC email address", "<user@username.com>, ",
testAddress);
RecipientEntry alreadyNamed = RecipientEntry.constructGeneratedEntry("User Name",
- "\"User Name, Jr\" <user@username.com>");
+ "\"User Name, Jr\" <user@username.com>", true);
testAddress = view.createAddressText(alreadyNamed);
testDisplay = view.createChipDisplayText(alreadyNamed);
assertEquals(
@@ -254,8 +256,8 @@ public class ChipsTest extends AndroidTestCase {
String first = (String) mTokenizer.terminateToken("FIRST");
String second = (String) mTokenizer.terminateToken("SECOND");
String third = (String) mTokenizer.terminateToken("THIRD");
- String fourth = (String) ("FOURTH,");
- String fifth = (String) ("FIFTH,");
+ String fourth = "FOURTH,";
+ String fifth = "FIFTH,";
mEditable = new SpannableStringBuilder();
mEditable.append(first+second+third+fourth+fifth);
assertEquals(view.countTokens(mEditable), 5);
@@ -620,7 +622,7 @@ public class ChipsTest extends AndroidTestCase {
mEditable.setSpan(mMockRecips[mMockRecips.length - 1], thirdStart, thirdEnd, 0);
assertEquals(mEditable.toString(), first + second + third);
view.replaceChip(mMockRecips[mMockRecips.length - 3], RecipientEntry
- .constructGeneratedEntry("replacement", "replacement@replacement.com"));
+ .constructGeneratedEntry("replacement", "replacement@replacement.com", true));
assertEquals(mEditable.toString(), mTokenizer
.terminateToken("replacement <replacement@replacement.com>")
+ second + third);
@@ -636,10 +638,11 @@ public class ChipsTest extends AndroidTestCase {
assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 1]), mEditable
.toString().indexOf(third)
+ third.trim().length());
- RecipientChip[] spans = mEditable.getSpans(0, mEditable.length(), RecipientChip.class);
+ DrawableRecipientChip[] spans =
+ mEditable.getSpans(0, mEditable.length(), DrawableRecipientChip.class);
assertEquals(spans.length, 3);
spans = mEditable
- .getSpans(0, mEditable.toString().indexOf(second) - 1, RecipientChip.class);
+ .getSpans(0, mEditable.toString().indexOf(second) - 1, DrawableRecipientChip.class);
assertEquals((String) spans[0].getDisplay(), "replacement");
@@ -657,7 +660,7 @@ public class ChipsTest extends AndroidTestCase {
mEditable.setSpan(mMockRecips[mMockRecips.length - 1], thirdStart, thirdEnd, 0);
assertEquals(mEditable.toString(), first + second + third);
view.replaceChip(mMockRecips[mMockRecips.length - 2], RecipientEntry
- .constructGeneratedEntry("replacement", "replacement@replacement.com"));
+ .constructGeneratedEntry("replacement", "replacement@replacement.com", true));
assertEquals(mEditable.toString(), first + mTokenizer
.terminateToken("replacement <replacement@replacement.com>") + third);
assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 3]), firstStart);
@@ -669,10 +672,10 @@ public class ChipsTest extends AndroidTestCase {
assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 1]), mEditable
.toString().indexOf(third)
+ third.trim().length());
- spans = mEditable.getSpans(0, mEditable.length(), RecipientChip.class);
+ spans = mEditable.getSpans(0, mEditable.length(), DrawableRecipientChip.class);
assertEquals(spans.length, 3);
- spans = mEditable
- .getSpans(firstEnd, mEditable.toString().indexOf(third) - 1, RecipientChip.class);
+ spans = mEditable.getSpans(firstEnd, mEditable.toString().indexOf(third) - 1,
+ DrawableRecipientChip.class);
assertEquals((String) spans[0].getDisplay(), "replacement");
@@ -690,7 +693,7 @@ public class ChipsTest extends AndroidTestCase {
mEditable.setSpan(mMockRecips[mMockRecips.length - 1], thirdStart, thirdEnd, 0);
assertEquals(mEditable.toString(), first + second + third);
view.replaceChip(mMockRecips[mMockRecips.length - 1], RecipientEntry
- .constructGeneratedEntry("replacement", "replacement@replacement.com"));
+ .constructGeneratedEntry("replacement", "replacement@replacement.com", true));
assertEquals(mEditable.toString(), first + second + mTokenizer
.terminateToken("replacement <replacement@replacement.com>"));
assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 3]), firstStart);
@@ -699,10 +702,10 @@ public class ChipsTest extends AndroidTestCase {
assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 2]), secondEnd);
assertEquals(mEditable.getSpanStart(mMockRecips[mMockRecips.length - 1]), -1);
assertEquals(mEditable.getSpanEnd(mMockRecips[mMockRecips.length - 1]), -1);
- spans = mEditable.getSpans(0, mEditable.length(), RecipientChip.class);
+ spans = mEditable.getSpans(0, mEditable.length(), DrawableRecipientChip.class);
assertEquals(spans.length, 3);
spans = mEditable
- .getSpans(secondEnd, mEditable.length(), RecipientChip.class);
+ .getSpans(secondEnd, mEditable.length(), DrawableRecipientChip.class);
assertEquals((String) spans[0].getDisplay(), "replacement");
}
@@ -717,7 +720,7 @@ public class ChipsTest extends AndroidTestCase {
mEditable.append("user@user.com");
view.setSelection(mEditable.length());
view.handlePaste();
- assertEquals(mEditable.getSpans(0, mEditable.length(), RecipientChip.class).length, 0);
+ assertEquals(mEditable.getSpans(0, mEditable.length(), DrawableRecipientChip.class).length, 0);
assertEquals(mEditable.toString(), "user@user.com");
// Test adding a single address to an empty chips field with a space at
@@ -727,7 +730,7 @@ public class ChipsTest extends AndroidTestCase {
mEditable.append(tokenizedUser);
view.setSelection(mEditable.length());
view.handlePaste();
- assertEquals(mEditable.getSpans(0, mEditable.length(), RecipientChip.class).length, 0);
+ assertEquals(mEditable.getSpans(0, mEditable.length(), DrawableRecipientChip.class).length, 0);
assertEquals(mEditable.toString(), tokenizedUser);
// Test adding a single address to an empty chips field with a semicolon at
@@ -737,7 +740,7 @@ public class ChipsTest extends AndroidTestCase {
mEditable.append(tokenizedUser);
view.setSelection(mEditable.length());
view.handlePaste();
- assertEquals(mEditable.getSpans(0, mEditable.length(), RecipientChip.class).length, 1);
+ assertEquals(mEditable.getSpans(0, mEditable.length(), DrawableRecipientChip.class).length, 1);
// Test adding 2 address to an empty chips field. The second to last
// address should become a chip and the last address should stay as
@@ -746,9 +749,9 @@ public class ChipsTest extends AndroidTestCase {
mEditable.append("user1,user2@user.com");
view.setSelection(mEditable.length());
view.handlePaste();
- assertEquals(mEditable.getSpans(0, mEditable.length(), RecipientChip.class).length, 1);
+ assertEquals(mEditable.getSpans(0, mEditable.length(), DrawableRecipientChip.class).length, 1);
assertEquals(mEditable.getSpans(0, mEditable.toString().indexOf("user2@user.com"),
- RecipientChip.class).length, 1);
+ DrawableRecipientChip.class).length, 1);
assertEquals(mEditable.toString(), "<user1>, user2@user.com");
// Test adding a single address to the end of existing chips. The existing
@@ -773,7 +776,7 @@ public class ChipsTest extends AndroidTestCase {
mEditable.append("user@user.com");
view.setSelection(mEditable.length());
view.handlePaste();
- assertEquals(mEditable.getSpans(0, mEditable.length(), RecipientChip.class).length,
+ assertEquals(mEditable.getSpans(0, mEditable.length(), DrawableRecipientChip.class).length,
mMockRecips.length);
assertEquals(mEditable.toString(), first + second + third + "user@user.com");
@@ -790,12 +793,12 @@ public class ChipsTest extends AndroidTestCase {
mEditable.append("user1, user2@user.com");
view.setSelection(mEditable.length());
view.handlePaste();
- assertEquals(mEditable.getSpans(0, mEditable.length(), RecipientChip.class).length,
+ assertEquals(mEditable.getSpans(0, mEditable.length(), DrawableRecipientChip.class).length,
mMockRecips.length + 1);
assertEquals(mEditable.getSpans(mEditable.toString().indexOf("<user1>"), mEditable
- .toString().indexOf("user2@user.com") - 1, RecipientChip.class).length, 1);
+ .toString().indexOf("user2@user.com") - 1, DrawableRecipientChip.class).length, 1);
assertEquals(mEditable.getSpans(mEditable.toString().indexOf("user2@user.com"), mEditable
- .length(), RecipientChip.class).length, 0);
+ .length(), DrawableRecipientChip.class).length, 0);
assertEquals(mEditable.toString(), first + second + third + "<user1>, user2@user.com");
// Paste 2 addresses after existing chips. We expect the first address to be turned into
@@ -812,12 +815,12 @@ public class ChipsTest extends AndroidTestCase {
mEditable.append("user1,user2@user.com");
view.setSelection(mEditable.length());
view.handlePaste();
- assertEquals(mEditable.getSpans(0, mEditable.length(), RecipientChip.class).length,
+ assertEquals(mEditable.getSpans(0, mEditable.length(), DrawableRecipientChip.class).length,
mMockRecips.length + 1);
assertEquals(mEditable.getSpans(mEditable.toString().indexOf("<user1>"), mEditable
- .toString().indexOf("user2@user.com") - 1, RecipientChip.class).length, 1);
+ .toString().indexOf("user2@user.com") - 1, DrawableRecipientChip.class).length, 1);
assertEquals(mEditable.getSpans(mEditable.toString().indexOf("user2@user.com"), mEditable
- .length(), RecipientChip.class).length, 0);
+ .length(), DrawableRecipientChip.class).length, 0);
assertEquals(mEditable.toString(), first + second + third + "<user1>, user2@user.com");
// Test a complete token pasted in at the end. It should be turned into a chip.
@@ -825,11 +828,11 @@ public class ChipsTest extends AndroidTestCase {
mEditable.append("user1, user2@user.com,");
view.setSelection(mEditable.length());
view.handlePaste();
- assertEquals(mEditable.getSpans(0, mEditable.length(), RecipientChip.class).length, 2);
+ assertEquals(mEditable.getSpans(0, mEditable.length(), DrawableRecipientChip.class).length, 2);
assertEquals(mEditable.getSpans(mEditable.toString().indexOf("<user1>"), mEditable
- .toString().indexOf("user2@user.com") - 1, RecipientChip.class).length, 1);
+ .toString().indexOf("user2@user.com") - 1, DrawableRecipientChip.class).length, 1);
assertEquals(mEditable.getSpans(mEditable.toString().indexOf("user2@user.com"), mEditable
- .length(), RecipientChip.class).length, 1);
+ .length(), DrawableRecipientChip.class).length, 1);
assertEquals(mEditable.toString(), "<user1>, <user2@user.com>, ");
}
@@ -922,11 +925,69 @@ public class ChipsTest extends AndroidTestCase {
mMockEntries = new RecipientEntry[size];
for (int i = 0; i < size; i++) {
mMockEntries[i] = RecipientEntry.constructGeneratedEntry("user",
- "user@username.com");
+ "user@username.com", true);
}
- mMockRecips = new RecipientChip[size];
+ mMockRecips = new DrawableRecipientChip[size];
for (int i = 0; i < size; i++) {
- mMockRecips[i] = new RecipientChip(null, mMockEntries[i], i);
+ mMockRecips[i] = new VisibleRecipientChip(null, mMockEntries[i]);
}
}
+
+ /**
+ * <p>
+ * Ensure the original text is always accurate, regardless of the type of email. The original
+ * text is used to determine where to display the chip span. If this test fails, it means some
+ * text that should be turned into one whole chip may behave unexpectedly.
+ * </p>
+ * <p>
+ * For example, a bug was seen where
+ *
+ * <pre>
+ * "Android User" <android@example.com>
+ * </pre>
+ *
+ * was converted to
+ *
+ * <pre>
+ * Android User [android@example.com]
+ * </pre>
+ *
+ * where text inside [] is a chip.
+ * </p>
+ */
+ public void testCreateReplacementChipOriginalText() {
+ // Name in quotes + email address
+ testCreateReplacementChipOriginalText("\"Android User\" <android@example.com>,");
+ // Name in quotes + email address without brackets
+ testCreateReplacementChipOriginalText("\"Android User\" android@example.com,");
+ // Name in quotes
+ testCreateReplacementChipOriginalText("\"Android User\",");
+ // Name without quotes + email address
+ testCreateReplacementChipOriginalText("Android User <android@example.com>,");
+ // Name without quotes
+ testCreateReplacementChipOriginalText("Android User,");
+ // Email address
+ testCreateReplacementChipOriginalText("<android@example.com>,");
+ // Email address without brackets
+ testCreateReplacementChipOriginalText("android@example.com,");
+ }
+
+ private void testCreateReplacementChipOriginalText(final String email) {
+ // No trailing space
+ attemptCreateReplacementChipOriginalText(email.trim());
+ // Trailing space
+ attemptCreateReplacementChipOriginalText(email.trim() + " ");
+ }
+
+ private void attemptCreateReplacementChipOriginalText(final String email) {
+ final RecipientEditTextView view = new RecipientEditTextView(getContext(), null);
+
+ view.setText(email);
+ view.mPendingChips.add(email);
+
+ view.createReplacementChip(0, email.length(), view.getText(), true);
+ // The "original text" should be the email without the comma or space(s)
+ assertEquals(email.replaceAll(",\\s*$", ""),
+ view.mTemporaryRecipients.get(0).getOriginalText().toString().trim());
+ }
}
diff --git a/chips/tests/src/com/android/ex/chips/RecipientAlternatesAdapterTest.java b/chips/tests/src/com/android/ex/chips/RecipientAlternatesAdapterTest.java
index f4b87c0..a1a1c7a 100644
--- a/chips/tests/src/com/android/ex/chips/RecipientAlternatesAdapterTest.java
+++ b/chips/tests/src/com/android/ex/chips/RecipientAlternatesAdapterTest.java
@@ -18,8 +18,13 @@ package com.android.ex.chips;
import android.database.Cursor;
import android.database.MatrixCursor;
+import android.net.Uri;
+import android.provider.ContactsContract.DisplayNameSources;
import android.test.AndroidTestCase;
+import com.android.ex.chips.RecipientAlternatesAdapter;
+import com.android.ex.chips.RecipientEntry;
+
public class RecipientAlternatesAdapterTest extends AndroidTestCase {
public void testRemoveDuplicateDestinations() {
@@ -99,4 +104,55 @@ public class RecipientAlternatesAdapterTest extends AndroidTestCase {
assertEquals(photoUri, c.getString(6));
assertEquals(displayNameSource, c.getInt(7));
}
+
+ public void testGetBetterRecipient() {
+ // Ensure that if either (but not both) parameters are null, the other is returned
+ {
+ final RecipientEntry entry1 =
+ RecipientEntry.constructFakeEntry("1@android.com", true);
+ final RecipientEntry entry2 = null;
+
+ assertEquals(RecipientAlternatesAdapter.getBetterRecipient(entry1, entry2), entry1);
+ assertEquals(RecipientAlternatesAdapter.getBetterRecipient(entry2, entry1), entry1);
+ }
+
+ // Ensure that if only one has a display name, it is used
+ {
+ final RecipientEntry entry1 =
+ RecipientEntry.constructTopLevelEntry("Android", DisplayNameSources.NICKNAME,
+ "1@android.com", 0, null, 0, 0, (Uri) null, true);
+ final RecipientEntry entry2 = RecipientEntry.constructFakeEntry("1@android.com", true);
+
+ assertEquals(RecipientAlternatesAdapter.getBetterRecipient(entry1, entry2), entry1);
+ assertEquals(RecipientAlternatesAdapter.getBetterRecipient(entry2, entry1), entry1);
+ }
+
+ // Ensure that if one has a display name different from its destination, and the other's
+ // is equal to its destination, we use the unique one
+ {
+ final RecipientEntry entry1 =
+ RecipientEntry.constructTopLevelEntry("Android", DisplayNameSources.NICKNAME,
+ "1@android.com", 0, null, 0, 0, (Uri) null, true);
+ final RecipientEntry entry2 =
+ RecipientEntry.constructTopLevelEntry("2@android.com", DisplayNameSources.EMAIL,
+ "2@android.com", 0, null, 0, 0, (Uri) null, true);
+
+ assertEquals(RecipientAlternatesAdapter.getBetterRecipient(entry1, entry2), entry1);
+ assertEquals(RecipientAlternatesAdapter.getBetterRecipient(entry2, entry1), entry1);
+ }
+
+ // Ensure that if only one has a photo, it is used
+ {
+ final RecipientEntry entry1 =
+ RecipientEntry.constructTopLevelEntry("Android", DisplayNameSources.NICKNAME,
+ "1@android.com", 0, null, 0, 0, Uri.parse("http://www.android.com"),
+ true);
+ final RecipientEntry entry2 =
+ RecipientEntry.constructTopLevelEntry("Android", DisplayNameSources.EMAIL,
+ "2@android.com", 0, null, 0, 0, (Uri) null, true);
+
+ assertEquals(RecipientAlternatesAdapter.getBetterRecipient(entry1, entry2), entry1);
+ assertEquals(RecipientAlternatesAdapter.getBetterRecipient(entry2, entry1), entry1);
+ }
+ }
}