diff options
Diffstat (limited to 'java/src')
16 files changed, 614 insertions, 246 deletions
diff --git a/java/src/com/android/inputmethod/latin/BaseKeyboard.java b/java/src/com/android/inputmethod/latin/BaseKeyboard.java index 0f8b75d45..9dbfff34a 100644 --- a/java/src/com/android/inputmethod/latin/BaseKeyboard.java +++ b/java/src/com/android/inputmethod/latin/BaseKeyboard.java @@ -626,7 +626,7 @@ public class BaseKeyboard { return false; } - public boolean isShifted() { + public boolean isShiftedOrShiftLocked() { return mShifted; } diff --git a/java/src/com/android/inputmethod/latin/BaseKeyboardParser.java b/java/src/com/android/inputmethod/latin/BaseKeyboardParser.java index 496f65174..276abfc1f 100644 --- a/java/src/com/android/inputmethod/latin/BaseKeyboardParser.java +++ b/java/src/com/android/inputmethod/latin/BaseKeyboardParser.java @@ -120,14 +120,6 @@ public class BaseKeyboardParser { private static final String TAG_CASE = "case"; private static final String TAG_DEFAULT = "default"; - // String representation of KeyboardSwitcher.MODE_xxx. - private static final String MODE_TEXT = "text"; - private static final String MODE_URL = "url"; - private static final String MODE_EMAIL = "email"; - private static final String MODE_IM = "im"; - private static final String MODE_WEB = "web"; - private static final String MODE_PHONE = "phone"; - private final BaseKeyboard mKeyboard; private final Resources mResources; @@ -411,7 +403,7 @@ public class BaseKeyboardParser { final BaseKeyboard keyboard = mKeyboard; final TypedArray a = mResources.obtainAttributes(Xml.asAttributeSet(parser), R.styleable.BaseKeyboard_Case); - final String mode = a.getString(R.styleable.BaseKeyboard_Case_mode); + final int mode = a.getInt(R.styleable.BaseKeyboard_Case_mode, -1); final String settingsKey = a.getString(R.styleable.BaseKeyboard_Case_settingsKey); final String voiceKey = a.getString(R.styleable.BaseKeyboard_Case_voiceKey); a.recycle(); @@ -419,8 +411,7 @@ public class BaseKeyboardParser { final KeyboardId id = keyboard.mId; if (id == null) return true; - final boolean modeMatched = (mode == null - || id.mMode == parseModeString(mode)); + final boolean modeMatched = (mode == -1 || id.mMode == mode); final boolean settingsKeyMatched = (settingsKey == null || id.mHasSettingsKey == Boolean.parseBoolean(settingsKey)); final boolean voiceKeyMatched = (voiceKey == null @@ -428,23 +419,13 @@ public class BaseKeyboardParser { final boolean selected = modeMatched && settingsKeyMatched && voiceKeyMatched; if (DEBUG_TAG) { Log.d(TAG, "parseCaseCondition: " + Boolean.toString(selected).toUpperCase() - + (mode != null ? " mode=" + mode : "") + + (mode != -1 ? " mode=" + mode : "") + (settingsKey != null ? " settingsKey="+settingsKey : "") + (voiceKey != null ? " voiceKey=" + voiceKey : "")); } return selected; } - private static int parseModeString(String mode) { - if (mode.equals(MODE_TEXT)) return KeyboardSwitcher.MODE_TEXT; - if (mode.equals(MODE_URL)) return KeyboardSwitcher.MODE_URL; - if (mode.equals(MODE_EMAIL)) return KeyboardSwitcher.MODE_EMAIL; - if (mode.equals(MODE_IM)) return KeyboardSwitcher.MODE_IM; - if (mode.equals(MODE_WEB)) return KeyboardSwitcher.MODE_WEB; - if (mode.equals(MODE_PHONE)) return KeyboardSwitcher.MODE_PHONE; - throw new RuntimeException("uknown mode attribute in Keyboard XML: " + mode); - } - private boolean parseDefault(XmlResourceParser parser, Row row, List<Key> keys) throws XmlPullParserException, IOException { if (DEBUG_PARSER) debugEnterMethod("parseDefault", keys == null); diff --git a/java/src/com/android/inputmethod/latin/BaseKeyboardView.java b/java/src/com/android/inputmethod/latin/BaseKeyboardView.java index ad0e8d41a..89c9572b1 100644 --- a/java/src/com/android/inputmethod/latin/BaseKeyboardView.java +++ b/java/src/com/android/inputmethod/latin/BaseKeyboardView.java @@ -683,7 +683,7 @@ public class BaseKeyboardView extends View implements PointerTracker.UIProxy { } protected CharSequence adjustCase(CharSequence label) { - if (mKeyboard.isShifted() && label != null && label.length() < 3 + if (mKeyboard.isShiftedOrShiftLocked() && label != null && label.length() < 3 && Character.isLowerCase(label.charAt(0))) { label = label.toString().toUpperCase(); } @@ -772,8 +772,8 @@ public class BaseKeyboardView extends View implements PointerTracker.UIProxy { final int kbdPaddingTop = getPaddingTop(); final Key[] keys = mKeys; final Key invalidKey = mInvalidatedKey; - final boolean isTemporaryUpperCase = (mKeyboard instanceof LatinKeyboard - && ((LatinKeyboard)mKeyboard).isTemporaryUpperCase()); + final boolean isManualTemporaryUpperCase = (mKeyboard instanceof LatinKeyboard + && ((LatinKeyboard)mKeyboard).isManualTemporaryUpperCase()); paint.setColor(mKeyTextColor); boolean drawSingleKey = false; @@ -853,7 +853,7 @@ public class BaseKeyboardView extends View implements PointerTracker.UIProxy { int drawableHeight = key.height; int drawableX = 0; int drawableY = HINT_ICON_VERTICAL_ADJUSTMENT_PIXEL; - Drawable icon = (isTemporaryUpperCase + Drawable icon = (isManualTemporaryUpperCase && key.manualTemporaryUpperCaseHintIcon != null) ? key.manualTemporaryUpperCaseHintIcon : key.hintIcon; drawIcon(canvas, icon, drawableX, drawableY, drawableWidth, drawableHeight); @@ -1226,7 +1226,7 @@ public class BaseKeyboardView extends View implements PointerTracker.UIProxy { // TODO: change the below line to use getLatinKeyboard() instead of getKeyboard() BaseKeyboard baseMiniKeyboard = mMiniKeyboard.getKeyboard(); if (baseMiniKeyboard != null && baseMiniKeyboard.setShifted(mKeyboard == null - ? false : mKeyboard.isShifted())) { + ? false : mKeyboard.isShiftedOrShiftLocked())) { mMiniKeyboard.invalidateAllKeys(); } // Mini keyboard needs no pop-up key preview displayed. 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<Loc> mAvailableLanguages = new ArrayList<Loc>(); private static final String[] BLACKLIST_LANGUAGES = { - "ko", "ja", "zh", "el" + "ko", "ja", "zh", "el", "zz" }; private static class Loc implements Comparable<Object> { @@ -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/KeyboardSwitcher.java b/java/src/com/android/inputmethod/latin/KeyboardSwitcher.java index 3f6b6ca33..5f78cb91e 100644 --- a/java/src/com/android/inputmethod/latin/KeyboardSwitcher.java +++ b/java/src/com/android/inputmethod/latin/KeyboardSwitcher.java @@ -18,7 +18,6 @@ package com.android.inputmethod.latin; import android.content.Context; import android.content.SharedPreferences; -import android.content.res.Configuration; import android.content.res.Resources; import android.preference.PreferenceManager; import android.util.Log; @@ -32,6 +31,7 @@ import java.util.Locale; public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceChangeListener { private static final String TAG = "KeyboardSwitcher"; private static final boolean DEBUG = false; + public static final boolean DEBUG_STATE = false; public static final int MODE_TEXT = 0; public static final int MODE_URL = 1; @@ -40,11 +40,17 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha public static final int MODE_WEB = 4; public static final int MODE_PHONE = 5; - public static final String DEFAULT_LAYOUT_ID = "4"; + // Changing DEFAULT_LAYOUT_ID also requires prefs_for_debug.xml to be matched with. + public static final String DEFAULT_LAYOUT_ID = "5"; public static final String PREF_KEYBOARD_LAYOUT = "pref_keyboard_layout_20100902"; private static final int[] THEMES = new int [] { - R.layout.input_basic, R.layout.input_basic_highcontrast, R.layout.input_stone_normal, - R.layout.input_stone_bold, R.layout.input_gingerbread}; + R.layout.input_basic, + R.layout.input_basic_highcontrast, + R.layout.input_stone_normal, + R.layout.input_stone_bold, + R.layout.input_gingerbread, + R.layout.input_honeycomb, // DEFAULT_LAYOUT_ID + }; // Ids for each characters' color in the keyboard private static final int CHAR_THEME_COLOR_WHITE = 0; @@ -76,8 +82,8 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha private LatinKeyboardView mInputView; private LatinIME mInputMethodService; - private ShiftKeyState mShiftState = new ShiftKeyState(); - private ModifierKeyState mSymbolKeyState = new ModifierKeyState(); + private ShiftKeyState mShiftKeyState = new ShiftKeyState("Shift"); + private ModifierKeyState mSymbolKeyState = new ModifierKeyState("Symbol"); private KeyboardId mSymbolsId; private KeyboardId mSymbolsShiftedId; @@ -374,10 +380,10 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha latinKeyboard.keyReleased(); } - public boolean isShifted() { + public boolean isShiftedOrShiftLocked() { LatinKeyboard latinKeyboard = getLatinKeyboard(); if (latinKeyboard != null) - return latinKeyboard.isShifted(); + return latinKeyboard.isShiftedOrShiftLocked(); return false; } @@ -388,7 +394,21 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha return false; } - private void setShifted(boolean shifted) { + public boolean isAutomaticTemporaryUpperCase() { + LatinKeyboard latinKeyboard = getLatinKeyboard(); + if (latinKeyboard != null) + return latinKeyboard.isAutomaticTemporaryUpperCase(); + return false; + } + + public boolean isManualTemporaryUpperCase() { + LatinKeyboard latinKeyboard = getLatinKeyboard(); + if (latinKeyboard != null) + return latinKeyboard.isManualTemporaryUpperCase(); + return false; + } + + private void setManualTemporaryUpperCase(boolean shifted) { LatinKeyboard latinKeyboard = getLatinKeyboard(); if (latinKeyboard != null && latinKeyboard.setShifted(shifted)) { mInputView.invalidateAllKeys(); @@ -403,21 +423,13 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha } public void toggleShift() { - handleShiftInternal(false); - } - - private void resetShift() { - handleShiftInternal(true); - } - - private void handleShiftInternal(boolean forceNormal) { mInputMethodService.mHandler.cancelUpdateShiftState(); + if (DEBUG_STATE) + Log.d(TAG, "toggleShift:" + + " keyboard=" + getLatinKeyboard().getKeyboardShiftState() + + " shiftKeyState=" + mShiftKeyState); if (isAlphabetMode()) { - if (forceNormal) { - setShifted(false); - } else { - setShifted(!isShifted()); - } + setManualTemporaryUpperCase(!isShiftedOrShiftLocked()); } else { toggleShiftInSymbol(); } @@ -425,27 +437,50 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha public void toggleCapsLock() { mInputMethodService.mHandler.cancelUpdateShiftState(); + if (DEBUG_STATE) + Log.d(TAG, "toggleCapsLock:" + + " keyboard=" + getLatinKeyboard().getKeyboardShiftState() + + " shiftKeyState=" + mShiftKeyState); if (isAlphabetMode()) { if (isShiftLocked()) { - // setShifted(false) also disable shift locked state. - // Note: Caps lock LED is off when Key.on is false. - setShifted(false); + // Shift key is long pressed while caps lock state, we will toggle back to normal + // state. And mark as if shift key is released. + setShiftLocked(false); + mShiftKeyState.onRelease(); } else { - // setShiftLocked(true) enable shift state too. - // Note: Caps lock LED is on when Key.on is true. setShiftLocked(true); } } } + private void setAutomaticTemporaryUpperCase() { + LatinKeyboard latinKeyboard = getLatinKeyboard(); + if (latinKeyboard != null) { + latinKeyboard.setAutomaticTemporaryUpperCase(); + mInputView.invalidateAllKeys(); + } + } + public void updateShiftState() { - if (isAlphabetMode() && !mShiftState.isIgnoring()) { - final boolean autoCapsMode = mInputMethodService.getCurrentAutoCapsState(); - setShifted(mShiftState.isMomentary() || isShiftLocked() || autoCapsMode); + if (DEBUG_STATE) + Log.d(TAG, "updateShiftState:" + + " autoCaps=" + mInputMethodService.getCurrentAutoCapsState() + + " keyboard=" + getLatinKeyboard().getKeyboardShiftState() + + " shiftKeyState=" + mShiftKeyState); + if (isAlphabetMode() && !isShiftLocked() && !mShiftKeyState.isIgnoring()) { + if (mInputMethodService.getCurrentAutoCapsState()) { + setAutomaticTemporaryUpperCase(); + } else { + setManualTemporaryUpperCase(mShiftKeyState.isMomentary()); + } } } public void changeKeyboardMode() { + if (DEBUG_STATE) + Log.d(TAG, "changeKeyboardMode:" + + " keyboard=" + getLatinKeyboard().getKeyboardShiftState() + + " shiftKeyState=" + mShiftKeyState); toggleKeyboardMode(); if (isShiftLocked() && isAlphabetMode()) setShiftLocked(true); @@ -455,47 +490,82 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha public void onPressShift() { if (!isKeyboardAvailable()) return; - if (isAlphabetMode() && isShifted()) { - // In alphabet mode, we don't call toggleShift() when we are already in the shifted - // state. - mShiftState.onPressOnShifted(); + ShiftKeyState shiftKeyState = mShiftKeyState; + if (DEBUG_STATE) + Log.d(TAG, "onPressShift:" + + " keyboard=" + getLatinKeyboard().getKeyboardShiftState() + + " shiftKeyState=" + shiftKeyState); + if (isAlphabetMode()) { + if (isShiftLocked()) { + // Shift key is pressed while caps lock state, we will treat this state as shifted + // caps lock state and mark as if shift key pressed while normal state. + setManualTemporaryUpperCase(true); + shiftKeyState.onPress(); + } else if (isAutomaticTemporaryUpperCase()) { + // Shift key is pressed while automatic temporary upper case, we have to move to + // manual temporary upper case. + setManualTemporaryUpperCase(true); + shiftKeyState.onPressOnShifted(); + } else if (isShiftedOrShiftLocked()) { + // In manual upper case state, we just record shift key has been pressing while + // shifted state. + shiftKeyState.onPressOnShifted(); + } else { + // In base layout, chording or manual temporary upper case mode is started. + toggleShift(); + shiftKeyState.onPress(); + } } else { - // In alphabet mode, we call toggleShift() to go into the shifted mode only when we are - // not in the shifted state. - // This else clause also handles shift key pressing in symbol mode. - mShiftState.onPress(); + // In symbol mode, just toggle symbol and symbol more keyboard. toggleShift(); + shiftKeyState.onPress(); } } public void onReleaseShift() { if (!isKeyboardAvailable()) return; + ShiftKeyState shiftKeyState = mShiftKeyState; + if (DEBUG_STATE) + Log.d(TAG, "onReleaseShift:" + + " keyboard=" + getLatinKeyboard().getKeyboardShiftState() + + " shiftKeyState=" + shiftKeyState); if (isAlphabetMode()) { - if (mShiftState.isMomentary()) { - resetShift(); - } else if (isShifted() && mShiftState.isPressingOnShifted()) { - // In alphabet mode, we call toggleShift() to go into the non shifted state only - // when we are in the shifted state -- temporary shifted mode or caps lock mode. + if (shiftKeyState.isMomentary()) { + // After chording input while normal state. + toggleShift(); + } else if (isShiftLocked() && !shiftKeyState.isIgnoring()) { + // Shift has been pressed without chording while caps lock state. + toggleCapsLock(); + } else if (isShiftedOrShiftLocked() && shiftKeyState.isPressingOnShifted()) { + // Shift has been pressed without chording while shifted state. toggleShift(); } } - mShiftState.onRelease(); + shiftKeyState.onRelease(); } public void onPressSymbol() { + if (DEBUG_STATE) + Log.d(TAG, "onReleaseShift:" + + " keyboard=" + getLatinKeyboard().getKeyboardShiftState() + + " symbolKeyState=" + mSymbolKeyState); changeKeyboardMode(); mSymbolKeyState.onPress(); } public void onReleaseSymbol() { + if (DEBUG_STATE) + Log.d(TAG, "onReleaseShift:" + + " keyboard=" + getLatinKeyboard().getKeyboardShiftState() + + " symbolKeyState=" + mSymbolKeyState); if (mSymbolKeyState.isMomentary()) changeKeyboardMode(); mSymbolKeyState.onRelease(); } public void onOtherKeyPressed() { - mShiftState.onOtherKeyPressed(); + mShiftKeyState.onOtherKeyPressed(); mSymbolKeyState.onOtherKeyPressed(); } @@ -521,7 +591,7 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha mInputView.setKeyboard(keyboard); } - public void toggleKeyboardMode() { + private void toggleKeyboardMode() { loadKeyboardInternal(mMode, mImeOptions, mVoiceButtonEnabled, mVoiceButtonOnPrimary, !mIsSymbols); if (mIsSymbols) { diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 9a800ba38..307021a37 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); @@ -1001,7 +1004,8 @@ public class LatinIME extends InputMethodService return true; } // Enable shift key and DPAD to do selections - if (mKeyboardSwitcher.isInputViewShown() && mKeyboardSwitcher.isShifted()) { + if (mKeyboardSwitcher.isInputViewShown() + && mKeyboardSwitcher.isShiftedOrShiftLocked()) { event = new KeyEvent(event.getDownTime(), event.getEventTime(), event.getAction(), event.getKeyCode(), event.getRepeatCount(), event.getDeviceId(), event.getScanCode(), @@ -1370,7 +1374,7 @@ public class LatinIME extends InputMethodService } } KeyboardSwitcher switcher = mKeyboardSwitcher; - if (switcher.isShifted()) { + if (switcher.isShiftedOrShiftLocked()) { if (keyCodes == null || keyCodes[0] < Character.MIN_CODE_POINT || keyCodes[0] > Character.MAX_CODE_POINT) { return; @@ -1389,7 +1393,8 @@ public class LatinIME extends InputMethodService } } if (mPredicting) { - if (mComposing.length() == 0 && switcher.isAlphabetMode() && switcher.isShifted()) { + if (mComposing.length() == 0 && switcher.isAlphabetMode() + && switcher.isShiftedOrShiftLocked()) { mWord.setFirstCharCapitalized(true); } mComposing.append((char) primaryCode); @@ -1674,7 +1679,7 @@ public class LatinIME extends InputMethodService final List<CharSequence> nBest = new ArrayList<CharSequence>(); KeyboardSwitcher switcher = mKeyboardSwitcher; boolean capitalizeFirstWord = preferCapitalization() - || (switcher.isAlphabetMode() && switcher.isShifted()); + || (switcher.isAlphabetMode() && switcher.isShiftedOrShiftLocked()); for (String c : mVoiceResults.candidates) { if (capitalizeFirstWord) { c = Character.toUpperCase(c.charAt(0)) + c.substring(1, c.length()); @@ -2176,8 +2181,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 +2264,7 @@ public class LatinIME extends InputMethodService return new FieldContext( getCurrentInputConnection(), getCurrentInputEditorInfo(), - mSubtypeSwitcher.getInputLanguage(), + mSubtypeSwitcher.getInputLocaleStr(), mSubtypeSwitcher.getEnabledLanguages()); } @@ -2372,7 +2387,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 +2434,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 +2595,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/LatinIMEUtil.java b/java/src/com/android/inputmethod/latin/LatinIMEUtil.java index 9ef48a413..e392bfd38 100644 --- a/java/src/com/android/inputmethod/latin/LatinIMEUtil.java +++ b/java/src/com/android/inputmethod/latin/LatinIMEUtil.java @@ -21,6 +21,9 @@ import android.view.inputmethod.InputMethodManager; import android.content.Context; import android.inputmethodservice.InputMethodService; import android.os.AsyncTask; +import android.os.Handler; +import android.os.HandlerThread; +import android.os.Process; import android.text.format.DateUtils; import android.text.format.Time; import android.util.Log; @@ -172,7 +175,7 @@ public class LatinIMEUtil { } } public String getLastString() { - StringBuffer sb = new StringBuffer(); + StringBuilder sb = new StringBuilder(); for (int i = 0; i < mLength; ++i) { char c = mCharBuf[normalize(mEnd - 1 - i)]; if (!((LatinIME)mContext).isWordSeparator(c)) { @@ -247,16 +250,22 @@ public class LatinIMEUtil { private static final String FILENAME = "log.txt"; private static final UsabilityStudyLogUtils sInstance = new UsabilityStudyLogUtils(); + private final Handler mLoggingHandler; private File mFile; private File mDirectory; private InputMethodService mIms; private PrintWriter mWriter; - private Date mDate; - private SimpleDateFormat mDateFormat; + private final Date mDate; + private final SimpleDateFormat mDateFormat; private UsabilityStudyLogUtils() { mDate = new Date(); mDateFormat = new SimpleDateFormat("dd MMM HH:mm:ss.SSS"); + + HandlerThread handlerThread = new HandlerThread("UsabilityStudyLogUtils logging task", + Process.THREAD_PRIORITY_BACKGROUND); + handlerThread.start(); + mLoggingHandler = new Handler(handlerThread.getLooper()); } public static UsabilityStudyLogUtils getInstance() { @@ -266,7 +275,6 @@ public class LatinIMEUtil { public void init(InputMethodService ims) { mIms = ims; mDirectory = ims.getFilesDir(); - createLogFileIfNotExist(); } private void createLogFileIfNotExist() { @@ -301,51 +309,63 @@ public class LatinIMEUtil { LatinImeLogger.onPrintAllUsabilityStudtyLogs(); } - public void write(String log) { - createLogFileIfNotExist(); - final long currentTime = System.currentTimeMillis(); - mDate.setTime(currentTime); + public void write(final String log) { + mLoggingHandler.post(new Runnable() { + public void run() { + createLogFileIfNotExist(); + final long currentTime = System.currentTimeMillis(); + mDate.setTime(currentTime); - final String printString = String.format("%s\t%d\t%s\n", mDateFormat.format(mDate), - currentTime, log); - if (LatinImeLogger.sDBG) { - Log.d(TAG, "Write: " + log); - } - mWriter.print(printString); - mWriter.flush(); + final String printString = String.format("%s\t%d\t%s\n", + mDateFormat.format(mDate), currentTime, log); + if (LatinImeLogger.sDBG) { + Log.d(TAG, "Write: " + log); + } + mWriter.print(printString); + } + }); } public void printAll() { - StringBuffer sb = new StringBuffer(); - BufferedReader br = getBufferedReader(); - String line; - try { - while ((line = br.readLine()) != null) { - sb.append('\n'); - sb.append(line); + mLoggingHandler.post(new Runnable() { + public void run() { + mWriter.flush(); + StringBuilder sb = new StringBuilder(); + BufferedReader br = getBufferedReader(); + String line; + try { + while ((line = br.readLine()) != null) { + sb.append('\n'); + sb.append(line); + } + } catch (IOException e) { + Log.e(TAG, "Can't read log file."); + } finally { + if (LatinImeLogger.sDBG) { + Log.d(TAG, "output all logs\n" + sb.toString()); + } + mIms.getCurrentInputConnection().commitText(sb.toString(), 0); + try { + br.close(); + } catch (IOException e) { + } + } } - } catch (IOException e) { - Log.e(TAG, "Can't read log file."); - } finally { - if (LatinImeLogger.sDBG) { - Log.d(TAG, "output all logs\n" + sb.toString()); - } - mIms.getCurrentInputConnection().commitText(sb.toString(), 0); - try { - br.close(); - } catch (IOException e) { - } - } + }); } public void clearAll() { - if (mFile != null && mFile.exists()) { - if (LatinImeLogger.sDBG) { - Log.d(TAG, "Delete log file."); + mLoggingHandler.post(new Runnable() { + public void run() { + if (mFile != null && mFile.exists()) { + if (LatinImeLogger.sDBG) { + Log.d(TAG, "Delete log file."); + } + mFile.delete(); + mWriter.close(); + } } - mFile.delete(); - mWriter.close(); - } + }); } private BufferedReader getBufferedReader() { @@ -365,7 +385,7 @@ public class LatinIMEUtil { mFile.delete(); } } - return new PrintWriter(new FileOutputStream(mFile)); + return new PrintWriter(new FileOutputStream(mFile), true /* autoFlush */); } } } diff --git a/java/src/com/android/inputmethod/latin/LatinKeyboard.java b/java/src/com/android/inputmethod/latin/LatinKeyboard.java index 9473eaf84..6fcea227d 100644 --- a/java/src/com/android/inputmethod/latin/LatinKeyboard.java +++ b/java/src/com/android/inputmethod/latin/LatinKeyboard.java @@ -46,9 +46,9 @@ public class LatinKeyboard extends BaseKeyboard { private static final int OPACITY_FULLY_OPAQUE = 255; private static final int SPACE_LED_LENGTH_PERCENT = 80; - private Drawable mShiftLockIcon; + private Drawable mShiftedIcon; private Drawable mShiftLockPreviewIcon; - private final HashMap<Key, Drawable> mOldShiftIcons = new HashMap<Key, Drawable>(); + private final HashMap<Key, Drawable> mNormalShiftIcons = new HashMap<Key, Drawable>(); private Drawable mSpaceIcon; private Drawable mSpaceAutoCompletionIndicator; private Drawable mSpacePreviewIcon; @@ -92,11 +92,7 @@ public class LatinKeyboard extends BaseKeyboard { // TODO: generalize for any keyboardId private boolean mIsBlackSym; - private static final int SHIFT_OFF = 0; - private static final int SHIFT_ON = 1; - private static final int SHIFT_LOCKED = 2; - - private int mShiftState = SHIFT_OFF; + private LatinKeyboardShiftState mShiftState = new LatinKeyboardShiftState(); private static final float SPACEBAR_DRAG_THRESHOLD = 0.8f; private static final float OVERLAP_PERCENTAGE_LOW_PROB = 0.70f; @@ -117,7 +113,7 @@ public class LatinKeyboard extends BaseKeyboard { mContext = context; mRes = res; mMode = id.mMode; - mShiftLockIcon = res.getDrawable(R.drawable.sym_keyboard_shift_locked); + mShiftedIcon = res.getDrawable(R.drawable.sym_keyboard_shift_locked); mShiftLockPreviewIcon = res.getDrawable(R.drawable.sym_keyboard_feedback_shift_locked); setDefaultBounds(mShiftLockPreviewIcon); mSpaceIcon = res.getDrawable(R.drawable.sym_keyboard_space); @@ -226,61 +222,62 @@ public class LatinKeyboard extends BaseKeyboard { if (key instanceof LatinKey) { ((LatinKey)key).enableShiftLock(); } - mOldShiftIcons.put(key, key.icon); + mNormalShiftIcons.put(key, key.icon); } } - public boolean setShiftLocked(boolean shiftLocked) { - // TODO: cleanup this method with BaseKeyboard.Key + public boolean setShiftLocked(boolean newShiftLockState) { for (final Key key : getShiftKeys()) { - key.on = shiftLocked; - key.icon = mShiftLockIcon; + key.on = newShiftLockState; + key.icon = newShiftLockState ? mShiftedIcon : mNormalShiftIcons.get(key); } - mShiftState = shiftLocked ? SHIFT_LOCKED : SHIFT_ON; + mShiftState.setShiftLocked(newShiftLockState); return true; } public boolean isShiftLocked() { - return mShiftState == SHIFT_LOCKED; + return mShiftState.isShiftLocked(); } @Override - public boolean setShifted(boolean shiftState) { - // TODO: cleanup this method with BaseKeyboard.Key. - boolean shiftChanged = false; - if (getShiftKeys().size() > 0) { - for (final Key key : getShiftKeys()) { - if (shiftState == false) { - key.on = false; - key.icon = mOldShiftIcons.get(key); - } else if (mShiftState == SHIFT_OFF) { - key.icon = mShiftLockIcon; - } - } - if (shiftState == false) { - shiftChanged = mShiftState != SHIFT_OFF; - mShiftState = SHIFT_OFF; - } else if (mShiftState == SHIFT_OFF) { - shiftChanged = mShiftState == SHIFT_OFF; - mShiftState = SHIFT_ON; + public boolean setShifted(boolean newShiftState) { + if (getShiftKeys().size() == 0) + return super.setShifted(newShiftState); + + for (final Key key : getShiftKeys()) { + if (!newShiftState && !mShiftState.isShiftLocked()) { + key.icon = mNormalShiftIcons.get(key); + } else if (newShiftState && !mShiftState.isShiftedOrShiftLocked()) { + key.icon = mShiftedIcon; } - return shiftChanged; - } else { - return super.setShifted(shiftState); } + return mShiftState.setShifted(newShiftState); } @Override - public boolean isShifted() { + public boolean isShiftedOrShiftLocked() { if (getShiftKeys().size() > 0) { - return mShiftState != SHIFT_OFF; + return mShiftState.isShiftedOrShiftLocked(); } else { - return super.isShifted(); + return super.isShiftedOrShiftLocked(); } } - public boolean isTemporaryUpperCase() { - return mIsAlphaKeyboard && isShifted() && !isShiftLocked(); + public void setAutomaticTemporaryUpperCase() { + setShifted(true); + mShiftState.setAutomaticTemporaryUpperCase(); + } + + public boolean isAutomaticTemporaryUpperCase() { + return mIsAlphaKeyboard && mShiftState.isAutomaticTemporaryUpperCase(); + } + + public boolean isManualTemporaryUpperCase() { + return mIsAlphaKeyboard && mShiftState.isManualTemporaryUpperCase(); + } + + /* package */ LatinKeyboardShiftState getKeyboardShiftState() { + return mShiftState; } public boolean isAlphaKeyboard() { @@ -291,12 +288,12 @@ public class LatinKeyboard extends BaseKeyboard { mIsBlackSym = isBlack; final Resources res = mRes; if (isBlack) { - mShiftLockIcon = res.getDrawable(R.drawable.sym_bkeyboard_shift_locked); + mShiftedIcon = res.getDrawable(R.drawable.sym_bkeyboard_shift_locked); mSpaceIcon = res.getDrawable(R.drawable.sym_bkeyboard_space); mMicIcon = res.getDrawable(R.drawable.sym_bkeyboard_mic); m123MicIcon = res.getDrawable(R.drawable.sym_bkeyboard_123_mic); } else { - mShiftLockIcon = res.getDrawable(R.drawable.sym_keyboard_shift_locked); + mShiftedIcon = res.getDrawable(R.drawable.sym_keyboard_shift_locked); mSpaceIcon = res.getDrawable(R.drawable.sym_keyboard_space); mMicIcon = res.getDrawable(R.drawable.sym_keyboard_mic); m123MicIcon = res.getDrawable(R.drawable.sym_keyboard_123_mic); @@ -419,7 +416,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 +432,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/LatinKeyboardShiftState.java b/java/src/com/android/inputmethod/latin/LatinKeyboardShiftState.java new file mode 100644 index 000000000..74c474293 --- /dev/null +++ b/java/src/com/android/inputmethod/latin/LatinKeyboardShiftState.java @@ -0,0 +1,88 @@ +package com.android.inputmethod.latin; + +import android.util.Log; + +public class LatinKeyboardShiftState { + private static final String TAG = "LatinKeyboardShiftState"; + private static final boolean DEBUG = KeyboardSwitcher.DEBUG_STATE; + + private static final int NORMAL = 0; + private static final int MANUAL_SHIFTED = 1; + private static final int SHIFT_LOCKED = 2; + private static final int AUTO_SHIFTED = 3; + private static final int SHIFT_LOCK_SHIFTED = 4; + + private int mState = NORMAL; + + public boolean setShifted(boolean newShiftState) { + final int oldState = mState; + if (newShiftState) { + if (oldState == NORMAL || oldState == AUTO_SHIFTED) { + mState = MANUAL_SHIFTED; + } else if (oldState == SHIFT_LOCKED) { + mState = SHIFT_LOCK_SHIFTED; + } + } else { + if (oldState == MANUAL_SHIFTED || oldState == AUTO_SHIFTED) { + mState = NORMAL; + } else if (oldState == SHIFT_LOCK_SHIFTED) { + mState = SHIFT_LOCKED; + } + } + if (DEBUG) + Log.d(TAG, "setShifted: " + toString(oldState) + " > " + this); + return mState != oldState; + } + + public void setShiftLocked(boolean newShiftLockState) { + final int oldState = mState; + if (newShiftLockState) { + if (oldState == NORMAL || oldState == MANUAL_SHIFTED || oldState == AUTO_SHIFTED) + mState = SHIFT_LOCKED; + } else { + if (oldState == SHIFT_LOCKED || oldState == SHIFT_LOCK_SHIFTED) + mState = NORMAL; + } + if (DEBUG) + Log.d(TAG, "setShiftLocked: " + toString(oldState) + " > " + this); + } + + public void setAutomaticTemporaryUpperCase() { + final int oldState = mState; + mState = AUTO_SHIFTED; + if (DEBUG) + Log.d(TAG, "setAutomaticTemporaryUpperCase: " + toString(oldState) + " > " + this); + } + + public boolean isShiftedOrShiftLocked() { + return mState != NORMAL; + } + + public boolean isShiftLocked() { + return mState == SHIFT_LOCKED || mState == SHIFT_LOCK_SHIFTED; + } + + public boolean isAutomaticTemporaryUpperCase() { + return mState == AUTO_SHIFTED; + } + + public boolean isManualTemporaryUpperCase() { + return mState == MANUAL_SHIFTED || mState == SHIFT_LOCK_SHIFTED; + } + + @Override + public String toString() { + return toString(mState); + } + + private static String toString(int state) { + switch (state) { + case NORMAL: return "NORMAL"; + case MANUAL_SHIFTED: return "MANUAL_SHIFTED"; + case SHIFT_LOCKED: return "SHIFT_LOCKED"; + case AUTO_SHIFTED: return "AUTO_SHIFTED"; + case SHIFT_LOCK_SHIFTED: return "SHIFT_LOCK_SHIFTED"; + default: return "UKNOWN"; + } + } +}
\ No newline at end of file diff --git a/java/src/com/android/inputmethod/latin/LatinKeyboardView.java b/java/src/com/android/inputmethod/latin/LatinKeyboardView.java index 3bcac4ec1..a215621d1 100644 --- a/java/src/com/android/inputmethod/latin/LatinKeyboardView.java +++ b/java/src/com/android/inputmethod/latin/LatinKeyboardView.java @@ -119,7 +119,7 @@ public class LatinKeyboardView extends BaseKeyboardView { protected CharSequence adjustCase(CharSequence label) { LatinKeyboard keyboard = getLatinKeyboard(); if (keyboard.isAlphaKeyboard() - && keyboard.isShifted() + && keyboard.isShiftedOrShiftLocked() && !TextUtils.isEmpty(label) && label.length() < 3 && Character.isLowerCase(label.charAt(0))) { label = label.toString().toUpperCase(); diff --git a/java/src/com/android/inputmethod/latin/ModifierKeyState.java b/java/src/com/android/inputmethod/latin/ModifierKeyState.java index 8139ec531..07a5c4f7f 100644 --- a/java/src/com/android/inputmethod/latin/ModifierKeyState.java +++ b/java/src/com/android/inputmethod/latin/ModifierKeyState.java @@ -16,26 +16,60 @@ package com.android.inputmethod.latin; +import android.util.Log; + public class ModifierKeyState { + protected static final String TAG = "ModifierKeyState"; + protected static final boolean DEBUG = KeyboardSwitcher.DEBUG_STATE; + protected static final int RELEASING = 0; protected static final int PRESSING = 1; protected static final int MOMENTARY = 2; + protected final String mName; protected int mState = RELEASING; + public ModifierKeyState(String name) { + mName = name; + } + public void onPress() { + final int oldState = mState; mState = PRESSING; + if (DEBUG) + Log.d(TAG, mName + ".onPress: " + toString(oldState) + " > " + this); } public void onRelease() { + final int oldState = mState; mState = RELEASING; + if (DEBUG) + Log.d(TAG, mName + ".onRelease: " + toString(oldState) + " > " + this); } public void onOtherKeyPressed() { - mState = MOMENTARY; + final int oldState = mState; + if (mState == PRESSING) + mState = MOMENTARY; + if (DEBUG) + Log.d(TAG, mName + ".onOtherKeyPressed: " + toString(oldState) + " > " + this); } public boolean isMomentary() { return mState == MOMENTARY; } + + @Override + public String toString() { + return toString(mState); + } + + protected static String toString(int state) { + switch (state) { + case RELEASING: return "RELEASING"; + case PRESSING: return "PRESSING"; + case MOMENTARY: return "MOMENTARY"; + default: return "UNKNOWN"; + } + } } diff --git a/java/src/com/android/inputmethod/latin/PointerTracker.java b/java/src/com/android/inputmethod/latin/PointerTracker.java index e76f8c705..4d9133045 100644 --- a/java/src/com/android/inputmethod/latin/PointerTracker.java +++ b/java/src/com/android/inputmethod/latin/PointerTracker.java @@ -423,9 +423,9 @@ public class PointerTracker { } } - private boolean isTemporaryUpperCase() { + private boolean isManualTemporaryUpperCase() { return mKeyboard instanceof LatinKeyboard - && ((LatinKeyboard)mKeyboard).isTemporaryUpperCase(); + && ((LatinKeyboard)mKeyboard).isManualTemporaryUpperCase(); } private void detectAndSendKey(int index, int x, int y, long eventTime) { @@ -458,7 +458,7 @@ public class PointerTracker { // If keyboard is in manual temporary upper case state and key has manual temporary // shift code, alternate character code should be sent. - if (isTemporaryUpperCase() && key.manualTemporaryUpperCaseCode != 0) { + if (isManualTemporaryUpperCase() && key.manualTemporaryUpperCaseCode != 0) { code = key.manualTemporaryUpperCaseCode; codes[0] = code; } diff --git a/java/src/com/android/inputmethod/latin/ShiftKeyState.java b/java/src/com/android/inputmethod/latin/ShiftKeyState.java index 5312ce2cc..ef13ddc9b 100644 --- a/java/src/com/android/inputmethod/latin/ShiftKeyState.java +++ b/java/src/com/android/inputmethod/latin/ShiftKeyState.java @@ -16,21 +16,33 @@ package com.android.inputmethod.latin; +import android.util.Log; + public class ShiftKeyState extends ModifierKeyState { private static final int PRESSING_ON_SHIFTED = 3; // both temporary shifted & shift locked private static final int IGNORING = 4; + public ShiftKeyState(String name) { + super(name); + } + @Override public void onOtherKeyPressed() { + int oldState = mState; if (mState == PRESSING) { mState = MOMENTARY; } else if (mState == PRESSING_ON_SHIFTED) { mState = IGNORING; } + if (DEBUG) + Log.d(TAG, mName + ".onOtherKeyPressed: " + toString(oldState) + " > " + this); } public void onPressOnShifted() { + int oldState = mState; mState = PRESSING_ON_SHIFTED; + if (DEBUG) + Log.d(TAG, mName + ".onPressOnShifted: " + toString(oldState) + " > " + this); } public boolean isPressingOnShifted() { @@ -40,4 +52,17 @@ public class ShiftKeyState extends ModifierKeyState { public boolean isIgnoring() { return mState == IGNORING; } + + @Override + public String toString() { + return toString(mState); + } + + protected static String toString(int state) { + switch (state) { + case PRESSING_ON_SHIFTED: return "PRESSING_ON_SHIFTED"; + case IGNORING: return "IGNORING"; + default: return ModifierKeyState.toString(state); + } + } } 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<InputMethodSubtype> mEnabledKeyboardSubtypesOfCurrentInputMethod = + new ArrayList<InputMethodSubtype>(); + private final ArrayList<String> mEnabledLanguagesOfCurrentInputMethod = new ArrayList<String>(); + + /*-----------------------------------------------------------*/ + // Variants which should be changed only by reload functions. private Locale mSystemLocale; + private Locale mInputLocale; + private String mInputLocaleStr; + private String mMode; + private List<InputMethodSubtype> 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) { diff --git a/java/src/com/android/inputmethod/latin/Tutorial.java b/java/src/com/android/inputmethod/latin/Tutorial.java index 3563a8c73..cd7636f3c 100644 --- a/java/src/com/android/inputmethod/latin/Tutorial.java +++ b/java/src/com/android/inputmethod/latin/Tutorial.java @@ -217,7 +217,7 @@ public class Tutorial implements OnTouchListener { return; } if (mBubbleIndex == 3 || mBubbleIndex == 4) { - mKeyboardSwitcher.toggleKeyboardMode(); + mKeyboardSwitcher.changeKeyboardMode(); } mHandler.sendMessageDelayed( mHandler.obtainMessage(MSG_SHOW_BUBBLE, mBubbles.get(mBubbleIndex)), 500); |