Changes ContactListItemView highlighting scheme.

- Re-match smart dial query every time in BindView.

Change-Id: I42a54948481fead693db5a2db188bcc31202d6ee
diff --git a/src/com/android/contacts/common/format/SpannedTestUtils.java b/src/com/android/contacts/common/format/SpannedTestUtils.java
index d385c92..1fee7d1 100644
--- a/src/com/android/contacts/common/format/SpannedTestUtils.java
+++ b/src/com/android/contacts/common/format/SpannedTestUtils.java
@@ -18,6 +18,7 @@
 
 import android.test.suitebuilder.annotation.SmallTest;
 import android.text.Html;
+import android.text.SpannableString;
 import android.text.Spanned;
 import android.text.TextUtils;
 import android.text.style.ForegroundColorSpan;
@@ -81,10 +82,7 @@
         Assert.assertEquals(expected, seq);
     }
 
-    public static int getNextTransition(CharSequence seq, int start) {
-        Assert.assertTrue(seq instanceof Spanned);
-        final Spanned spannable = (Spanned) seq;
-
-        return spannable.nextSpanTransition(start, seq.length(), ForegroundColorSpan.class);
+    public static int getNextTransition(SpannableString seq, int start) {
+        return seq.nextSpanTransition(start, seq.length(), ForegroundColorSpan.class);
     }
 }
diff --git a/src/com/android/contacts/common/format/TextHighlighter.java b/src/com/android/contacts/common/format/TextHighlighter.java
index e0eb28c..648b1d5 100644
--- a/src/com/android/contacts/common/format/TextHighlighter.java
+++ b/src/com/android/contacts/common/format/TextHighlighter.java
@@ -50,43 +50,14 @@
     }
 
     /**
-     * Sets a mask for text highlighting. The mask should be a string of the same length as text,
-     * where each character is either 0 or 1. If the character is 1, the letter in text at the same
-     * position should be highlighted. Otherwise the letter should not be highlighted.
-     *
-     * @param view TextView where the highlighted text should go.
-     * @param text Text to be highlighted.
-     * @param mask Mask indicating which letter to highlight.
-     */
-    public void setMaskingText(TextView view, String text, String mask) {
-        view.setText(applyMaskingHighlight(text, mask));
-    }
-
-    /**
      * Applies highlight span to the text.
      * @param text Text sequence to be highlighted.
-     * @param mask Mask indicating where highlight should be.
-     * @return Highlighted text sequence.
+     * @param start Start position of the highlight sequence.
+     * @param end End position of the highlight sequence.
      */
