package com.simplecity.amp_library.format;
import android.content.Context;
import android.text.SpannableString;
import android.text.TextUtils;
import android.text.style.ForegroundColorSpan;
import android.widget.TextView;
import com.simplecity.amp_library.utils.ColorUtils;
/**
* Highlights the text in a text field
*/
public class PrefixHighlighter {
private final int mPrefixHighlightColor;
private ForegroundColorSpan mPrefixColorSpan;
public PrefixHighlighter(Context context) {
mPrefixHighlightColor = ColorUtils.getContrastAwareColorAccent(context);
}
/**
* Sets the text on the given {@link TextView}, highlighting the word that
* matches the given prefix
*
* @param view The {@link TextView} on which to set the text
* @param prefix The prefix to look for
*/
public void setText(TextView view, char[] prefix) {
setText(view, view.getText().toString(), prefix);
}
/**
* Sets the text on the given {@link TextView}, highlighting the word that
* matches the given prefix
*
* @param view The {@link TextView} on which to set the text
* @param text The string to use as the text
* @param prefix The prefix to look for
*/
public void setText(TextView view, String text, char[] prefix) {
if (view == null) {
return;
}
if ((prefix == null || prefix.length == 0)) {
view.setText(text);
} else if (!TextUtils.isEmpty(text)) {
view.setText(apply(text, prefix));
}
}
/**
* Returns a {@link CharSequence} which highlights the given prefix if found
* in the given text
*
* @param text the text to which to apply the highlight
* @param prefix the prefix to look for
*/
private CharSequence apply(CharSequence text, char[] prefix) {
final int index = indexOfWordPrefix(text, prefix);
if (index != -1) {
if (mPrefixColorSpan == null) {
mPrefixColorSpan = new ForegroundColorSpan(mPrefixHighlightColor);
}
final SpannableString result = new SpannableString(text);
result.setSpan(mPrefixColorSpan, index, index + prefix.length, 0);
return result;
} else {
return text;
}
}
/**
* Finds the index of the first word that starts with the given prefix. If
* not found, returns -1
*
* @param text the text in which to search for the prefix
* @param prefix the text to find, in upper case letters
*/
private static int indexOfWordPrefix(CharSequence text, char[] prefix) {
if (TextUtils.isEmpty(text) || prefix == null) {
return -1;
}
final int tlen = text.length();
final int plen = prefix.length;
if (plen == 0 || tlen < plen) {
return -1;
}
int i = 0;
while (i < tlen) {
// Skip non-word characters
while (i < tlen && !Character.isLetterOrDigit(text.charAt(i))) {
i++;
}
if (i + plen > tlen) {
return -1;
}
// Compare the prefixes
int j;
for (j = 0; j < plen; j++) {
if (Character.toUpperCase(text.charAt(i + j)) != prefix[j]) {
break;
}
}
if (j == plen) {
return i;
}
// Skip this word
while (i < tlen && Character.isLetterOrDigit(text.charAt(i))) {
i++;
}
}
return -1;
}
}