From 4ab730dbd34fad323063f2ffd31ce33de746668d Mon Sep 17 00:00:00 2001 From: satok Date: Thu, 18 Nov 2010 09:55:23 +0900 Subject: [PATCH] Add a functionarity to handle Subtype Change-Id: Ic6055ba218b64f4276e3db99a435f546c3990ee5 --- .../latin/InputLanguageSelection.java | 14 +- .../android/inputmethod/latin/LatinIME.java | 28 +- .../inputmethod/latin/LatinIMESettings.java | 2 - .../inputmethod/latin/LatinKeyboard.java | 4 +- .../inputmethod/latin/SubtypeSwitcher.java | 259 ++++++++++++++---- 5 files changed, 229 insertions(+), 78 deletions(-) diff --git a/java/src/com/android/inputmethod/latin/InputLanguageSelection.java b/java/src/com/android/inputmethod/latin/InputLanguageSelection.java index 4f4f7e3a7..7f64bcb43 100644 --- a/java/src/com/android/inputmethod/latin/InputLanguageSelection.java +++ b/java/src/com/android/inputmethod/latin/InputLanguageSelection.java @@ -37,7 +37,7 @@ public class InputLanguageSelection extends PreferenceActivity { private String mSelectedLanguages; private ArrayList mAvailableLanguages = new ArrayList(); private static final String[] BLACKLIST_LANGUAGES = { - "ko", "ja", "zh", "el" + "ko", "ja", "zh", "el", "zz" }; private static class Loc implements Comparable { @@ -74,7 +74,7 @@ public class InputLanguageSelection extends PreferenceActivity { for (int i = 0; i < mAvailableLanguages.size(); i++) { CheckBoxPreference pref = new CheckBoxPreference(this); Locale locale = mAvailableLanguages.get(i).locale; - pref.setTitle(SubtypeSwitcher.getLanguageName(locale)); + pref.setTitle(SubtypeSwitcher.getFullDisplayName(locale, true)); boolean checked = isLocaleIn(locale, languageList); pref.setChecked(checked); if (hasDictionary(locale)) { @@ -167,7 +167,7 @@ public class InputLanguageSelection extends PreferenceActivity { if (finalSize == 0) { preprocess[finalSize++] = - new Loc(SubtypeSwitcher.getLanguageName(l), l); + new Loc(SubtypeSwitcher.getFullDisplayName(l, true), l); } else { // check previous entry: // same lang and a country -> upgrade to full name and @@ -175,15 +175,15 @@ public class InputLanguageSelection extends PreferenceActivity { // diff lang -> insert ours with lang-only name if (preprocess[finalSize-1].locale.getLanguage().equals( language)) { - preprocess[finalSize-1].label = SubtypeSwitcher.getLanguageName( - preprocess[finalSize-1].locale); + preprocess[finalSize-1].label = SubtypeSwitcher.getFullDisplayName( + preprocess[finalSize-1].locale, false); preprocess[finalSize++] = - new Loc(SubtypeSwitcher.getLanguageName(l), l); + new Loc(SubtypeSwitcher.getFullDisplayName(l, false), l); } else { String displayName; if (s.equals("zz_ZZ")) { } else { - displayName = SubtypeSwitcher.getLanguageName(l); + displayName = SubtypeSwitcher.getFullDisplayName(l, true); preprocess[finalSize++] = new Loc(displayName, l); } } diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 9a800ba38..295a03be3 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -462,7 +462,7 @@ public class LatinIME extends InputMethodService private void initSuggest() { updateAutoTextEnabled(); - String locale = mSubtypeSwitcher.getInputLanguage(); + String locale = mSubtypeSwitcher.getInputLocaleStr(); Resources orig = getResources(); Locale savedLocale = mSubtypeSwitcher.changeSystemLocale(new Locale(locale)); @@ -519,6 +519,7 @@ public class LatinIME extends InputMethodService @Override public void onConfigurationChanged(Configuration conf) { mSubtypeSwitcher.onConfigurationChanged(conf); + onLanguageChanged(); updateAutoTextEnabled(); // If orientation changed while predicting, commit the change @@ -577,9 +578,11 @@ public class LatinIME extends InputMethodService return; } + SubtypeSwitcher.getInstance().updateParametersOnStartInputView(); + if (mRefreshKeyboardRequired) { mRefreshKeyboardRequired = false; - toggleLanguage(true, true); + onLanguageChanged(); } TextEntryState.newSession(this); @@ -2176,8 +2179,18 @@ public class LatinIME extends InputMethodService return mWord.isFirstCharCapitalized(); } + // Notify that Language has been changed and toggleLanguage will update KeyboaredID according + // to new Language. + private void onLanguageChanged() { + toggleLanguage(true, true); + } + + // "reset" and "next" are used only for USE_SPACEBAR_LANGUAGE_SWITCHER. private void toggleLanguage(boolean reset, boolean next) { - mSubtypeSwitcher.toggleLanguage(reset, next); + if (SubtypeSwitcher.USE_SPACEBAR_LANGUAGE_SWITCHER) { + mSubtypeSwitcher.toggleLanguage(reset, next); + } + // Reload keyboard because the current language has been changed. KeyboardSwitcher switcher = mKeyboardSwitcher; final int mode = switcher.getKeyboardMode(); final EditorInfo attribute = getCurrentInputEditorInfo(); @@ -2249,7 +2262,7 @@ public class LatinIME extends InputMethodService return new FieldContext( getCurrentInputConnection(), getCurrentInputEditorInfo(), - mSubtypeSwitcher.getInputLanguage(), + mSubtypeSwitcher.getInputLocaleStr(), mSubtypeSwitcher.getEnabledLanguages()); } @@ -2372,7 +2385,7 @@ public class LatinIME extends InputMethodService private void updateAutoTextEnabled() { if (mSuggest == null) return; mSuggest.setAutoTextEnabled(mQuickFixes - && SubtypeSwitcher.getInstance().isSystemLocaleSameAsInputLocale()); + && SubtypeSwitcher.getInstance().isSystemLanguageSameAsInputLanguage()); } private void updateSuggestionVisibility(SharedPreferences prefs) { @@ -2419,7 +2432,7 @@ public class LatinIME extends InputMethodService sp.getBoolean(PREF_HAS_USED_VOICE_INPUT_UNSUPPORTED_LOCALE, false); mLocaleSupportedForVoiceInput = SubtypeSwitcher.getInstance().isVoiceSupported( - SubtypeSwitcher.getInstance().getInputLanguage()); + SubtypeSwitcher.getInstance().getInputLocaleStr()); mAutoCorrectEnabled = isAutoCorrectEnabled(sp); mBigramSuggestionEnabled = mAutoCorrectEnabled && isBigramSuggestionEnabled(sp); @@ -2580,6 +2593,7 @@ public class LatinIME extends InputMethodService @Override public void onCurrentInputMethodSubtypeChanged(InputMethodSubtype subtype) { - SubtypeSwitcher.getInstance().onCurrentInputMethodSubtypeChanged(subtype); + SubtypeSwitcher.getInstance().updateSubtype(subtype); + onLanguageChanged(); } } diff --git a/java/src/com/android/inputmethod/latin/LatinIMESettings.java b/java/src/com/android/inputmethod/latin/LatinIMESettings.java index df2cd2717..960c54d7a 100644 --- a/java/src/com/android/inputmethod/latin/LatinIMESettings.java +++ b/java/src/com/android/inputmethod/latin/LatinIMESettings.java @@ -16,7 +16,6 @@ package com.android.inputmethod.latin; -import java.util.ArrayList; import java.util.Locale; import android.app.AlertDialog; @@ -34,7 +33,6 @@ import android.speech.SpeechRecognizer; import android.text.AutoText; import android.util.Log; -import com.android.inputmethod.voice.SettingsUtil; import com.android.inputmethod.voice.VoiceInputLogger; public class LatinIMESettings extends PreferenceActivity diff --git a/java/src/com/android/inputmethod/latin/LatinKeyboard.java b/java/src/com/android/inputmethod/latin/LatinKeyboard.java index 9473eaf84..6520d08e6 100644 --- a/java/src/com/android/inputmethod/latin/LatinKeyboard.java +++ b/java/src/com/android/inputmethod/latin/LatinKeyboard.java @@ -419,7 +419,7 @@ public class LatinKeyboard extends BaseKeyboard { final Rect bounds = new Rect(); // Estimate appropriate language name text size to fit in maxTextWidth. - String language = SubtypeSwitcher.getLanguageName(locale); + String language = SubtypeSwitcher.getDisplayLanguage(locale); int textWidth = getTextWidth(paint, language, origTextSize, bounds); // Assuming text width and text size are proportional to each other. float textSize = origTextSize * Math.min(maxTextWidth / textWidth, 1.0f); @@ -435,7 +435,7 @@ public class LatinKeyboard extends BaseKeyboard { textSize = origTextSize; } if (useShortName) { - language = SubtypeSwitcher.getShortLanguageName(locale); + language = SubtypeSwitcher.getShortDisplayLanguage(locale); textWidth = getTextWidth(paint, language, origTextSize, bounds); textSize = origTextSize * Math.min(maxTextWidth / textWidth, 1.0f); } diff --git a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java index 768274ed7..fe629949c 100644 --- a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java +++ b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java @@ -18,14 +18,18 @@ package com.android.inputmethod.latin; import com.android.inputmethod.voice.SettingsUtil; +import android.content.Context; import android.content.SharedPreferences; import android.content.res.Configuration; import android.content.res.Resources; import android.inputmethodservice.InputMethodService; import android.preference.PreferenceManager; import android.text.TextUtils; +import android.util.Log; +import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodSubtype; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Locale; @@ -33,12 +37,34 @@ import java.util.Locale; public class SubtypeSwitcher { // This flag indicates if we support language switching by swipe on space bar. // We may or may not draw the current language on space bar regardless of this flag. - public static final boolean USE_SPACEBAR_LANGUAGE_SWITCHER = true; + public static final boolean USE_SPACEBAR_LANGUAGE_SWITCHER = false; + private static final boolean DBG = false; private static final String TAG = "SubtypeSwitcher"; + + private static final char LOCALE_SEPARATER = '_'; + private static final String KEYBOARD_MODE = "keyboard"; + private static final String VOICE_MODE = "voice"; + private final TextUtils.SimpleStringSplitter mLocaleSplitter = + new TextUtils.SimpleStringSplitter(LOCALE_SEPARATER); + private static final SubtypeSwitcher sInstance = new SubtypeSwitcher(); - private InputMethodService mService; - private Resources mResources; + private /* final */ InputMethodService mService; + private /* final */ InputMethodManager mImm; + private /* final */ Resources mResources; + private final ArrayList mEnabledKeyboardSubtypesOfCurrentInputMethod = + new ArrayList(); + private final ArrayList mEnabledLanguagesOfCurrentInputMethod = new ArrayList(); + + /*-----------------------------------------------------------*/ + // Variants which should be changed only by reload functions. private Locale mSystemLocale; + private Locale mInputLocale; + private String mInputLocaleStr; + private String mMode; + private List mAllEnabledSubtypesOfCurrentInputMethod; + private boolean mNeedsToDisplayLanguage; + private boolean mIsSystemLanguageSameAsInputLanguage; + /*-----------------------------------------------------------*/ public static SubtypeSwitcher getInstance() { return sInstance; @@ -47,16 +73,97 @@ public class SubtypeSwitcher { public static void init(LatinIME service) { sInstance.mService = service; sInstance.mResources = service.getResources(); - sInstance.mSystemLocale = sInstance.mResources.getConfiguration().locale; + sInstance.mImm = (InputMethodManager) service.getSystemService( + Context.INPUT_METHOD_SERVICE); if (USE_SPACEBAR_LANGUAGE_SWITCHER) { sInstance.initLanguageSwitcher(service); } + + sInstance.updateAllParameters(); } private SubtypeSwitcher() { } - public void onCurrentInputMethodSubtypeChanged(InputMethodSubtype subtype) { + // Update all parameters stored in SubtypeSwitcher. + // Only configuration changed event is allowed to call this because this is heavy. + private void updateAllParameters() { + mSystemLocale = mResources.getConfiguration().locale; + updateSubtype(mImm.getCurrentInputMethodSubtype()); + updateParametersOnStartInputView(); + } + + // Update parameters which are changed outside LatinIME. This parameters affect UI so they + // should be updated every time onStartInputview. + public void updateParametersOnStartInputView() { + if (USE_SPACEBAR_LANGUAGE_SWITCHER) { + updateForSpaceBarLanguageSwitch(); + } else { + updateEnabledSubtypes(); + } + } + + // Reload enabledSubtypes from the framework. + private void updateEnabledSubtypes() { + boolean foundCurrentSubtypeBecameDisabled = true; + mAllEnabledSubtypesOfCurrentInputMethod = mImm.getEnabledInputMethodSubtypeList(null); + mEnabledLanguagesOfCurrentInputMethod.clear(); + mEnabledKeyboardSubtypesOfCurrentInputMethod.clear(); + for (InputMethodSubtype ims: mAllEnabledSubtypesOfCurrentInputMethod) { + final String locale = ims.getLocale(); + final String mode = ims.getMode(); + mLocaleSplitter.setString(locale); + if (mLocaleSplitter.hasNext()) { + mEnabledLanguagesOfCurrentInputMethod.add(mLocaleSplitter.next()); + } + if (locale.equals(mInputLocaleStr) && mode.equals(mMode)) { + foundCurrentSubtypeBecameDisabled = false; + } + if (KEYBOARD_MODE.equals(ims.getMode())) { + mEnabledKeyboardSubtypesOfCurrentInputMethod.add(ims); + } + } + mNeedsToDisplayLanguage = !(getEnabledKeyboardLocaleCount() <= 1 + && mIsSystemLanguageSameAsInputLanguage); + if (foundCurrentSubtypeBecameDisabled) { + updateSubtype(mImm.getCurrentInputMethodSubtype()); + } + } + + // Update the current subtype. LatinIME.onCurrentInputMethodSubtypeChanged calls this function. + public void updateSubtype(InputMethodSubtype newSubtype) { + if (DBG) { + Log.w(TAG, "Update subtype to:" + newSubtype.getLocale() + "," + newSubtype.getMode()); + } + updateInputLocale(newSubtype.getLocale()); + mMode = newSubtype.getMode(); + } + + // Update the current input locale from Locale string. + private void updateInputLocale(String inputLocaleStr) { + // example: inputLocaleStr = "en_US" "en" "" + // "en_US" --> language: en & country: US + // "en" --> language: en + // "" --> the system locale + mLocaleSplitter.setString(inputLocaleStr); + if (mLocaleSplitter.hasNext()) { + String language = mLocaleSplitter.next(); + if (mLocaleSplitter.hasNext()) { + mInputLocale = new Locale(language, mLocaleSplitter.next()); + } else { + mInputLocale = new Locale(language); + } + mInputLocaleStr = inputLocaleStr; + } else { + mInputLocale = mSystemLocale; + String country = mSystemLocale.getCountry(); + mInputLocaleStr = mSystemLocale.getLanguage() + + (TextUtils.isEmpty(country) ? "" : "_" + mSystemLocale.getLanguage()); + } + mIsSystemLanguageSameAsInputLanguage = getSystemLocale().getLanguage().equalsIgnoreCase( + getInputLocale().getLanguage()); + mNeedsToDisplayLanguage = !(getEnabledKeyboardLocaleCount() <= 1 + && mIsSystemLanguageSameAsInputLanguage); } ////////////////////////////////// @@ -66,82 +173,94 @@ public class SubtypeSwitcher { public int getEnabledKeyboardLocaleCount() { if (USE_SPACEBAR_LANGUAGE_SWITCHER) { return mLanguageSwitcher.getLocaleCount(); + } else { + return mEnabledKeyboardSubtypesOfCurrentInputMethod.size(); } - // TODO: Implement for no legacy mode - return 0; } - // TODO: Cache the value public boolean needsToDisplayLanguage() { - // TODO: Takes care of two-char locale such as "en" in addition to "en_US" - return !(getEnabledKeyboardLocaleCount() <= 1 && getSystemLocale().getLanguage( - ).equalsIgnoreCase(getInputLocale().getLanguage())); + return mNeedsToDisplayLanguage; } public Locale getInputLocale() { if (USE_SPACEBAR_LANGUAGE_SWITCHER) { return mLanguageSwitcher.getInputLocale(); + } else { + return mInputLocale; } - // TODO: Implement for no legacy mode - return null; } - public String getInputLanguage() { - String inputLanguage = null; + public String getInputLocaleStr() { if (USE_SPACEBAR_LANGUAGE_SWITCHER) { + String inputLanguage = null; inputLanguage = mLanguageSwitcher.getInputLanguage(); + // Should return system locale if there is no Language available. + if (inputLanguage == null) { + inputLanguage = getSystemLocale().getLanguage(); + } + return inputLanguage; + } else { + return mInputLocaleStr; } - // Should return system locale if there is no Language available. - if (inputLanguage == null) { - inputLanguage = getSystemLocale().getLanguage(); - } - return inputLanguage; } public String[] getEnabledLanguages() { if (USE_SPACEBAR_LANGUAGE_SWITCHER) { return mLanguageSwitcher.getEnabledLanguages(); + } else { + return mEnabledLanguagesOfCurrentInputMethod.toArray( + new String[mEnabledLanguagesOfCurrentInputMethod.size()]); } - // TODO: Implement for no legacy mode - return null; } public Locale getSystemLocale() { - return mSystemLocale; + if (USE_SPACEBAR_LANGUAGE_SWITCHER) { + return mLanguageSwitcher.getSystemLocale(); + } else { + return mSystemLocale; + } } - // TODO: Cache the value for faster processing. - public boolean isSystemLocaleSameAsInputLocale() { - // TODO: Takes care of two-char locale such as "en" in addition to "en_US" - return getSystemLocale().getLanguage().equalsIgnoreCase( - getInputLanguage().substring(0, 2)); + public boolean isSystemLanguageSameAsInputLanguage() { + if (USE_SPACEBAR_LANGUAGE_SWITCHER) { + return getSystemLocale().getLanguage().equalsIgnoreCase( + getInputLocaleStr().substring(0, 2)); + } else { + return mIsSystemLanguageSameAsInputLanguage; + } } public void onConfigurationChanged(Configuration conf) { - if (USE_SPACEBAR_LANGUAGE_SWITCHER) { - // If the system locale changes and is different from the saved - // locale (mSystemLocale), then reload the input locale list from the - // latin ime settings (shared prefs) and reset the input locale - // to the first one. - final Locale systemLocale = conf.locale; - if (!TextUtils.equals(systemLocale.toString(), mSystemLocale.toString())) { - mSystemLocale = systemLocale; - mLanguageSwitcher.loadLocales( - PreferenceManager.getDefaultSharedPreferences(mService)); + final Locale systemLocale = conf.locale; + // If system configuration was changed, update all parameters. + if (!TextUtils.equals(systemLocale.toString(), mSystemLocale.toString())) { + if (USE_SPACEBAR_LANGUAGE_SWITCHER) { + // If the system locale changes and is different from the saved + // locale (mSystemLocale), then reload the input locale list from the + // latin ime settings (shared prefs) and reset the input locale + // to the first one. + mLanguageSwitcher.loadLocales(PreferenceManager + .getDefaultSharedPreferences(mService)); mLanguageSwitcher.setSystemLocale(systemLocale); - toggleLanguage(true, true); + } else { + updateAllParameters(); } - return; } } public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { if (USE_SPACEBAR_LANGUAGE_SWITCHER) { - mLanguageSwitcher.loadLocales(sharedPreferences); - return; + if (LatinIME.PREF_SELECTED_LANGUAGES.equals(key)) { + mLanguageSwitcher.loadLocales(sharedPreferences); + } } } + /** + * Change system locale for this application + * @param newLocale + * @return oldLocale + */ public Locale changeSystemLocale(Locale newLocale) { Configuration conf = mResources.getConfiguration(); Locale oldLocale = conf.locale; @@ -150,16 +269,25 @@ public class SubtypeSwitcher { return oldLocale; } - //////////////////////////////////////////// - // Legacy Language Switch support // - //////////////////////////////////////////// + ////////////////////////////////////// + // SpaceBar Language Switch support // + ////////////////////////////////////// + private LanguageSwitcher mLanguageSwitcher; - public static String getLanguageName(Locale locale) { + public static String getFullDisplayName(Locale locale, boolean returnsNameInThisLocale) { + if (returnsNameInThisLocale) { + return toTitleCase(locale.getDisplayName(locale)); + } else { + return toTitleCase(locale.getDisplayName()); + } + } + + public static String getDisplayLanguage(Locale locale) { return toTitleCase(locale.getDisplayLanguage(locale)); } - public static String getShortLanguageName(Locale locale) { + public static String getShortDisplayLanguage(Locale locale) { return toTitleCase(locale.getLanguage()); } @@ -170,25 +298,34 @@ public class SubtypeSwitcher { return Character.toUpperCase(s.charAt(0)) + s.substring(1); } + private void updateForSpaceBarLanguageSwitch() { + // We need to update mNeedsToDisplayLanguage in onStartInputView because + // getEnabledKeyboardLocaleCount could have been changed. + mNeedsToDisplayLanguage = !(getEnabledKeyboardLocaleCount() <= 1 + && getSystemLocale().getLanguage().equalsIgnoreCase( + getInputLocale().getLanguage())); + } + public String getInputLanguageName() { - return getLanguageName(getInputLocale()); + return getDisplayLanguage(getInputLocale()); } public String getNextInputLanguageName() { if (USE_SPACEBAR_LANGUAGE_SWITCHER) { - return getLanguageName(mLanguageSwitcher.getNextInputLocale()); + return getDisplayLanguage(mLanguageSwitcher.getNextInputLocale()); + } else { + return ""; } - return ""; } public String getPreviousInputLanguageName() { if (USE_SPACEBAR_LANGUAGE_SWITCHER) { - return getLanguageName(mLanguageSwitcher.getPrevInputLocale()); + return getDisplayLanguage(mLanguageSwitcher.getPrevInputLocale()); + } else { + return ""; } - return ""; } - // TODO: This can be an array of String // A list of locales which are supported by default for voice input, unless we get a // different list from Gservices. private static final String DEFAULT_VOICE_INPUT_SUPPORTED_LOCALES = @@ -225,16 +362,18 @@ public class SubtypeSwitcher { } public void toggleLanguage(boolean reset, boolean next) { - if (reset) { - mLanguageSwitcher.reset(); - } else { - if (next) { - mLanguageSwitcher.next(); + if (USE_SPACEBAR_LANGUAGE_SWITCHER) { + if (reset) { + mLanguageSwitcher.reset(); } else { - mLanguageSwitcher.prev(); + if (next) { + mLanguageSwitcher.next(); + } else { + mLanguageSwitcher.prev(); + } } + mLanguageSwitcher.persist(); } - mLanguageSwitcher.persist(); } private void initLanguageSwitcher(LatinIME service) {