-    public CharSequence applyMaskingHighlight(CharSequence text, String mask) {
-        Preconditions.checkNotNull(text);
-        Preconditions.checkNotNull(mask);
-
-        if (text.length() != mask.length() || text.length() == 0) {
-            if (DEBUG) {
-                Log.v(TAG, "Mask size mismatch or text length is 0" + text + " " + mask);
-            }
-            return text;
-        }
-
+    public void applyMaskingHighlight(SpannableString text, int start, int end) {
         /** Sets text color of the masked locations to be highlighted. */
-        final SpannableString result = new SpannableString(text);
-        for (int i = 0; i < mask.length(); ++i) {
-            if (mask.charAt(i) == '1') {
-                 result.setSpan(new ForegroundColorSpan(mTextHighlightColor), i, i + 1, 0);
-            }
-        }
-        return result;
+        text.setSpan(new ForegroundColorSpan(mTextHighlightColor), start, end, 0);
     }
 
     /**
diff --git a/src/com/android/contacts/common/list/ContactListItemView.java b/src/com/android/contacts/common/list/ContactListItemView.java
index 85d6bf8..1f1d785 100644
--- a/src/com/android/contacts/common/list/ContactListItemView.java
+++ b/src/com/android/contacts/common/list/ContactListItemView.java
@@ -34,6 +34,7 @@
 import android.text.TextUtils;
 import android.text.TextUtils.TruncateAt;
 import android.util.AttributeSet;
+import android.util.Log;
 import android.util.TypedValue;
 import android.view.Gravity;
 import android.view.View;
@@ -110,9 +111,18 @@
     private Drawable mHorizontalDividerDrawable;
     private int mHorizontalDividerHeight;
 
-    // Highlighting Masks for the name and number.
-    private String mNameHighlightMask;
-    private String mNumberHighlightMask;
+    protected static class HighlightSequence {
+        private final int start;
+        private final int end;
+
+        HighlightSequence(int start, int end) {
+            this.start = start;
+            this.end = end;
+        }
+    }
+
+    private ArrayList<HighlightSequence> mNameHighlightSequence;
+    private ArrayList<HighlightSequence> mNumberHighlightSequence;
 
     // Highlighting prefix for names.
     private String mHighlightedPrefix;
@@ -305,6 +315,9 @@
         if (mActivatedBackgroundDrawable != null) {
             mActivatedBackgroundDrawable.setCallback(this);
         }
+
+        mNameHighlightSequence = new ArrayList<HighlightSequence>();
+        mNumberHighlightSequence = new ArrayList<HighlightSequence>();
     }
 
     public void setUnknownNameText(CharSequence unknownNameText) {
@@ -866,26 +879,33 @@
      */
     public void setHighlightedPrefix(String upperCasePrefix) {
         mHighlightedPrefix = upperCasePrefix;
-        mNameHighlightMask = null;
     }
 
     /**
-     * Sets a highlighting mask for names. This will disable the prefix highlighting.
-     *
-     * @param highlightMask A string of 0 and 1's to indicate which letter to highlight
+     * Clears previously set highlight sequences for the view.
      */
-    public void setHighlightMask(String highlightMask) {
-        mNameHighlightMask = highlightMask;
+    public void clearHighlightSequences() {
+        mNameHighlightSequence.clear();
+        mNumberHighlightSequence.clear();
         mHighlightedPrefix = null;
     }
 
     /**
-     * Sets a highlighting mask for numbers.
-     *
-     * @param highlightMask A string of 0 and 1's to indicate which digit to highlight.
+     * Adds a highlight sequence to the name highlighter.
+     * @param start The start position of the highlight sequence.
+     * @param end The end position of the highlight sequence.
      */
-    public void setNumberHighlightMask(String highlightMask) {
-        mNumberHighlightMask = highlightMask;
+    public void addNameHighlightSequence(int start, int end) {
+        mNameHighlightSequence.add(new HighlightSequence(start, end));
+    }
+
+    /**
+     * Adds a highlight sequence to the number highlighter.
+     * @param start The start position of the highlight sequence.
+     * @param end The end position of the highlight sequence.
+     */
+    public void addNumberHighlightSequence(int start, int end) {
+        mNumberHighlightSequence.add(new HighlightSequence(start, end));
     }
 
     /**
@@ -1005,11 +1025,15 @@
         } else {
             getDataView();
             // Sets phone number texts for display after highlighting it, if applicable.
-            CharSequence textToSet = text;
-            if (mNumberHighlightMask != null) {
-                textToSet = mTextHighlighter.applyMaskingHighlight(text,
-                        mNumberHighlightMask);
+            //CharSequence textToSet = text;
+            final SpannableString textToSet = new SpannableString(text);
+
+            if (mNumberHighlightSequence.size() != 0) {
+                final HighlightSequence highlightSequence = mNumberHighlightSequence.get(0);
+                mTextHighlighter.applyMaskingHighlight(textToSet, highlightSequence.start,
+                        highlightSequence.end);
             }
+
             setMarqueeText(mDataView, textToSet);
             mDataView.setVisibility(VISIBLE);
 
@@ -1065,12 +1089,7 @@
                 mSnippetView.setVisibility(View.GONE);
             }
         } else {
-            // Chooses a highlighting method for text highlighting.
-            if (mHighlightedPrefix != null) {
-                mTextHighlighter.setPrefixText(getSnippetView(), text, mHighlightedPrefix);
-            } else if (mNameHighlightMask != null) {
-                mTextHighlighter.setMaskingText(getSnippetView(), text, mNameHighlightMask);
-            }
+            mTextHighlighter.setPrefixText(getSnippetView(), text, mHighlightedPrefix);
             mSnippetView.setVisibility(VISIBLE);
         }
     }
@@ -1185,8 +1204,13 @@
             // Chooses the available highlighting method for highlighting.
             if (mHighlightedPrefix != null) {
                 name = mTextHighlighter.applyPrefixHighlight(name, mHighlightedPrefix);
-            } else if (mNameHighlightMask != null) {
-                name = mTextHighlighter.applyMaskingHighlight(name, mNameHighlightMask);
+            } else if (mNameHighlightSequence.size() != 0) {
+                final SpannableString spannableName = new SpannableString(name);
+                for (HighlightSequence highlightSequence : mNameHighlightSequence) {
+                    mTextHighlighter.applyMaskingHighlight(spannableName, highlightSequence.start,
+                            highlightSequence.end);
+                }
+                name = spannableName;
             }
         } else {
             name = mUnknownNameText;
diff --git a/tests/src/com/android/contacts/common/format/TextHighlighterTest.java b/tests/src/com/android/contacts/common/format/TextHighlighterTest.java
index 2009c31..f6962f8 100644
--- a/tests/src/com/android/contacts/common/format/TextHighlighterTest.java
+++ b/tests/src/com/android/contacts/common/format/TextHighlighterTest.java
@@ -17,6 +17,7 @@
 package com.android.contacts.common.format;
 
 import android.test.suitebuilder.annotation.SmallTest;
+import android.text.SpannableString;
 
 import com.android.contacts.common.format.SpannedTestUtils;
 
@@ -86,25 +87,33 @@
     }
 
     public void testSetMask_LengthMismatch() {
-        final String mask = "001101";
-        CharSequence seq = mTextHighlighter.applyMaskingHighlight("atest", mask);
+        final SpannableString testString1 = new SpannableString("atest");
+        mTextHighlighter.applyMaskingHighlight(testString1, 0, 0);
+        CharSequence seq = testString1;
         SpannedTestUtils.assertNotSpanned(seq, "atest");
 
-        seq = mTextHighlighter.applyMaskingHighlight("alongtest", mask);
-        SpannedTestUtils.assertNotSpanned(seq, "alongtest");
-
-        seq = mTextHighlighter.applyMaskingHighlight("", mask);
+        final SpannableString testString2 = new SpannableString("");
+        mTextHighlighter.applyMaskingHighlight(testString2, 0, 0);
+        seq = testString2;
         SpannedTestUtils.assertNotSpanned(seq, "");
     }
 
     public void testSetMask_Highlight() {
-        final String mask = "001101011";
-        CharSequence seq = mTextHighlighter.applyMaskingHighlight("alongtest", mask);
-        assertEquals(SpannedTestUtils.getNextTransition(seq, 0), 2);
-        assertEquals(SpannedTestUtils.getNextTransition(seq, 2), 4);
-        assertEquals(SpannedTestUtils.getNextTransition(seq, 4), 5);
-        assertEquals(SpannedTestUtils.getNextTransition(seq, 5), 6);
-        assertEquals(SpannedTestUtils.getNextTransition(seq, 6), 7);
-        assertEquals(SpannedTestUtils.getNextTransition(seq, 7), 9);
+        final SpannableString testString1 = new SpannableString("alongtest");
+        mTextHighlighter.applyMaskingHighlight(testString1, 2, 4);
+        assertEquals(SpannedTestUtils.getNextTransition(testString1, 0), 2);
+        assertEquals(SpannedTestUtils.getNextTransition(testString1, 2), 4);
+
+        mTextHighlighter.applyMaskingHighlight(testString1, 3, 6);
+        assertEquals(SpannedTestUtils.getNextTransition(testString1, 0), 2);
+        assertEquals(SpannedTestUtils.getNextTransition(testString1, 2), 6);
+
+        mTextHighlighter.applyMaskingHighlight(testString1, 4, 5);
+        assertEquals(SpannedTestUtils.getNextTransition(testString1, 2), 6);
+
+        mTextHighlighter.applyMaskingHighlight(testString1, 7, 8);
+        assertEquals(SpannedTestUtils.getNextTransition(testString1, 2), 6);
+        assertEquals(SpannedTestUtils.getNextTransition(testString1, 6), 7);
+        assertEquals(SpannedTestUtils.getNextTransition(testString1, 7), 8);
     }
 }