blob: de38fbea6e5a6cd5037f7f770fd7986f239fbb29 [file] [log] [blame]
satokab751aa2010-09-14 19:17:36 +09001/*
2 * Copyright (C) 2010 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 android.view.inputmethod;
18
satok7265d9b2011-02-14 15:47:30 +090019import android.content.Context;
satokab751aa2010-09-14 19:17:36 +090020import android.os.Parcel;
21import android.os.Parcelable;
satok9c4cc032011-02-14 18:03:32 +090022import android.util.Slog;
satokab751aa2010-09-14 19:17:36 +090023
satok7265d9b2011-02-14 15:47:30 +090024import java.util.ArrayList;
satokab751aa2010-09-14 19:17:36 +090025import java.util.Arrays;
satok9c4cc032011-02-14 18:03:32 +090026import java.util.HashMap;
satok7265d9b2011-02-14 15:47:30 +090027import java.util.HashSet;
28import java.util.List;
satokab751aa2010-09-14 19:17:36 +090029
30/**
Ken Wakasae31e9422011-01-21 15:36:05 +090031 * This class is used to specify meta information of a subtype contained in an input method.
32 * Subtype can describe locale (e.g. en_US, fr_FR...) and mode (e.g. voice, keyboard...), and is
33 * used for IME switch and settings. The input method subtype allows the system to bring up the
34 * specified subtype of the designated input method directly.
satokab751aa2010-09-14 19:17:36 +090035 */
36public final class InputMethodSubtype implements Parcelable {
satok9c4cc032011-02-14 18:03:32 +090037 private static final String TAG = InputMethodSubtype.class.getSimpleName();
38 private static final String EXTRA_VALUE_PAIR_SEPARATOR = ",";
39 private static final String EXTRA_VALUE_KEY_VALUE_SEPARATOR = "=";
40
satok9aabb952011-05-06 15:41:37 +090041 private final boolean mIsAuxiliary;
42 private final int mSubtypeHashCode;
satokab751aa2010-09-14 19:17:36 +090043 private final int mSubtypeIconResId;
satok9aabb952011-05-06 15:41:37 +090044 private final int mSubtypeNameResId;
satokab751aa2010-09-14 19:17:36 +090045 private final String mSubtypeLocale;
satok9ef02832010-11-04 21:17:48 +090046 private final String mSubtypeMode;
satokab751aa2010-09-14 19:17:36 +090047 private final String mSubtypeExtraValue;
satok9c4cc032011-02-14 18:03:32 +090048 private HashMap<String, String> mExtraValueHashMapCache;
satokab751aa2010-09-14 19:17:36 +090049
50 /**
51 * Constructor
52 * @param nameId The name of the subtype
53 * @param iconId The icon of the subtype
54 * @param locale The locale supported by the subtype
55 * @param modeId The mode supported by the subtype
56 * @param extraValue The extra value of the subtype
57 */
satok9ef02832010-11-04 21:17:48 +090058 InputMethodSubtype(int nameId, int iconId, String locale, String mode, String extraValue) {
satok9aabb952011-05-06 15:41:37 +090059 this(nameId, iconId, locale, mode, extraValue, false);
60 }
61
62 /**
63 * Constructor
64 * @param nameId The name of the subtype
65 * @param iconId The icon of the subtype
66 * @param locale The locale supported by the subtype
67 * @param modeId The mode supported by the subtype
68 * @param extraValue The extra value of the subtype
69 * @param isAuxiliary true when this subtype is one shot subtype.
70 */
71 InputMethodSubtype(int nameId, int iconId, String locale, String mode, String extraValue,
72 boolean isAuxiliary) {
satokab751aa2010-09-14 19:17:36 +090073 mSubtypeNameResId = nameId;
74 mSubtypeIconResId = iconId;
satokaf4bf402010-11-30 14:02:49 +090075 mSubtypeLocale = locale != null ? locale : "";
76 mSubtypeMode = mode != null ? mode : "";
77 mSubtypeExtraValue = extraValue != null ? extraValue : "";
satokece92d32011-04-27 16:09:53 +090078 mSubtypeHashCode = hashCodeInternal(mSubtypeLocale, mSubtypeMode, mSubtypeExtraValue);
satok9aabb952011-05-06 15:41:37 +090079 mIsAuxiliary = isAuxiliary;
satokab751aa2010-09-14 19:17:36 +090080 }
81
82 InputMethodSubtype(Parcel source) {
satokaf4bf402010-11-30 14:02:49 +090083 String s;
satokab751aa2010-09-14 19:17:36 +090084 mSubtypeNameResId = source.readInt();
85 mSubtypeIconResId = source.readInt();
satokaf4bf402010-11-30 14:02:49 +090086 s = source.readString();
87 mSubtypeLocale = s != null ? s : "";
88 s = source.readString();
89 mSubtypeMode = s != null ? s : "";
90 s = source.readString();
91 mSubtypeExtraValue = s != null ? s : "";
satokece92d32011-04-27 16:09:53 +090092 mSubtypeHashCode = hashCodeInternal(mSubtypeLocale, mSubtypeMode, mSubtypeExtraValue);
satok9aabb952011-05-06 15:41:37 +090093 mIsAuxiliary = (source.readInt() == 1);
satokab751aa2010-09-14 19:17:36 +090094 }
95
96 /**
97 * @return the name of the subtype
98 */
99 public int getNameResId() {
100 return mSubtypeNameResId;
101 }
102
103 /**
104 * @return the icon of the subtype
105 */
106 public int getIconResId() {
107 return mSubtypeIconResId;
108 }
109
110 /**
111 * @return the locale of the subtype
112 */
113 public String getLocale() {
114 return mSubtypeLocale;
115 }
116
117 /**
118 * @return the mode of the subtype
119 */
satok9ef02832010-11-04 21:17:48 +0900120 public String getMode() {
121 return mSubtypeMode;
satokab751aa2010-09-14 19:17:36 +0900122 }
123
124 /**
125 * @return the extra value of the subtype
126 */
127 public String getExtraValue() {
128 return mSubtypeExtraValue;
129 }
130
satok9aabb952011-05-06 15:41:37 +0900131 /**
132 * @return true if this subtype is one shot subtype. One shot subtype will not be shown in the
133 * ime switch list when this subtype is implicitly enabled. The framework will never
134 * switch the current ime to this subtype by switchToLastInputMethod in InputMethodManager.
135 */
136 public boolean isAuxiliary() {
137 return mIsAuxiliary;
138 }
139
satok9c4cc032011-02-14 18:03:32 +0900140 private HashMap<String, String> getExtraValueHashMap() {
141 if (mExtraValueHashMapCache == null) {
142 mExtraValueHashMapCache = new HashMap<String, String>();
143 final String[] pairs = mSubtypeExtraValue.split(EXTRA_VALUE_PAIR_SEPARATOR);
144 final int N = pairs.length;
145 for (int i = 0; i < N; ++i) {
146 final String[] pair = pairs[i].split(EXTRA_VALUE_KEY_VALUE_SEPARATOR);
147 if (pair.length == 1) {
148 mExtraValueHashMapCache.put(pair[0], null);
149 } else if (pair.length > 1) {
150 if (pair.length > 2) {
151 Slog.w(TAG, "ExtraValue has two or more '='s");
152 }
153 mExtraValueHashMapCache.put(pair[0], pair[1]);
154 }
155 }
156 }
157 return mExtraValueHashMapCache;
158 }
159
160 /**
161 * The string of ExtraValue in subtype should be defined as follows:
162 * example: key0,key1=value1,key2,key3,key4=value4
163 * @param key the key of extra value
164 * @return the subtype contains specified the extra value
165 */
166 public boolean containsExtraValueKey(String key) {
167 return getExtraValueHashMap().containsKey(key);
168 }
169
170 /**
171 * The string of ExtraValue in subtype should be defined as follows:
172 * example: key0,key1=value1,key2,key3,key4=value4
173 * @param key the key of extra value
174 * @return the value of the specified key
175 */
176 public String getExtraValueOf(String key) {
177 return getExtraValueHashMap().get(key);
178 }
179
satokab751aa2010-09-14 19:17:36 +0900180 @Override
181 public int hashCode() {
182 return mSubtypeHashCode;
183 }
184
185 @Override
186 public boolean equals(Object o) {
187 if (o instanceof InputMethodSubtype) {
188 InputMethodSubtype subtype = (InputMethodSubtype) o;
satokaf4bf402010-11-30 14:02:49 +0900189 return (subtype.hashCode() == hashCode())
190 && (subtype.getNameResId() == getNameResId())
191 && (subtype.getMode().equals(getMode()))
satokab751aa2010-09-14 19:17:36 +0900192 && (subtype.getIconResId() == getIconResId())
193 && (subtype.getLocale().equals(getLocale()))
194 && (subtype.getExtraValue().equals(getExtraValue()));
195 }
196 return false;
197 }
198
satok9aabb952011-05-06 15:41:37 +0900199 @Override
satokab751aa2010-09-14 19:17:36 +0900200 public int describeContents() {
201 return 0;
202 }
203
satok9aabb952011-05-06 15:41:37 +0900204 @Override
satokab751aa2010-09-14 19:17:36 +0900205 public void writeToParcel(Parcel dest, int parcelableFlags) {
206 dest.writeInt(mSubtypeNameResId);
207 dest.writeInt(mSubtypeIconResId);
208 dest.writeString(mSubtypeLocale);
satok9ef02832010-11-04 21:17:48 +0900209 dest.writeString(mSubtypeMode);
satokab751aa2010-09-14 19:17:36 +0900210 dest.writeString(mSubtypeExtraValue);
satok9aabb952011-05-06 15:41:37 +0900211 dest.writeInt(mIsAuxiliary ? 1 : 0);
satokab751aa2010-09-14 19:17:36 +0900212 }
213
214 public static final Parcelable.Creator<InputMethodSubtype> CREATOR
215 = new Parcelable.Creator<InputMethodSubtype>() {
satok9aabb952011-05-06 15:41:37 +0900216 @Override
satokab751aa2010-09-14 19:17:36 +0900217 public InputMethodSubtype createFromParcel(Parcel source) {
218 return new InputMethodSubtype(source);
219 }
220
satok9aabb952011-05-06 15:41:37 +0900221 @Override
satokab751aa2010-09-14 19:17:36 +0900222 public InputMethodSubtype[] newArray(int size) {
223 return new InputMethodSubtype[size];
224 }
225 };
226
satokece92d32011-04-27 16:09:53 +0900227 private static int hashCodeInternal(String locale, String mode, String extraValue) {
228 return Arrays.hashCode(new Object[] {locale, mode, extraValue});
satokab751aa2010-09-14 19:17:36 +0900229 }
satok7265d9b2011-02-14 15:47:30 +0900230
231 /**
232 * Sort the list of InputMethodSubtype
233 * @param context Context will be used for getting localized strings from IME
234 * @param flags Flags for the sort order
235 * @param imi InputMethodInfo of which subtypes are subject to be sorted
236 * @param subtypeList List of InputMethodSubtype which will be sorted
237 * @return Sorted list of subtypes
238 * @hide
239 */
240 public static List<InputMethodSubtype> sort(Context context, int flags, InputMethodInfo imi,
241 List<InputMethodSubtype> subtypeList) {
242 if (imi == null) return subtypeList;
243 final HashSet<InputMethodSubtype> inputSubtypesSet = new HashSet<InputMethodSubtype>(
244 subtypeList);
245 final ArrayList<InputMethodSubtype> sortedList = new ArrayList<InputMethodSubtype>();
246 int N = imi.getSubtypeCount();
247 for (int i = 0; i < N; ++i) {
248 InputMethodSubtype subtype = imi.getSubtypeAt(i);
249 if (inputSubtypesSet.contains(subtype)) {
250 sortedList.add(subtype);
251 inputSubtypesSet.remove(subtype);
252 }
253 }
254 // If subtypes in inputSubtypesSet remain, that means these subtypes are not
255 // contained in imi, so the remaining subtypes will be appended.
256 for (InputMethodSubtype subtype: inputSubtypesSet) {
257 sortedList.add(subtype);
258 }
259 return sortedList;
260 }
satokaf4bf402010-11-30 14:02:49 +0900261}