SuggestionSpanUtils.java revision add3e053797d7d2355c61160ab746f7dfeb92aef
1/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.inputmethod.compat;
18
19import com.android.inputmethod.latin.SuggestedWords;
20import com.android.inputmethod.latin.SuggestionSpanPickedNotificationReceiver;
21
22import android.content.Context;
23import android.text.Spannable;
24import android.text.SpannableString;
25import android.text.Spanned;
26import android.text.TextUtils;
27
28import java.lang.reflect.Constructor;
29import java.util.ArrayList;
30import java.util.Locale;
31
32public class SuggestionSpanUtils {
33    // TODO: Use reflection to get field values
34    public static final String ACTION_SUGGESTION_PICKED =
35            "android.text.style.SUGGESTION_PICKED";
36    public static final String SUGGESTION_SPAN_PICKED_AFTER = "after";
37    public static final String SUGGESTION_SPAN_PICKED_BEFORE = "before";
38    public static final String SUGGESTION_SPAN_PICKED_HASHCODE = "hashcode";
39    public static final int SUGGESTION_MAX_SIZE = 5;
40    public static final boolean SUGGESTION_SPAN_IS_SUPPORTED;
41
42    private static final Class<?> CLASS_SuggestionSpan = CompatUtils
43            .getClass("android.text.style.SuggestionSpan");
44    private static final Class<?>[] INPUT_TYPE_SuggestionSpan = new Class<?>[] {
45            Context.class, Locale.class, String[].class, int.class, Class.class };
46    private static final Constructor<?> CONSTRUCTOR_SuggestionSpan = CompatUtils
47            .getConstructor(CLASS_SuggestionSpan, INPUT_TYPE_SuggestionSpan);
48    static {
49        SUGGESTION_SPAN_IS_SUPPORTED =
50                CLASS_SuggestionSpan != null && CONSTRUCTOR_SuggestionSpan != null;
51    }
52
53    public static CharSequence getTextWithSuggestionSpan(Context context,
54            CharSequence pickedWord, SuggestedWords suggestedWords) {
55        if (TextUtils.isEmpty(pickedWord) || CONSTRUCTOR_SuggestionSpan == null
56                || suggestedWords == null || suggestedWords.size() == 0
57                || suggestedWords.getInfo(0).isObsoleteSuggestedWord()) {
58            return pickedWord;
59        }
60
61        final Spannable spannable;
62        if (pickedWord instanceof Spannable) {
63            spannable = (Spannable) pickedWord;
64        } else {
65            spannable = new SpannableString(pickedWord);
66        }
67        final ArrayList<String> suggestionsList = new ArrayList<String>();
68        for (int i = 0; i < suggestedWords.size(); ++i) {
69            if (suggestionsList.size() >= SUGGESTION_MAX_SIZE) {
70                break;
71            }
72            final CharSequence word = suggestedWords.getWord(i);
73            if (!TextUtils.equals(pickedWord, word)) {
74                suggestionsList.add(word.toString());
75            }
76        }
77
78        final Object[] args =
79                { context, null, suggestionsList.toArray(new String[suggestionsList.size()]), 0,
80                        (Class<?>) SuggestionSpanPickedNotificationReceiver.class };
81        final Object ss = CompatUtils.newInstance(CONSTRUCTOR_SuggestionSpan, args);
82        if (ss == null) {
83            return pickedWord;
84        }
85        spannable.setSpan(ss, 0, pickedWord.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
86        return spannable;
87    }
88}
89