InputMethodSubtype.java revision ece92d34fcf273f68f33d2fd8e5764764fc0c66d
1/* 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 19import android.content.Context; 20import android.os.Parcel; 21import android.os.Parcelable; 22import android.util.Slog; 23 24import java.util.ArrayList; 25import java.util.Arrays; 26import java.util.HashMap; 27import java.util.HashSet; 28import java.util.List; 29 30/** 31 * 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. 35 */ 36public final class InputMethodSubtype implements Parcelable { 37 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 41 private final int mSubtypeNameResId; 42 private final int mSubtypeIconResId; 43 private final String mSubtypeLocale; 44 private final String mSubtypeMode; 45 private final String mSubtypeExtraValue; 46 private final int mSubtypeHashCode; 47 private HashMap<String, String> mExtraValueHashMapCache; 48 49 /** 50 * Constructor 51 * @param nameId The name of the subtype 52 * @param iconId The icon of the subtype 53 * @param locale The locale supported by the subtype 54 * @param modeId The mode supported by the subtype 55 * @param extraValue The extra value of the subtype 56 */ 57 InputMethodSubtype(int nameId, int iconId, String locale, String mode, String extraValue) { 58 mSubtypeNameResId = nameId; 59 mSubtypeIconResId = iconId; 60 mSubtypeLocale = locale != null ? locale : ""; 61 mSubtypeMode = mode != null ? mode : ""; 62 mSubtypeExtraValue = extraValue != null ? extraValue : ""; 63 mSubtypeHashCode = hashCodeInternal(mSubtypeLocale, mSubtypeMode, mSubtypeExtraValue); 64 } 65 66 InputMethodSubtype(Parcel source) { 67 String s; 68 mSubtypeNameResId = source.readInt(); 69 mSubtypeIconResId = source.readInt(); 70 s = source.readString(); 71 mSubtypeLocale = s != null ? s : ""; 72 s = source.readString(); 73 mSubtypeMode = s != null ? s : ""; 74 s = source.readString(); 75 mSubtypeExtraValue = s != null ? s : ""; 76 mSubtypeHashCode = hashCodeInternal(mSubtypeLocale, mSubtypeMode, mSubtypeExtraValue); 77 } 78 79 /** 80 * @return the name of the subtype 81 */ 82 public int getNameResId() { 83 return mSubtypeNameResId; 84 } 85 86 /** 87 * @return the icon of the subtype 88 */ 89 public int getIconResId() { 90 return mSubtypeIconResId; 91 } 92 93 /** 94 * @return the locale of the subtype 95 */ 96 public String getLocale() { 97 return mSubtypeLocale; 98 } 99 100 /** 101 * @return the mode of the subtype 102 */ 103 public String getMode() { 104 return mSubtypeMode; 105 } 106 107 /** 108 * @return the extra value of the subtype 109 */ 110 public String getExtraValue() { 111 return mSubtypeExtraValue; 112 } 113 114 private HashMap<String, String> getExtraValueHashMap() { 115 if (mExtraValueHashMapCache == null) { 116 mExtraValueHashMapCache = new HashMap<String, String>(); 117 final String[] pairs = mSubtypeExtraValue.split(EXTRA_VALUE_PAIR_SEPARATOR); 118 final int N = pairs.length; 119 for (int i = 0; i < N; ++i) { 120 final String[] pair = pairs[i].split(EXTRA_VALUE_KEY_VALUE_SEPARATOR); 121 if (pair.length == 1) { 122 mExtraValueHashMapCache.put(pair[0], null); 123 } else if (pair.length > 1) { 124 if (pair.length > 2) { 125 Slog.w(TAG, "ExtraValue has two or more '='s"); 126 } 127 mExtraValueHashMapCache.put(pair[0], pair[1]); 128 } 129 } 130 } 131 return mExtraValueHashMapCache; 132 } 133 134 /** 135 * The string of ExtraValue in subtype should be defined as follows: 136 * example: key0,key1=value1,key2,key3,key4=value4 137 * @param key the key of extra value 138 * @return the subtype contains specified the extra value 139 */ 140 public boolean containsExtraValueKey(String key) { 141 return getExtraValueHashMap().containsKey(key); 142 } 143 144 /** 145 * The string of ExtraValue in subtype should be defined as follows: 146 * example: key0,key1=value1,key2,key3,key4=value4 147 * @param key the key of extra value 148 * @return the value of the specified key 149 */ 150 public String getExtraValueOf(String key) { 151 return getExtraValueHashMap().get(key); 152 } 153 154 @Override 155 public int hashCode() { 156 return mSubtypeHashCode; 157 } 158 159 @Override 160 public boolean equals(Object o) { 161 if (o instanceof InputMethodSubtype) { 162 InputMethodSubtype subtype = (InputMethodSubtype) o; 163 return (subtype.hashCode() == hashCode()) 164 && (subtype.getNameResId() == getNameResId()) 165 && (subtype.getMode().equals(getMode())) 166 && (subtype.getIconResId() == getIconResId()) 167 && (subtype.getLocale().equals(getLocale())) 168 && (subtype.getExtraValue().equals(getExtraValue())); 169 } 170 return false; 171 } 172 173 public int describeContents() { 174 return 0; 175 } 176 177 public void writeToParcel(Parcel dest, int parcelableFlags) { 178 dest.writeInt(mSubtypeNameResId); 179 dest.writeInt(mSubtypeIconResId); 180 dest.writeString(mSubtypeLocale); 181 dest.writeString(mSubtypeMode); 182 dest.writeString(mSubtypeExtraValue); 183 } 184 185 public static final Parcelable.Creator<InputMethodSubtype> CREATOR 186 = new Parcelable.Creator<InputMethodSubtype>() { 187 public InputMethodSubtype createFromParcel(Parcel source) { 188 return new InputMethodSubtype(source); 189 } 190 191 public InputMethodSubtype[] newArray(int size) { 192 return new InputMethodSubtype[size]; 193 } 194 }; 195 196 private static int hashCodeInternal(String locale, String mode, String extraValue) { 197 return Arrays.hashCode(new Object[] {locale, mode, extraValue}); 198 } 199 200 /** 201 * Sort the list of InputMethodSubtype 202 * @param context Context will be used for getting localized strings from IME 203 * @param flags Flags for the sort order 204 * @param imi InputMethodInfo of which subtypes are subject to be sorted 205 * @param subtypeList List of InputMethodSubtype which will be sorted 206 * @return Sorted list of subtypes 207 * @hide 208 */ 209 public static List<InputMethodSubtype> sort(Context context, int flags, InputMethodInfo imi, 210 List<InputMethodSubtype> subtypeList) { 211 if (imi == null) return subtypeList; 212 final HashSet<InputMethodSubtype> inputSubtypesSet = new HashSet<InputMethodSubtype>( 213 subtypeList); 214 final ArrayList<InputMethodSubtype> sortedList = new ArrayList<InputMethodSubtype>(); 215 int N = imi.getSubtypeCount(); 216 for (int i = 0; i < N; ++i) { 217 InputMethodSubtype subtype = imi.getSubtypeAt(i); 218 if (inputSubtypesSet.contains(subtype)) { 219 sortedList.add(subtype); 220 inputSubtypesSet.remove(subtype); 221 } 222 } 223 // If subtypes in inputSubtypesSet remain, that means these subtypes are not 224 // contained in imi, so the remaining subtypes will be appended. 225 for (InputMethodSubtype subtype: inputSubtypesSet) { 226 sortedList.add(subtype); 227 } 228 return sortedList; 229 } 230} 231