blob: 25f2229936aa68e2891863085459c8ed7a0e2dc5 [file] [log] [blame]
/*
* Copyright (C) 2010 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 android.view.inputmethod;
import android.content.Context;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Slog;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
/**
* This class is used to specify meta information of a subtype contained in an input method.
* Subtype can describe locale (e.g. en_US, fr_FR...) and mode (e.g. voice, keyboard...), and is
* used for IME switch and settings. The input method subtype allows the system to bring up the
* specified subtype of the designated input method directly.
*/
public final class InputMethodSubtype implements Parcelable {
private static final String TAG = InputMethodSubtype.class.getSimpleName();
private static final String EXTRA_VALUE_PAIR_SEPARATOR = ",";
private static final String EXTRA_VALUE_KEY_VALUE_SEPARATOR = "=";
private final int mSubtypeNameResId;
private final int mSubtypeIconResId;
private final String mSubtypeLocale;
private final String mSubtypeMode;
private final String mSubtypeExtraValue;
private final int mSubtypeHashCode;
private HashMap<String, String> mExtraValueHashMapCache;
/**
* Constructor
* @param nameId The name of the subtype
* @param iconId The icon of the subtype
* @param locale The locale supported by the subtype
* @param modeId The mode supported by the subtype
* @param extraValue The extra value of the subtype
*/
InputMethodSubtype(int nameId, int iconId, String locale, String mode, String extraValue) {
mSubtypeNameResId = nameId;
mSubtypeIconResId = iconId;
mSubtypeLocale = locale != null ? locale : "";
mSubtypeMode = mode != null ? mode : "";
mSubtypeExtraValue = extraValue != null ? extraValue : "";
mSubtypeHashCode = hashCodeInternal(mSubtypeNameResId, mSubtypeIconResId, mSubtypeLocale,
mSubtypeMode, mSubtypeExtraValue);
}
InputMethodSubtype(Parcel source) {
String s;
mSubtypeNameResId = source.readInt();
mSubtypeIconResId = source.readInt();
s = source.readString();
mSubtypeLocale = s != null ? s : "";
s = source.readString();
mSubtypeMode = s != null ? s : "";
s = source.readString();
mSubtypeExtraValue = s != null ? s : "";
mSubtypeHashCode = hashCodeInternal(mSubtypeNameResId, mSubtypeIconResId, mSubtypeLocale,
mSubtypeMode, mSubtypeExtraValue);
}
/**
* @return the name of the subtype
*/
public int getNameResId() {
return mSubtypeNameResId;
}
/**
* @return the icon of the subtype
*/
public int getIconResId() {
return mSubtypeIconResId;
}
/**
* @return the locale of the subtype
*/
public String getLocale() {
return mSubtypeLocale;
}
/**
* @return the mode of the subtype
*/
public String getMode() {
return mSubtypeMode;
}
/**
* @return the extra value of the subtype
*/
public String getExtraValue() {
return mSubtypeExtraValue;
}
private HashMap<String, String> getExtraValueHashMap() {
if (mExtraValueHashMapCache == null) {
mExtraValueHashMapCache = new HashMap<String, String>();
final String[] pairs = mSubtypeExtraValue.split(EXTRA_VALUE_PAIR_SEPARATOR);
final int N = pairs.length;
for (int i = 0; i < N; ++i) {
final String[] pair = pairs[i].split(EXTRA_VALUE_KEY_VALUE_SEPARATOR);
if (pair.length == 1) {
mExtraValueHashMapCache.put(pair[0], null);
} else if (pair.length > 1) {
if (pair.length > 2) {
Slog.w(TAG, "ExtraValue has two or more '='s");
}
mExtraValueHashMapCache.put(pair[0], pair[1]);
}
}
}
return mExtraValueHashMapCache;
}
/**
* The string of ExtraValue in subtype should be defined as follows:
* example: key0,key1=value1,key2,key3,key4=value4
* @param key the key of extra value
* @return the subtype contains specified the extra value
*/
public boolean containsExtraValueKey(String key) {
return getExtraValueHashMap().containsKey(key);
}
/**
* The string of ExtraValue in subtype should be defined as follows:
* example: key0,key1=value1,key2,key3,key4=value4
* @param key the key of extra value
* @return the value of the specified key
*/
public String getExtraValueOf(String key) {
return getExtraValueHashMap().get(key);
}
@Override
public int hashCode() {
return mSubtypeHashCode;
}
@Override
public boolean equals(Object o) {
if (o instanceof InputMethodSubtype) {
InputMethodSubtype subtype = (InputMethodSubtype) o;
return (subtype.hashCode() == hashCode())
&& (subtype.getNameResId() == getNameResId())
&& (subtype.getMode().equals(getMode()))
&& (subtype.getIconResId() == getIconResId())
&& (subtype.getLocale().equals(getLocale()))
&& (subtype.getExtraValue().equals(getExtraValue()));
}
return false;
}
public int describeContents() {
return 0;
}
public void writeToParcel(Parcel dest, int parcelableFlags) {
dest.writeInt(mSubtypeNameResId);
dest.writeInt(mSubtypeIconResId);
dest.writeString(mSubtypeLocale);
dest.writeString(mSubtypeMode);
dest.writeString(mSubtypeExtraValue);
}
public static final Parcelable.Creator<InputMethodSubtype> CREATOR
= new Parcelable.Creator<InputMethodSubtype>() {
public InputMethodSubtype createFromParcel(Parcel source) {
return new InputMethodSubtype(source);
}
public InputMethodSubtype[] newArray(int size) {
return new InputMethodSubtype[size];
}
};
private static int hashCodeInternal(int nameResId, int iconResId, String locale,
String mode, String extraValue) {
return Arrays.hashCode(new Object[] {nameResId, iconResId, locale, mode, extraValue});
}
/**
* Sort the list of InputMethodSubtype
* @param context Context will be used for getting localized strings from IME
* @param flags Flags for the sort order
* @param imi InputMethodInfo of which subtypes are subject to be sorted
* @param subtypeList List of InputMethodSubtype which will be sorted
* @return Sorted list of subtypes
* @hide
*/
public static List<InputMethodSubtype> sort(Context context, int flags, InputMethodInfo imi,
List<InputMethodSubtype> subtypeList) {
if (imi == null) return subtypeList;
final HashSet<InputMethodSubtype> inputSubtypesSet = new HashSet<InputMethodSubtype>(
subtypeList);
final ArrayList<InputMethodSubtype> sortedList = new ArrayList<InputMethodSubtype>();
int N = imi.getSubtypeCount();
for (int i = 0; i < N; ++i) {
InputMethodSubtype subtype = imi.getSubtypeAt(i);
if (inputSubtypesSet.contains(subtype)) {
sortedList.add(subtype);
inputSubtypesSet.remove(subtype);
}
}
// If subtypes in inputSubtypesSet remain, that means these subtypes are not
// contained in imi, so the remaining subtypes will be appended.
for (InputMethodSubtype subtype: inputSubtypesSet) {
sortedList.add(subtype);
}
return sortedList;
}
}