summaryrefslogtreecommitdiffstats
path: root/src/org/lineageos/eleven/format/PrefixHighlighter.java
blob: 83f69a70f2384ed65515526ee3ab5cdb60c3f54c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/*
 * 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.cyanogenmod.eleven.format;

import android.content.Context;
import android.text.SpannableString;
import android.text.TextUtils;
import android.text.style.ForegroundColorSpan;
import android.widget.TextView;

import com.cyanogenmod.eleven.utils.PreferenceUtils;

/**
 * Highlights the text in a text field.
 */
public class PrefixHighlighter {

    /* Color used when highlighting the prefixes */
    private final int mPrefixHighlightColor;

    private ForegroundColorSpan mPrefixColorSpan;

    /**
     * @param prefixHighlightColor The color used to highlight the prefixes.
     */
    public PrefixHighlighter(final Context context) {
        mPrefixHighlightColor = PreferenceUtils.getInstance(context).getDefaultThemeColor(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 text The string to use as the text
     * @param prefix The prefix to look for
     */
    public void setText(final TextView view, final String text, final char[] prefix) {
        if (view == null || TextUtils.isEmpty(text) || prefix == null || prefix.length == 0) {
            return;
        }
        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
     */
    public CharSequence apply(final CharSequence text, final char[] prefix) {
        int mIndex = indexOfPrefix(text, prefix, true);
        // prefer word prefix, if not search through the entire word
        if (mIndex == -1) {
            mIndex = indexOfPrefix(text, prefix, false);
        }

        if (mIndex != -1) {
            if (mPrefixColorSpan == null) {
                mPrefixColorSpan = new ForegroundColorSpan(mPrefixHighlightColor);
            }
            final SpannableString mResult = new SpannableString(text);
            mResult.setSpan(mPrefixColorSpan, mIndex, mIndex + prefix.length, 0);
            return mResult;
        } else {
            return text;
        }
    }

    /**
     * Finds the index of the first character 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
     * @param wordOnly only search for word prefixes if true
     */
    private int indexOfPrefix(final CharSequence text, final char[] prefix, boolean wordOnly) {
        if (TextUtils.isEmpty(text) || prefix == null) {
            return -1;
        }

        final int mTextLength = text.length();
        final int mPrefixLength = prefix.length;

        if (mPrefixLength == 0 || mTextLength < mPrefixLength) {
            return -1;
        }

        int i = 0;
        while (i < mTextLength) {
            /* Skip non-word characters */
            while (i < mTextLength && !Character.isLetterOrDigit(text.charAt(i))) {
                i++;
            }

            if (i + mPrefixLength > mTextLength) {
                return -1;
            }

            /* Compare the prefixes */
            int j;
            for (j = 0; j < mPrefixLength; j++) {
                if (Character.toUpperCase(text.charAt(i + j)) != prefix[j]) {
                    break;
                }
            }
            if (j == mPrefixLength) {
                return i;
            }

            if (wordOnly) {
                /* Skip this word */
                while (i < mTextLength && Character.isLetterOrDigit(text.charAt(i))) {
                    i++;
                }
            } else {
                i++;
            }
        }
        return -1;
    }
}