diff options
author | 2012-04-11 18:21:10 +0900 | |
---|---|---|
committer | 2012-04-13 18:36:26 +0900 | |
commit | f6972561fcb45310f18230ce217f0c6bb57e7eee (patch) | |
tree | 85d9a39c849a394c1d7f04a8aa2415ebdcee02cb | |
parent | f338f8b50d276cfed2bafe6856792c675087ad15 (diff) | |
download | latinime-f6972561fcb45310f18230ce217f0c6bb57e7eee.tar.gz latinime-f6972561fcb45310f18230ce217f0c6bb57e7eee.tar.xz latinime-f6972561fcb45310f18230ce217f0c6bb57e7eee.zip |
Utilize InputMethodSubtype and additional subtype
* Remove de_QY and fr_CH from supported subtypes
* Add de-qwerty and fr-qwertz predefined additional subtypes instead.
Change-Id: I49e8ba0299529302f2b91b4d018b07304cdd6897
14 files changed, 296 insertions, 192 deletions
diff --git a/java/res/values/donottranslate.xml b/java/res/values/donottranslate.xml index bfe42327c..892c72aec 100644 --- a/java/res/values/donottranslate.xml +++ b/java/res/values/donottranslate.xml @@ -134,24 +134,24 @@ <item>5</item> </string-array> - <!-- Subtype locale name exceptions --> + <!-- Subtype locale display name exceptions --> <string-array name="subtype_locale_exception_keys"> <item>en_US</item> <item>en_GB</item> - <item>*_QY</item> - <item>QY</item> </string-array> <string-array name="subtype_locale_exception_values"> <item>English (US)</item> <item>English (UK)</item> - <item>@string/subtype_generic_qwerty</item> - <item>QWERTY</item> </string-array> <!-- Generic subtype label --> <string name="subtype_generic">%s</string> <!-- Description for generic QWERTY keyboard subtype --> <string name="subtype_generic_qwerty">%s (QWERTY)</string> + <!-- Description for generic QWERTZ keyboard subtype --> + <string name="subtype_generic_qwertz">%s (QWERTZ)</string> + <!-- Description for generic AZERTY keyboard subtype --> + <string name="subtype_generic_azerty">%s (AZERTY)</string> <!-- dictionary pack package name /settings activity (for shared prefs and settings) --> <string name="dictionary_pack_package_name">com.google.android.inputmethod.latin.dictionarypack</string> diff --git a/java/res/xml/method.xml b/java/res/xml/method.xml index ba4534351..ca0b24e19 100644 --- a/java/res/xml/method.xml +++ b/java/res/xml/method.xml @@ -28,7 +28,6 @@ cs: Czech/qwertz da: Danish/nordic de: German/qwertz - de_QY: German (QWERTY)/qwerty el: Greek/greek en_US: English United States/qwerty en_GB: English Great Britain/qwerty @@ -38,7 +37,6 @@ fi: Finnish/nordic fr: French/azerty fr_CA: French Canada/qwerty - fr_CH: French Switzerland/qwertz hi: Hindi/hindi hr: Croatian/qwertz hu: Hungarian/qwertz @@ -64,7 +62,7 @@ tr: Turkish/qwerty uk: Ukrainian/east_slavic vi: Vietnamese/qwerty - zz_QY: QWERTY/qwerty + zz: QWERTY/qwerty --> <!-- TODO: use <lang>_keyboard icon instead of a common keyboard icon. --> <!-- If IME doesn't have an applicable subtype, the first subtype will be used as a default @@ -121,12 +119,6 @@ android:imeSubtypeExtraValue="KeyboardLayoutSet=qwertz,AsciiCapable" /> <subtype android:icon="@drawable/ic_subtype_keyboard" - android:label="@string/subtype_generic_qwerty" - android:imeSubtypeLocale="de" - android:imeSubtypeMode="keyboard" - android:imeSubtypeExtraValue="KeyboardLayoutSet=qwerty:de_QY,AsciiCapable" - /> - <subtype android:icon="@drawable/ic_subtype_keyboard" android:label="@string/subtype_generic" android:imeSubtypeLocale="el" android:imeSubtypeMode="keyboard" @@ -170,12 +162,6 @@ /> <subtype android:icon="@drawable/ic_subtype_keyboard" android:label="@string/subtype_generic" - android:imeSubtypeLocale="fr_CH" - android:imeSubtypeMode="keyboard" - android:imeSubtypeExtraValue="KeyboardLayoutSet=qwertz,AsciiCapable" - /> - <subtype android:icon="@drawable/ic_subtype_keyboard" - android:label="@string/subtype_generic" android:imeSubtypeLocale="hi" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=hindi" @@ -327,7 +313,7 @@ /> <subtype android:icon="@drawable/ic_subtype_keyboard" android:label="@string/subtype_no_language_qwerty" - android:imeSubtypeLocale="zz_QY" + android:imeSubtypeLocale="zz" android:imeSubtypeMode="keyboard" android:imeSubtypeExtraValue="KeyboardLayoutSet=qwerty,AsciiCapable,EnabledWhenDefaultIsNotAsciiCapable" /> diff --git a/java/src/com/android/inputmethod/compat/InputMethodManagerCompatWrapper.java b/java/src/com/android/inputmethod/compat/InputMethodManagerCompatWrapper.java index 04384523f..4bc82d2ec 100644 --- a/java/src/com/android/inputmethod/compat/InputMethodManagerCompatWrapper.java +++ b/java/src/com/android/inputmethod/compat/InputMethodManagerCompatWrapper.java @@ -53,6 +53,10 @@ public class InputMethodManagerCompatWrapper { sInstance.mImm = (InputMethodManager)context.getSystemService(Context.INPUT_METHOD_SERVICE); } + public void setAdditionalInputMethodSubtypes(String imiId, InputMethodSubtype[] subtypes) { + mImm.setAdditionalInputMethodSubtypes(imiId, subtypes); + } + public InputMethodSubtype getCurrentInputMethodSubtype() { return mImm.getCurrentInputMethodSubtype(); } diff --git a/java/src/com/android/inputmethod/keyboard/Keyboard.java b/java/src/com/android/inputmethod/keyboard/Keyboard.java index 58225e95d..d54acf715 100644 --- a/java/src/com/android/inputmethod/keyboard/Keyboard.java +++ b/java/src/com/android/inputmethod/keyboard/Keyboard.java @@ -793,7 +793,7 @@ public class Keyboard { } }; // Null means the current system locale. - final Locale locale = language.equals(SubtypeLocale.NO_LANGUAGE) + final Locale locale = SubtypeLocale.isNoLanguage(params.mId.mSubtype) ? null : params.mId.mLocale; job.runInLocale(mResources, locale); diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardId.java b/java/src/com/android/inputmethod/keyboard/KeyboardId.java index e35081867..b7eb8f69c 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardId.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardId.java @@ -19,9 +19,12 @@ package com.android.inputmethod.keyboard; import android.text.InputType; import android.text.TextUtils; import android.view.inputmethod.EditorInfo; +import android.view.inputmethod.InputMethodSubtype; import com.android.inputmethod.compat.EditorInfoCompatUtils; import com.android.inputmethod.latin.InputTypeUtils; +import com.android.inputmethod.latin.LatinIME; +import com.android.inputmethod.latin.SubtypeLocale; import java.util.Arrays; import java.util.Locale; @@ -53,6 +56,7 @@ public class KeyboardId { private static final int IME_ACTION_CUSTOM_LABEL = EditorInfo.IME_MASK_ACTION + 1; + public final InputMethodSubtype mSubtype; public final Locale mLocale; public final int mOrientation; public final int mWidth; @@ -67,10 +71,11 @@ public class KeyboardId { private final int mHashCode; - public KeyboardId(int elementId, Locale locale, int orientation, int width, int mode, - EditorInfo editorInfo, boolean clobberSettingsKey, boolean shortcutKeyEnabled, + public KeyboardId(int elementId, InputMethodSubtype subtype, int orientation, int width, + int mode, EditorInfo editorInfo, boolean clobberSettingsKey, boolean shortcutKeyEnabled, boolean hasShortcutKey, boolean languageSwitchKeyEnabled) { - mLocale = locale; + mSubtype = subtype; + mLocale = SubtypeLocale.getSubtypeLocale(subtype); mOrientation = orientation; mWidth = width; mMode = mode; @@ -102,7 +107,7 @@ public class KeyboardId { id.mCustomActionLabel, id.navigateNext(), id.navigatePrevious(), - id.mLocale + id.mSubtype }); } @@ -123,7 +128,7 @@ public class KeyboardId { && TextUtils.equals(other.mCustomActionLabel, mCustomActionLabel) && other.navigateNext() == navigateNext() && other.navigatePrevious() == navigatePrevious() - && other.mLocale.equals(mLocale); + && other.mSubtype.equals(mSubtype); } public boolean isAlphabetKeyboard() { @@ -176,9 +181,10 @@ public class KeyboardId { @Override public String toString() { - return String.format("[%s %s %s%d %s %s %s%s%s%s%s%s%s%s]", + return String.format("[%s %s:%s %s%d %s %s %s%s%s%s%s%s%s%s]", elementIdToName(mElementId), mLocale, + mSubtype.getExtraValueOf(LatinIME.SUBTYPE_EXTRA_VALUE_KEYBOARD_LAYOUT_SET), (mOrientation == 1 ? "port" : "land"), mWidth, modeName(mMode), imeAction(), diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java b/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java index 6d56c5cdc..35209e0ad 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java @@ -44,7 +44,6 @@ import org.xmlpull.v1.XmlPullParserException; import java.io.IOException; import java.lang.ref.SoftReference; import java.util.HashMap; -import java.util.Locale; /** * This class represents a set of keyboard layouts. Each of them represents a different keyboard @@ -109,7 +108,7 @@ public class KeyboardLayoutSet { boolean mVoiceKeyOnMain; boolean mNoSettingsKey; boolean mLanguageSwitchKeyEnabled; - Locale mLocale; + InputMethodSubtype mSubtype; int mOrientation; int mWidth; // KeyboardLayoutSet element id to element's parameters map. @@ -203,10 +202,10 @@ public class KeyboardLayoutSet { final Params params = mParams; final boolean isSymbols = (keyboardLayoutSetElementId == KeyboardId.ELEMENT_SYMBOLS || keyboardLayoutSetElementId == KeyboardId.ELEMENT_SYMBOLS_SHIFTED); - final boolean noLanguage = params.mLocale.getLanguage().equals(SubtypeLocale.NO_LANGUAGE); + final boolean noLanguage = SubtypeLocale.isNoLanguage(params.mSubtype); final boolean voiceKeyEnabled = params.mVoiceKeyEnabled && !noLanguage; final boolean hasShortcutKey = voiceKeyEnabled && (isSymbols != params.mVoiceKeyOnMain); - return new KeyboardId(keyboardLayoutSetElementId, params.mLocale, params.mOrientation, + return new KeyboardId(keyboardLayoutSetElementId, params.mSubtype, params.mOrientation, params.mWidth, params.mMode, params.mEditorInfo, params.mNoSettingsKey, voiceKeyEnabled, hasShortcutKey, params.mLanguageSwitchKeyEnabled); } @@ -251,7 +250,7 @@ public class KeyboardLayoutSet { final InputMethodSubtype keyboardSubtype = (forceAscii && !asciiCapable) ? SubtypeSwitcher.getInstance().getNoLanguageSubtype() : subtype; - mParams.mLocale = SubtypeLocale.getKeyboardLayoutSetLocale(keyboardSubtype); + mParams.mSubtype = keyboardSubtype; mParams.mKeyboardLayoutSetName = KEYBOARD_LAYOUT_SET_RESOURCE_PREFIX + SubtypeLocale.getKeyboardLayoutSetName(keyboardSubtype); return this; @@ -278,7 +277,7 @@ public class KeyboardLayoutSet { public KeyboardLayoutSet build() { if (mParams.mOrientation == Configuration.ORIENTATION_UNDEFINED) throw new RuntimeException("Screen geometry is not specified"); - if (mParams.mLocale == null) + if (mParams.mSubtype == null) throw new RuntimeException("KeyboardLayoutSet subtype is not specified"); final String packageName = mResources.getResourcePackageName( R.xml.keyboard_layout_set_qwerty); diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java index 7fadb3b8a..341d9bc7a 100644 --- a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java @@ -35,6 +35,7 @@ import android.view.MotionEvent; import android.view.View; import android.view.ViewConfiguration; import android.view.ViewGroup; +import android.view.inputmethod.InputMethodSubtype; import android.widget.PopupWindow; import com.android.inputmethod.accessibility.AccessibilityUtils; @@ -52,7 +53,6 @@ import com.android.inputmethod.latin.Utils; import com.android.inputmethod.latin.Utils.UsabilityStudyLogUtils; import com.android.inputmethod.latin.define.ProductionFlag; -import java.util.Locale; import java.util.WeakHashMap; /** @@ -80,7 +80,6 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke private ObjectAnimator mLanguageOnSpacebarFadeoutAnimator; private static final int ALPHA_OPAQUE = 255; private boolean mNeedsToDisplayLanguage; - private Locale mSpacebarLocale; private int mLanguageOnSpacebarAnimAlpha = ALPHA_OPAQUE; private final float mSpacebarTextRatio; private float mSpacebarTextSize; @@ -468,7 +467,6 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke mSpaceIcon = (mSpaceKey != null) ? mSpaceKey.getIcon(keyboard.mIconsSet) : null; final int keyHeight = keyboard.mMostCommonKeyHeight - keyboard.mVerticalGap; mSpacebarTextSize = keyHeight * mSpacebarTextRatio; - mSpacebarLocale = keyboard.mId.mLocale; } /** @@ -904,12 +902,12 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke } // Layout locale language name on spacebar. - private String layoutLanguageOnSpacebar(Paint paint, Locale locale, int width, + private String layoutLanguageOnSpacebar(Paint paint, InputMethodSubtype subtype, int width, float origTextSize) { paint.setTextAlign(Align.CENTER); paint.setTypeface(Typeface.DEFAULT); // Estimate appropriate language name text size to fit in maxTextWidth. - String language = SubtypeLocale.getFullDisplayName(locale); + String language = SubtypeLocale.getFullDisplayName(subtype); int textWidth = getTextWidth(paint, language, origTextSize); // Assuming text width and text size are proportional to each other. float textSize = origTextSize * Math.min(width / textWidth, 1.0f); @@ -921,7 +919,7 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke final boolean useShortName; if (useMiddleName) { - language = SubtypeLocale.getMiddleDisplayName(locale); + language = SubtypeLocale.getMiddleDisplayName(subtype); textWidth = getTextWidth(paint, language, origTextSize); textSize = origTextSize * Math.min(width / textWidth, 1.0f); useShortName = (textSize / origTextSize < MINIMUM_SCALE_OF_LANGUAGE_NAME) @@ -931,7 +929,7 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke } if (useShortName) { - language = SubtypeLocale.getShortDisplayName(locale); + language = SubtypeLocale.getShortDisplayName(subtype); textWidth = getTextWidth(paint, language, origTextSize); textSize = origTextSize * Math.min(width / textWidth, 1.0f); } @@ -944,10 +942,10 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke final int width = key.mWidth; final int height = key.mHeight; - // If input subtypes are explicitly selected. + // If input language are explicitly selected. if (mNeedsToDisplayLanguage) { - final String language = layoutLanguageOnSpacebar(paint, mSpacebarLocale, width, - mSpacebarTextSize); + final String language = layoutLanguageOnSpacebar( + paint, getKeyboard().mId.mSubtype, width, mSpacebarTextSize); // Draw language text with shadow // In case there is no space icon, we will place the language text at the center of // spacebar. diff --git a/java/src/com/android/inputmethod/latin/AdditionalSubtype.java b/java/src/com/android/inputmethod/latin/AdditionalSubtype.java new file mode 100644 index 000000000..deb247860 --- /dev/null +++ b/java/src/com/android/inputmethod/latin/AdditionalSubtype.java @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2012 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.android.inputmethod.latin; + +import android.view.inputmethod.InputMethodSubtype; + +import java.util.HashMap; +import java.util.Locale; + +public class AdditionalSubtype { + public static final String QWERTY = "qwerty"; + public static final String QWERTZ = "qwertz"; + public static final String AZERTY = "azerty"; + + private static final String SUBTYPE_MODE_KEYBOARD = "keyboard"; + private static final String SUBTYPE_EXTRA_VALUE_IS_ADDITIONAL_SUBTYPE = "isAdditionalSubtype"; + + // Keyboard layout to subtype name resource id map. + private static final HashMap<String, Integer> sKeyboardLayoutToNameIdsMap = + new HashMap<String, Integer>(); + + static { + sKeyboardLayoutToNameIdsMap.put(QWERTY, R.string.subtype_generic_qwerty); + sKeyboardLayoutToNameIdsMap.put(QWERTZ, R.string.subtype_generic_qwertz); + sKeyboardLayoutToNameIdsMap.put(AZERTY, R.string.subtype_generic_azerty); + } + + public static boolean isAdditionalSubtype(InputMethodSubtype subtype) { + return subtype.containsExtraValueKey(SUBTYPE_EXTRA_VALUE_IS_ADDITIONAL_SUBTYPE); + } + + public static InputMethodSubtype createAddtionalSubtype( + Locale locale, String keyboardLayoutSet) { + final String extraValue = String.format( + "%s=%s,%s", LatinIME.SUBTYPE_EXTRA_VALUE_KEYBOARD_LAYOUT_SET, keyboardLayoutSet, + SUBTYPE_EXTRA_VALUE_IS_ADDITIONAL_SUBTYPE); + Integer nameId = sKeyboardLayoutToNameIdsMap.get(keyboardLayoutSet); + if (nameId == null) nameId = R.string.subtype_generic; + return new InputMethodSubtype(nameId, R.drawable.ic_subtype_keyboard, + locale.toString(), SUBTYPE_MODE_KEYBOARD, extraValue, false, false); + } +} diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 187252a31..1ab461e3f 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -439,6 +439,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen loadSettings(); + mImm.setAdditionalInputMethodSubtypes( + SubtypeUtils.getInputMethodId(getPackageName()), + mSettingsValues.getPrefefinedAdditionalSubtypes()); + // TODO: remove the following when it's not needed by updateCorrectionMode() any more mInputAttributes = new InputAttributes(null, false /* isFullscreenMode */); updateCorrectionMode(); diff --git a/java/src/com/android/inputmethod/latin/SettingsValues.java b/java/src/com/android/inputmethod/latin/SettingsValues.java index 526acf128..8ff644fc5 100644 --- a/java/src/com/android/inputmethod/latin/SettingsValues.java +++ b/java/src/com/android/inputmethod/latin/SettingsValues.java @@ -21,12 +21,14 @@ import android.content.SharedPreferences; import android.content.res.Resources; import android.util.Log; import android.view.inputmethod.EditorInfo; +import android.view.inputmethod.InputMethodSubtype; import com.android.inputmethod.keyboard.internal.KeySpecParser; import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; import java.util.ArrayList; import java.util.Arrays; +import java.util.Locale; /** * When you call the constructor of this class, you may want to change the current system locale by @@ -69,6 +71,7 @@ public class SettingsValues { private final int mVibrationDurationSettingsRawValue; @SuppressWarnings("unused") // TODO: Use this private final float mKeypressSoundVolumeRawValue; + private final InputMethodSubtype[] mPredefinedAdditionalSubtypes; // Deduced settings public final int mKeypressVibrationDuration; @@ -145,6 +148,16 @@ public class SettingsValues { mAutoCorrectionThresholdRawValue); mVoiceKeyEnabled = mVoiceMode != null && !mVoiceMode.equals(voiceModeOff); mVoiceKeyOnMain = mVoiceMode != null && mVoiceMode.equals(voiceModeMain); + + // Predefined additional subtypes + final InputMethodSubtype DE_QWERTY = AdditionalSubtype.createAddtionalSubtype( + Locale.GERMAN, AdditionalSubtype.QWERTY); + final InputMethodSubtype FR_QWERTZ = AdditionalSubtype.createAddtionalSubtype( + Locale.FRENCH, AdditionalSubtype.QWERTZ); + mPredefinedAdditionalSubtypes = new InputMethodSubtype[] { + DE_QWERTY, + FR_QWERTZ, + }; } // Helper functions to create member values. @@ -304,6 +317,11 @@ public class SettingsValues { return res.getBoolean(R.bool.config_use_fullscreen_mode); } + // TODO: Should be able to add/remove/edit. + public InputMethodSubtype[] getPrefefinedAdditionalSubtypes() { + return mPredefinedAdditionalSubtypes; + } + // Accessed from the settings interface, hence public public static float getCurrentKeypressSoundVolume(final SharedPreferences sp, final Resources res) { diff --git a/java/src/com/android/inputmethod/latin/SubtypeLocale.java b/java/src/com/android/inputmethod/latin/SubtypeLocale.java index 05f91688e..37da5e846 100644 --- a/java/src/com/android/inputmethod/latin/SubtypeLocale.java +++ b/java/src/com/android/inputmethod/latin/SubtypeLocale.java @@ -20,23 +20,17 @@ import android.content.Context; import android.content.res.Resources; import android.view.inputmethod.InputMethodSubtype; - - +import java.util.HashMap; import java.util.Locale; public class SubtypeLocale { // Special language code to represent "no language". - public static final String NO_LANGUAGE = "zz"; - // Special country code to represent "QWERTY". - /* package for test */ static final String QWERTY = "QY"; - - public static final Locale LOCALE_NO_LANGUAGE_QWERTY = new Locale(NO_LANGUAGE, QWERTY); + private static final String NO_LANGUAGE = "zz"; + public static final Locale LOCALE_NO_LANGUAGE = new Locale(NO_LANGUAGE); - private static String[] sExceptionKeys; - private static String[] sExceptionValues; - - private static final String DEFAULT_KEYBOARD_LAYOUT_SET = "qwerty"; - private static final char KEYBOARD_LAYOUT_SET_LOCALE_DELIMITER = ':'; + // Exceptional locales to display name map. + private static final HashMap<String, String> sExceptionalDisplayNamesMap = + new HashMap<String, String>(); private SubtypeLocale() { // Intentional empty constructor for utility class. @@ -44,95 +38,82 @@ public class SubtypeLocale { public static void init(Context context) { final Resources res = context.getResources(); - sExceptionKeys = res.getStringArray(R.array.subtype_locale_exception_keys); - sExceptionValues = res.getStringArray(R.array.subtype_locale_exception_values); - } - - private static String lookupExceptionalLocale(String key) { - for (int index = 0; index < sExceptionKeys.length; index++) { - if (sExceptionKeys[index].equals(key)) { - return sExceptionValues[index]; - } + final String[] locales = res.getStringArray(R.array.subtype_locale_exception_keys); + final String[] displayNames = res.getStringArray(R.array.subtype_locale_exception_values); + for (int i = 0; i < locales.length; i++) { + sExceptionalDisplayNamesMap.put(locales[i], displayNames[i]); } - return null; } - // Get Locale's full display name in its locale. - // For example: - // "fr_CH" is converted to "Français (Suisse)". - // "de_QY" is converted to "Deutsche (QWERTY)". (Any locale that has country code "QY") - // "zz_QY" is converted to "QWERTY". (The language code "zz" means "No language", thus just - // ends up with the keyboard layout name.) - public static String getFullDisplayName(Locale locale) { - final String key; - if (locale.getLanguage().equals(NO_LANGUAGE)) { - key = locale.getCountry(); - } else if (locale.getCountry().equals(QWERTY)) { - key = "*_" + QWERTY; - } else { - key = locale.toString(); + // Get InputMethodSubtype's display name in its locale. + // isAdditionalSubtype (T=true, F=false) + // locale layout | Short Middle Full + // ------ ------ - ---- --------- ----------------- + // en_US qwerty F En English English (US) exception + // en_GB qwerty F En English English (UK) exception + // fr azerty F Fr Français Français + // fr_CA qwerty F Fr Français Français (Canada) + // de qwertz F De Deutsch Deutsch + // zz qwerty F QWERTY QWERTY + // fr qwertz T Fr Français Français (QWERTZ) + // de qwerty T De Deutsch Deutsch (QWERTY) + // en azerty T En English English (AZERTY) + // zz azerty T AZERTY AZERTY + + // Get InputMethodSubtype's full display name in its locale. + public static String getFullDisplayName(InputMethodSubtype subtype) { + final String value = sExceptionalDisplayNamesMap.get(subtype.getLocale()); + if (value != null) { + return value; } - final String value = lookupExceptionalLocale(key); - if (value == null) { - return StringUtils.toTitleCase(locale.getDisplayName(locale), locale); + + if (isNoLanguage(subtype)) { + return getKeyboardLayoutSetName(subtype).toUpperCase(); } - if (value.indexOf("%s") >= 0) { - final String languageName = StringUtils.toTitleCase( - locale.getDisplayLanguage(locale), locale); - return String.format(value, languageName); + + final Locale locale = getSubtypeLocale(subtype); + final String language = StringUtils.toTitleCase(locale.getDisplayLanguage(locale), locale); + if (AdditionalSubtype.isAdditionalSubtype(subtype)) { + return String.format("%s (%s)", + language, getKeyboardLayoutSetName(subtype).toUpperCase()); } - return value; + return StringUtils.toTitleCase(locale.getDisplayName(locale), locale); } - // Get Locale's middle display name in its locale. - // For example: - // "fr_CH" is converted to "Français". - // "de_QY" is converted to "Deutsche". (Any locale that has country code "QY") - // "zz_QY" is converted to "QWERTY". (The language code "zz" means "No language", thus just - // ends up with the keyboard layout name.) - public static String getMiddleDisplayName(Locale locale) { - if (NO_LANGUAGE.equals(locale.getLanguage())) { - return lookupExceptionalLocale(locale.getCountry()); - } else { - return StringUtils.toTitleCase(locale.getDisplayLanguage(locale), locale); + // Get InputMethodSubtype's middle display name in its locale. + public static String getMiddleDisplayName(InputMethodSubtype subtype) { + if (isNoLanguage(subtype)) { + return getKeyboardLayoutSetName(subtype).toUpperCase(); } + final Locale locale = getSubtypeLocale(subtype); + return StringUtils.toTitleCase(locale.getDisplayLanguage(locale), locale); } - // Get Locale's short display name in its locale. - // For example: - // "fr_CH" is converted to "Fr". - // "de_QY" is converted to "De". (Any locale that has country code "QY") - // "zz_QY" is converter to "QY". (The language code "zz" means "No language", thus just ends - // up with the keyboard layout name.) - public static String getShortDisplayName(Locale locale) { - if (NO_LANGUAGE.equals(locale.getLanguage())) { - return locale.getCountry(); - } else { - return StringUtils.toTitleCase(locale.getLanguage(), locale); + // Get InputMethodSubtype's short display name in its locale. + public static String getShortDisplayName(InputMethodSubtype subtype) { + if (isNoLanguage(subtype)) { + return ""; } + final Locale locale = getSubtypeLocale(subtype); + return StringUtils.toTitleCase(locale.getLanguage(), locale); } - public static String getKeyboardLayoutSetName(InputMethodSubtype subtype) { - final String keyboardLayoutSet = subtype.getExtraValueOf( - LatinIME.SUBTYPE_EXTRA_VALUE_KEYBOARD_LAYOUT_SET); - // TODO: Remove this null check when InputMethodManager.getCurrentInputMethodSubtype is - // fixed. - if (keyboardLayoutSet == null) return DEFAULT_KEYBOARD_LAYOUT_SET; - final int pos = keyboardLayoutSet.indexOf(KEYBOARD_LAYOUT_SET_LOCALE_DELIMITER); - return (pos > 0) ? keyboardLayoutSet.substring(0, pos) : keyboardLayoutSet; + public static boolean isNoLanguage(InputMethodSubtype subtype) { + final String localeString = subtype.getLocale(); + return localeString.equals(NO_LANGUAGE); } - public static String getKeyboardLayoutSetLocaleString(InputMethodSubtype subtype) { + public static Locale getSubtypeLocale(InputMethodSubtype subtype) { + final String localeString = subtype.getLocale(); + return LocaleUtils.constructLocaleFromString(localeString); + } + + public static String getKeyboardLayoutSetName(InputMethodSubtype subtype) { final String keyboardLayoutSet = subtype.getExtraValueOf( LatinIME.SUBTYPE_EXTRA_VALUE_KEYBOARD_LAYOUT_SET); // TODO: Remove this null check when InputMethodManager.getCurrentInputMethodSubtype is // fixed. - if (keyboardLayoutSet == null) return subtype.getLocale(); - final int pos = keyboardLayoutSet.indexOf(KEYBOARD_LAYOUT_SET_LOCALE_DELIMITER); - return (pos > 0) ? keyboardLayoutSet.substring(pos + 1) : subtype.getLocale(); - } - - public static Locale getKeyboardLayoutSetLocale(InputMethodSubtype subtype) { - return LocaleUtils.constructLocaleFromString(getKeyboardLayoutSetLocaleString(subtype)); + if (keyboardLayoutSet == null) return AdditionalSubtype.QWERTY; + return keyboardLayoutSet; } } diff --git a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java index 2ba742303..3bb3ab4ba 100644 --- a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java +++ b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java @@ -105,7 +105,7 @@ public class SubtypeSwitcher { mCurrentSubtype = mImm.getCurrentInputMethodSubtype(); mAllEnabledSubtypesOfCurrentInputMethod = null; mNoLanguageSubtype = SubtypeUtils.findSubtypeByLocaleAndKeyboardLayoutSet( - service, SubtypeLocale.LOCALE_NO_LANGUAGE_QWERTY, "qwerty"); + service, SubtypeLocale.LOCALE_NO_LANGUAGE, AdditionalSubtype.QWERTY); final NetworkInfo info = mConnectivityManager.getActiveNetworkInfo(); mIsNetworkConnected = (info != null && info.isConnected()); @@ -135,7 +135,7 @@ public class SubtypeSwitcher { mEnabledLanguagesOfCurrentInputMethod.clear(); mEnabledKeyboardSubtypesOfCurrentInputMethod.clear(); for (InputMethodSubtype ims : mAllEnabledSubtypesOfCurrentInputMethod) { - final String locale = SubtypeLocale.getKeyboardLayoutSetLocaleString(ims); + final String locale = ims.getLocale(); final String mode = ims.getMode(); mLocaleSplitter.setString(locale); if (mLocaleSplitter.hasNext()) { @@ -165,8 +165,7 @@ public class SubtypeSwitcher { + (mShortcutInputMethodInfo == null ? "<null>" : mShortcutInputMethodInfo.getId()) + ", " + (mShortcutSubtype == null ? "<null>" : ( - SubtypeLocale.getKeyboardLayoutSetLocaleString(mShortcutSubtype) - + ", " + mShortcutSubtype.getMode()))); + mShortcutSubtype.getLocale() + ", " + mShortcutSubtype.getMode()))); } // TODO: Update an icon for shortcut IME final Map<InputMethodInfo, List<InputMethodSubtype>> shortcuts = @@ -188,14 +187,13 @@ public class SubtypeSwitcher { + (mShortcutInputMethodInfo == null ? "<null>" : mShortcutInputMethodInfo.getId()) + ", " + (mShortcutSubtype == null ? "<null>" : ( - SubtypeLocale.getKeyboardLayoutSetLocaleString(mShortcutSubtype) - + ", " + mShortcutSubtype.getMode()))); + mShortcutSubtype.getLocale() + ", " + mShortcutSubtype.getMode()))); } } // Update the current subtype. LatinIME.onCurrentInputMethodSubtypeChanged calls this function. public void updateSubtype(InputMethodSubtype newSubtype) { - final String newLocale = SubtypeLocale.getKeyboardLayoutSetLocaleString(newSubtype); + final String newLocale = newSubtype.getLocale(); final String newMode = newSubtype.getMode(); final String oldMode = mCurrentSubtype.getMode(); if (DBG) { @@ -335,7 +333,7 @@ public class SubtypeSwitcher { } public boolean needsToDisplayLanguage(Locale keyboardLocale) { - if (keyboardLocale.equals(SubtypeLocale.LOCALE_NO_LANGUAGE_QWERTY)) { + if (keyboardLocale.equals(SubtypeLocale.LOCALE_NO_LANGUAGE)) { return true; } if (!keyboardLocale.equals(mInputLocale)) { diff --git a/java/src/com/android/inputmethod/latin/SubtypeUtils.java b/java/src/com/android/inputmethod/latin/SubtypeUtils.java index 4ad72fb9f..4d0f1c262 100644 --- a/java/src/com/android/inputmethod/latin/SubtypeUtils.java +++ b/java/src/com/android/inputmethod/latin/SubtypeUtils.java @@ -143,6 +143,7 @@ public class SubtypeUtils { return subtype; } } - throw new RuntimeException("Can not find subtype of locale " + localeString); + throw new RuntimeException("Can't find subtype for locale " + localeString + + " and keyboard layout " + keyoardLayoutSet); } } diff --git a/tests/src/com/android/inputmethod/latin/SubtypeLocaleTests.java b/tests/src/com/android/inputmethod/latin/SubtypeLocaleTests.java index 911429ddf..d34055a54 100644 --- a/tests/src/com/android/inputmethod/latin/SubtypeLocaleTests.java +++ b/tests/src/com/android/inputmethod/latin/SubtypeLocaleTests.java @@ -18,56 +18,35 @@ package com.android.inputmethod.latin; import android.content.Context; import android.test.AndroidTestCase; -import android.view.inputmethod.InputMethodInfo; -import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodSubtype; +import com.android.inputmethod.compat.InputMethodManagerCompatWrapper; + import java.util.ArrayList; import java.util.Locale; public class SubtypeLocaleTests extends AndroidTestCase { - private static final Locale LOCALE_zz_QY = SubtypeLocale.LOCALE_NO_LANGUAGE_QWERTY; - private static final Locale LOCALE_de_QY = - new Locale(Locale.GERMAN.getLanguage(), SubtypeLocale.QWERTY); - - private ArrayList<InputMethodSubtype> mSubtypesList; + // Locale to subtypes list. + private final ArrayList<InputMethodSubtype> mSubtypesList = new ArrayList<InputMethodSubtype>(); @Override protected void setUp() throws Exception { super.setUp(); - final Context context = getContext(); - final String packageName = context.getApplicationInfo().packageName; - + InputMethodManagerCompatWrapper.init(context); SubtypeLocale.init(context); - - final InputMethodManager imm = (InputMethodManager) context.getSystemService( - Context.INPUT_METHOD_SERVICE); - for (final InputMethodInfo imi : imm.getInputMethodList()) { - if (imi.getPackageName().equals(packageName)) { - mSubtypesList = new ArrayList<InputMethodSubtype>(); - final int subtypeCount = imi.getSubtypeCount(); - for (int i = 0; i < subtypeCount; i++) { - final InputMethodSubtype ims = imi.getSubtypeAt(i); - mSubtypesList.add(ims); - } - break; - } - } - assertNotNull("Can not find input method " + packageName, mSubtypesList); - assertTrue("Can not find keyboard subtype", mSubtypesList.size() > 0); } - public void testFullDisplayName() { + public void testAllFullDisplayName() { final StringBuilder messages = new StringBuilder(); int failedCount = 0; for (final InputMethodSubtype subtype : mSubtypesList) { - final Locale locale = SubtypeLocale.getKeyboardLayoutSetLocale(subtype); - if (locale.getLanguage().equals(SubtypeLocale.NO_LANGUAGE)) { + final Locale locale = SubtypeLocale.getSubtypeLocale(subtype); + if (SubtypeLocale.isNoLanguage(subtype)) { // This is special language name for language agnostic usage. continue; } - final String keyboardName = SubtypeLocale.getFullDisplayName(locale); + final String keyboardName = SubtypeLocale.getFullDisplayName(subtype); final String languageName = StringUtils.toTitleCase( locale.getDisplayLanguage(locale), locale); if (!keyboardName.contains(languageName)) { @@ -80,24 +59,16 @@ public class SubtypeLocaleTests extends AndroidTestCase { assertEquals(messages.toString(), 0, failedCount); } - public void testFullDisplayNameNoLanguage() { - assertEquals("zz_QY", "QWERTY", SubtypeLocale.getFullDisplayName(LOCALE_zz_QY)); - - final String de_QY = SubtypeLocale.getFullDisplayName(LOCALE_de_QY); - assertTrue("de_QY", de_QY.contains("(QWERTY")); - assertTrue("de_QY", de_QY.contains(Locale.GERMAN.getDisplayLanguage(Locale.GERMAN))); - } - - public void testMiddleDisplayName() { + public void testAllMiddleDisplayName() { final StringBuilder messages = new StringBuilder(); int failedCount = 0; for (final InputMethodSubtype subtype : mSubtypesList) { - final Locale locale = SubtypeLocale.getKeyboardLayoutSetLocale(subtype); - if (locale.getLanguage().equals(SubtypeLocale.NO_LANGUAGE)) { + final Locale locale = SubtypeLocale.getSubtypeLocale(subtype); + if (SubtypeLocale.isNoLanguage(subtype)) { // This is special language name for language agnostic usage. continue; } - final String keyboardName = SubtypeLocale.getMiddleDisplayName(locale); + final String keyboardName = SubtypeLocale.getMiddleDisplayName(subtype); final String languageName = StringUtils.toTitleCase( locale.getDisplayLanguage(locale), locale); if (!keyboardName.equals(languageName)) { @@ -110,21 +81,12 @@ public class SubtypeLocaleTests extends AndroidTestCase { assertEquals(messages.toString(), 0, failedCount); } - public void testMiddleDisplayNameNoLanguage() { - assertEquals("zz_QY", "QWERTY", SubtypeLocale.getMiddleDisplayName(LOCALE_zz_QY)); - assertEquals("de_QY", "Deutsch", SubtypeLocale.getMiddleDisplayName(LOCALE_de_QY)); - } - - public void testShortDisplayName() { + public void testAllShortDisplayName() { final StringBuilder messages = new StringBuilder(); int failedCount = 0; for (final InputMethodSubtype subtype : mSubtypesList) { - final Locale locale = SubtypeLocale.getKeyboardLayoutSetLocale(subtype); - if (locale.getCountry().equals(SubtypeLocale.QWERTY)) { - // This is special country code for QWERTY keyboard. - continue; - } - final String keyboardName = SubtypeLocale.getShortDisplayName(locale); + final Locale locale = SubtypeLocale.getSubtypeLocale(subtype); + final String keyboardName = SubtypeLocale.getShortDisplayName(subtype); final String languageCode = StringUtils.toTitleCase(locale.getLanguage(), locale); if (!keyboardName.equals(languageCode)) { failedCount++; @@ -136,8 +98,99 @@ public class SubtypeLocaleTests extends AndroidTestCase { assertEquals(messages.toString(), 0, failedCount); } - public void testShortDisplayNameNoLanguage() { - assertEquals("zz_QY", "QY", SubtypeLocale.getShortDisplayName(LOCALE_zz_QY)); - assertEquals("de_QY", "De", SubtypeLocale.getShortDisplayName(LOCALE_de_QY)); + // Get InputMethodSubtype's display name in its locale. + // additional + // locale layout Short Middle Full + // ------ ------ - ---- --------- ----------------- + // en_US qwerty F En English English (US) exception + // en_GB qwerty F En English English (UK) exception + // fr azerty F Fr Français Français + // fr_CA qwerty F Fr Français Français (Canada) + // de qwertz F De Deutsch Deutsch + // zz qwerty F QWERTY QWERTY + // fr qwertz T Fr Français Français (QWERTZ) + // de qwerty T De Deutsch Deutsch (QWERTY) + // zz azerty T AZERTY AZERTY + + public void testSampleSubtypes() { + final Context context = getContext(); + final InputMethodSubtype EN_US = SubtypeUtils.findSubtypeByLocaleAndKeyboardLayoutSet( + context, Locale.US, AdditionalSubtype.QWERTY); + final InputMethodSubtype EN_GB = SubtypeUtils.findSubtypeByLocaleAndKeyboardLayoutSet( + context, Locale.UK, AdditionalSubtype.QWERTY); + final InputMethodSubtype FR = SubtypeUtils.findSubtypeByLocaleAndKeyboardLayoutSet( + context, Locale.FRENCH, AdditionalSubtype.AZERTY); + final InputMethodSubtype FR_CA = SubtypeUtils.findSubtypeByLocaleAndKeyboardLayoutSet( + context, Locale.CANADA_FRENCH, AdditionalSubtype.QWERTY); + final InputMethodSubtype DE = SubtypeUtils.findSubtypeByLocaleAndKeyboardLayoutSet( + context, Locale.GERMAN, AdditionalSubtype.QWERTZ); + final InputMethodSubtype ZZ = SubtypeUtils.findSubtypeByLocaleAndKeyboardLayoutSet( + context, SubtypeLocale.LOCALE_NO_LANGUAGE, AdditionalSubtype.QWERTY); + + assertFalse(AdditionalSubtype.isAdditionalSubtype(EN_US)); + assertFalse(AdditionalSubtype.isAdditionalSubtype(EN_GB)); + assertFalse(AdditionalSubtype.isAdditionalSubtype(FR)); + assertFalse(AdditionalSubtype.isAdditionalSubtype(FR_CA)); + assertFalse(AdditionalSubtype.isAdditionalSubtype(DE)); + assertFalse(AdditionalSubtype.isAdditionalSubtype(ZZ)); + + assertEquals("en_US", "qwerty", SubtypeLocale.getKeyboardLayoutSetName(EN_US)); + assertEquals("en_GB", "qwerty", SubtypeLocale.getKeyboardLayoutSetName(EN_GB)); + assertEquals("fr ", "azerty", SubtypeLocale.getKeyboardLayoutSetName(FR)); + assertEquals("fr_CA", "qwerty", SubtypeLocale.getKeyboardLayoutSetName(FR_CA)); + assertEquals("de ", "qwertz", SubtypeLocale.getKeyboardLayoutSetName(DE)); + assertEquals("zz ", "qwerty", SubtypeLocale.getKeyboardLayoutSetName(ZZ)); + + assertEquals("en_US", "English (US)", SubtypeLocale.getFullDisplayName(EN_US)); + assertEquals("en_GB", "English (UK)", SubtypeLocale.getFullDisplayName(EN_GB)); + assertEquals("fr ", "Français", SubtypeLocale.getFullDisplayName(FR)); + assertEquals("fr_CA", "Français (Canada)", SubtypeLocale.getFullDisplayName(FR_CA)); + assertEquals("de ", "Deutsch", SubtypeLocale.getFullDisplayName(DE)); + assertEquals("zz ", "QWERTY", SubtypeLocale.getFullDisplayName(ZZ)); + + assertEquals("en_US", "English", SubtypeLocale.getMiddleDisplayName(EN_US)); + assertEquals("en_GB", "English", SubtypeLocale.getMiddleDisplayName(EN_GB)); + assertEquals("fr ", "Français", SubtypeLocale.getMiddleDisplayName(FR)); + assertEquals("fr_CA", "Français", SubtypeLocale.getMiddleDisplayName(FR_CA)); + assertEquals("de ", "Deutsch", SubtypeLocale.getMiddleDisplayName(DE)); + assertEquals("zz ", "QWERTY", SubtypeLocale.getMiddleDisplayName(ZZ)); + + assertEquals("en_US", "En", SubtypeLocale.getShortDisplayName(EN_US)); + assertEquals("en_GB", "En", SubtypeLocale.getShortDisplayName(EN_GB)); + assertEquals("fr ", "Fr", SubtypeLocale.getShortDisplayName(FR)); + assertEquals("fr_CA", "Fr", SubtypeLocale.getShortDisplayName(FR_CA)); + assertEquals("de ", "De", SubtypeLocale.getShortDisplayName(DE)); + assertEquals("zz ", "", SubtypeLocale.getShortDisplayName(ZZ)); + } + + public void testAdditionalSubtype() { + final InputMethodSubtype DE_QWERTY = AdditionalSubtype.createAddtionalSubtype( + Locale.GERMAN, AdditionalSubtype.QWERTY); + final InputMethodSubtype FR_QWERTZ = AdditionalSubtype.createAddtionalSubtype( + Locale.FRENCH, AdditionalSubtype.QWERTZ); + final InputMethodSubtype EN_AZERTY = AdditionalSubtype.createAddtionalSubtype( + Locale.ENGLISH, AdditionalSubtype.AZERTY); + final InputMethodSubtype ZZ_AZERTY = AdditionalSubtype.createAddtionalSubtype( + SubtypeLocale.LOCALE_NO_LANGUAGE, AdditionalSubtype.AZERTY); + + assertTrue(AdditionalSubtype.isAdditionalSubtype(FR_QWERTZ)); + assertTrue(AdditionalSubtype.isAdditionalSubtype(DE_QWERTY)); + assertTrue(AdditionalSubtype.isAdditionalSubtype(EN_AZERTY)); + assertTrue(AdditionalSubtype.isAdditionalSubtype(ZZ_AZERTY)); + + assertEquals("fr qwertz", "Français (QWERTZ)", SubtypeLocale.getFullDisplayName(FR_QWERTZ)); + assertEquals("de qwerty", "Deutsch (QWERTY)", SubtypeLocale.getFullDisplayName(DE_QWERTY)); + assertEquals("en azerty", "English (AZERTY)", SubtypeLocale.getFullDisplayName(EN_AZERTY)); + assertEquals("zz azerty", "AZERTY", SubtypeLocale.getFullDisplayName(ZZ_AZERTY)); + + assertEquals("fr qwertz", "Français", SubtypeLocale.getMiddleDisplayName(FR_QWERTZ)); + assertEquals("de qwerty", "Deutsch", SubtypeLocale.getMiddleDisplayName(DE_QWERTY)); + assertEquals("en azerty", "English", SubtypeLocale.getMiddleDisplayName(EN_AZERTY)); + assertEquals("zz azerty", "AZERTY", SubtypeLocale.getMiddleDisplayName(ZZ_AZERTY)); + + assertEquals("fr qwertz", "Fr", SubtypeLocale.getShortDisplayName(FR_QWERTZ)); + assertEquals("de qwerty", "De", SubtypeLocale.getShortDisplayName(DE_QWERTY)); + assertEquals("en azerty", "En", SubtypeLocale.getShortDisplayName(EN_AZERTY)); + assertEquals("zz azerty", "", SubtypeLocale.getShortDisplayName(ZZ_AZERTY)); } } |