OSDN Git Service

Update Eleven headers and namespace for open source
[android-x86/packages-apps-Eleven.git] / src / com / cyanogenmod / eleven / format / PrefixHighlighter.java
1 /*
2  * Copyright (C) 2011 The Android Open Source Project Licensed under the Apache
3  * License, Version 2.0 (the "License"); you may not use this file except in
4  * compliance with the License. You may obtain a copy of the License at
5  * http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law
6  * or agreed to in writing, software distributed under the License is
7  * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
8  * KIND, either express or implied. See the License for the specific language
9  * governing permissions and limitations under the License.
10  */
11
12 package com.cyanogenmod.eleven.format;
13
14 import android.content.Context;
15 import android.text.SpannableString;
16 import android.text.TextUtils;
17 import android.text.style.ForegroundColorSpan;
18 import android.widget.TextView;
19
20 import com.cyanogenmod.eleven.utils.PreferenceUtils;
21
22 /**
23  * Highlights the text in a text field.
24  */
25 public class PrefixHighlighter {
26
27     /* Color used when highlighting the prefixes */
28     private final int mPrefixHighlightColor;
29
30     private ForegroundColorSpan mPrefixColorSpan;
31
32     /**
33      * @param prefixHighlightColor The color used to highlight the prefixes.
34      */
35     public PrefixHighlighter(final Context context) {
36         mPrefixHighlightColor = PreferenceUtils.getInstance(context).getDefaultThemeColor(context);
37     }
38
39     /**
40      * Sets the text on the given {@link TextView}, highlighting the word that
41      * matches the given prefix.
42      * 
43      * @param view The {@link TextView} on which to set the text
44      * @param text The string to use as the text
45      * @param prefix The prefix to look for
46      */
47     public void setText(final TextView view, final String text, final char[] prefix) {
48         if (view == null || TextUtils.isEmpty(text) || prefix == null || prefix.length == 0) {
49             return;
50         }
51         view.setText(apply(text, prefix));
52     }
53
54     /**
55      * Returns a {@link CharSequence} which highlights the given prefix if found
56      * in the given text.
57      * 
58      * @param text the text to which to apply the highlight
59      * @param prefix the prefix to look for
60      */
61     public CharSequence apply(final CharSequence text, final char[] prefix) {
62         int mIndex = indexOfPrefix(text, prefix, true);
63         // prefer word prefix, if not search through the entire word
64         if (mIndex == -1) {
65             mIndex = indexOfPrefix(text, prefix, false);
66         }
67
68         if (mIndex != -1) {
69             if (mPrefixColorSpan == null) {
70                 mPrefixColorSpan = new ForegroundColorSpan(mPrefixHighlightColor);
71             }
72             final SpannableString mResult = new SpannableString(text);
73             mResult.setSpan(mPrefixColorSpan, mIndex, mIndex + prefix.length, 0);
74             return mResult;
75         } else {
76             return text;
77         }
78     }
79
80     /**
81      * Finds the index of the first character that starts with the given prefix. If
82      * not found, returns -1.
83      * 
84      * @param text the text in which to search for the prefix
85      * @param prefix the text to find, in upper case letters
86      * @param wordOnly only search for word prefixes if true
87      */
88     private int indexOfPrefix(final CharSequence text, final char[] prefix, boolean wordOnly) {
89         if (TextUtils.isEmpty(text) || prefix == null) {
90             return -1;
91         }
92
93         final int mTextLength = text.length();
94         final int mPrefixLength = prefix.length;
95
96         if (mPrefixLength == 0 || mTextLength < mPrefixLength) {
97             return -1;
98         }
99
100         int i = 0;
101         while (i < mTextLength) {
102             /* Skip non-word characters */
103             while (i < mTextLength && !Character.isLetterOrDigit(text.charAt(i))) {
104                 i++;
105             }
106
107             if (i + mPrefixLength > mTextLength) {
108                 return -1;
109             }
110
111             /* Compare the prefixes */
112             int j;
113             for (j = 0; j < mPrefixLength; j++) {
114                 if (Character.toUpperCase(text.charAt(i + j)) != prefix[j]) {
115                     break;
116                 }
117             }
118             if (j == mPrefixLength) {
119                 return i;
120             }
121
122             if (wordOnly) {
123                 /* Skip this word */
124                 while (i < mTextLength && Character.isLetterOrDigit(text.charAt(i))) {
125                     i++;
126                 }
127             } else {
128                 i++;
129             }
130         }
131         return -1;
132     }
133 }