am 15dbd382: [ML14] Forward the locale list to relevant places

* commit '15dbd38283fc9c8fdfd2540f1d94d4dbf2eabcb5':
  [ML14] Forward the locale list to relevant places
main
Jean Chalard 2014-10-03 14:30:45 +00:00 committed by Android Git Automerger
commit 6e724cfb66
15 changed files with 163 additions and 110 deletions

View File

@ -278,8 +278,8 @@ public class Key implements Comparable<Key> {
mLabelFlags = style.getFlags(keyAttr, R.styleable.Keyboard_Key_keyLabelFlags) mLabelFlags = style.getFlags(keyAttr, R.styleable.Keyboard_Key_keyLabelFlags)
| row.getDefaultKeyLabelFlags(); | row.getDefaultKeyLabelFlags();
final boolean needsToUpperCase = needsToUpperCase(mLabelFlags, params.mId.mElementId); final boolean needsToUpcase = needsToUpcase(mLabelFlags, params.mId.mElementId);
final Locale locale = params.mId.mLocale; final Locale localeForUpcasing = params.mId.getLocales()[0];
int actionFlags = style.getFlags(keyAttr, R.styleable.Keyboard_Key_keyActionFlags); int actionFlags = style.getFlags(keyAttr, R.styleable.Keyboard_Key_keyActionFlags);
String[] moreKeys = style.getStringArray(keyAttr, R.styleable.Keyboard_Key_moreKeys); String[] moreKeys = style.getStringArray(keyAttr, R.styleable.Keyboard_Key_moreKeys);
@ -321,7 +321,7 @@ public class Key implements Comparable<Key> {
actionFlags |= ACTION_FLAGS_ENABLE_LONG_PRESS; actionFlags |= ACTION_FLAGS_ENABLE_LONG_PRESS;
mMoreKeys = new MoreKeySpec[moreKeys.length]; mMoreKeys = new MoreKeySpec[moreKeys.length];
for (int i = 0; i < moreKeys.length; i++) { for (int i = 0; i < moreKeys.length; i++) {
mMoreKeys[i] = new MoreKeySpec(moreKeys[i], needsToUpperCase, locale); mMoreKeys[i] = new MoreKeySpec(moreKeys[i], needsToUpcase, localeForUpcasing);
} }
} else { } else {
mMoreKeys = null; mMoreKeys = null;
@ -342,16 +342,16 @@ public class Key implements Comparable<Key> {
mLabel = new StringBuilder().appendCodePoint(code).toString(); mLabel = new StringBuilder().appendCodePoint(code).toString();
} else { } else {
mLabel = StringUtils.toUpperCaseOfStringForLocale( mLabel = StringUtils.toUpperCaseOfStringForLocale(
KeySpecParser.getLabel(keySpec), needsToUpperCase, locale); KeySpecParser.getLabel(keySpec), needsToUpcase, localeForUpcasing);
} }
if ((mLabelFlags & LABEL_FLAGS_DISABLE_HINT_LABEL) != 0) { if ((mLabelFlags & LABEL_FLAGS_DISABLE_HINT_LABEL) != 0) {
mHintLabel = null; mHintLabel = null;
} else { } else {
mHintLabel = StringUtils.toUpperCaseOfStringForLocale(style.getString(keyAttr, mHintLabel = StringUtils.toUpperCaseOfStringForLocale(style.getString(keyAttr,
R.styleable.Keyboard_Key_keyHintLabel), needsToUpperCase, locale); R.styleable.Keyboard_Key_keyHintLabel), needsToUpcase, localeForUpcasing);
} }
String outputText = StringUtils.toUpperCaseOfStringForLocale( String outputText = StringUtils.toUpperCaseOfStringForLocale(
KeySpecParser.getOutputText(keySpec), needsToUpperCase, locale); KeySpecParser.getOutputText(keySpec), needsToUpcase, localeForUpcasing);
// Choose the first letter of the label as primary code if not specified. // Choose the first letter of the label as primary code if not specified.
if (code == CODE_UNSPECIFIED && TextUtils.isEmpty(outputText) if (code == CODE_UNSPECIFIED && TextUtils.isEmpty(outputText)
&& !TextUtils.isEmpty(mLabel)) { && !TextUtils.isEmpty(mLabel)) {
@ -377,12 +377,12 @@ public class Key implements Comparable<Key> {
mCode = CODE_OUTPUT_TEXT; mCode = CODE_OUTPUT_TEXT;
} }
} else { } else {
mCode = StringUtils.toUpperCaseOfCodeForLocale(code, needsToUpperCase, locale); mCode = StringUtils.toUpperCaseOfCodeForLocale(code, needsToUpcase, localeForUpcasing);
} }
final int altCodeInAttr = KeySpecParser.parseCode( final int altCodeInAttr = KeySpecParser.parseCode(
style.getString(keyAttr, R.styleable.Keyboard_Key_altCode), CODE_UNSPECIFIED); style.getString(keyAttr, R.styleable.Keyboard_Key_altCode), CODE_UNSPECIFIED);
final int altCode = StringUtils.toUpperCaseOfCodeForLocale( final int altCode = StringUtils.toUpperCaseOfCodeForLocale(
altCodeInAttr, needsToUpperCase, locale); altCodeInAttr, needsToUpcase, localeForUpcasing);
mOptionalAttributes = OptionalAttributes.newInstance(outputText, altCode, mOptionalAttributes = OptionalAttributes.newInstance(outputText, altCode,
disabledIconId, visualInsetsLeft, visualInsetsRight); disabledIconId, visualInsetsLeft, visualInsetsRight);
mKeyVisualAttributes = KeyVisualAttributes.newInstance(keyAttr); mKeyVisualAttributes = KeyVisualAttributes.newInstance(keyAttr);
@ -432,7 +432,7 @@ public class Key implements Comparable<Key> {
return (filteredMoreKeys == moreKeys) ? key : new Key(key, filteredMoreKeys); return (filteredMoreKeys == moreKeys) ? key : new Key(key, filteredMoreKeys);
} }
private static boolean needsToUpperCase(final int labelFlags, final int keyboardElementId) { private static boolean needsToUpcase(final int labelFlags, final int keyboardElementId) {
if ((labelFlags & LABEL_FLAGS_PRESERVE_CASE) != 0) return false; if ((labelFlags & LABEL_FLAGS_PRESERVE_CASE) != 0) return false;
switch (keyboardElementId) { switch (keyboardElementId) {
case KeyboardId.ELEMENT_ALPHABET_MANUAL_SHIFTED: case KeyboardId.ELEMENT_ALPHABET_MANUAL_SHIFTED:

View File

@ -63,7 +63,6 @@ public final class KeyboardId {
public static final int ELEMENT_EMOJI_CATEGORY6 = 16; public static final int ELEMENT_EMOJI_CATEGORY6 = 16;
public final RichInputMethodSubtype mSubtype; public final RichInputMethodSubtype mSubtype;
public final Locale mLocale;
public final int mWidth; public final int mWidth;
public final int mHeight; public final int mHeight;
public final int mMode; public final int mMode;
@ -79,7 +78,6 @@ public final class KeyboardId {
public KeyboardId(final int elementId, final KeyboardLayoutSet.Params params) { public KeyboardId(final int elementId, final KeyboardLayoutSet.Params params) {
mSubtype = params.mSubtype; mSubtype = params.mSubtype;
mLocale = SubtypeLocaleUtils.getSubtypeLocale(mSubtype);
mWidth = params.mKeyboardWidth; mWidth = params.mKeyboardWidth;
mHeight = params.mKeyboardHeight; mHeight = params.mKeyboardHeight;
mMode = params.mMode; mMode = params.mMode;
@ -167,6 +165,10 @@ public final class KeyboardId {
return InputTypeUtils.getImeOptionsActionIdFromEditorInfo(mEditorInfo); return InputTypeUtils.getImeOptionsActionIdFromEditorInfo(mEditorInfo);
} }
public Locale[] getLocales() {
return mSubtype.getLocales();
}
@Override @Override
public boolean equals(final Object other) { public boolean equals(final Object other) {
return other instanceof KeyboardId && equals((KeyboardId) other); return other instanceof KeyboardId && equals((KeyboardId) other);
@ -181,7 +183,8 @@ public final class KeyboardId {
public String toString() { public String toString() {
return String.format(Locale.ROOT, "[%s %s:%s %dx%d %s %s%s%s%s%s%s%s%s%s]", return String.format(Locale.ROOT, "[%s %s:%s %dx%d %s %s%s%s%s%s%s%s%s%s]",
elementIdToName(mElementId), elementIdToName(mElementId),
mLocale, mSubtype.getExtraValueOf(KEYBOARD_LAYOUT_SET), Arrays.deepToString(mSubtype.getLocales()),
mSubtype.getExtraValueOf(KEYBOARD_LAYOUT_SET),
mWidth, mHeight, mWidth, mHeight,
modeName(mMode), modeName(mMode),
actionName(imeAction()), actionName(imeAction()),

View File

@ -120,7 +120,9 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
mKeyboardLayoutSet = builder.build(); mKeyboardLayoutSet = builder.build();
try { try {
mState.onLoadKeyboard(currentAutoCapsState, currentRecapitalizeState); mState.onLoadKeyboard(currentAutoCapsState, currentRecapitalizeState);
mKeyboardTextsSet.setLocale(mSubtypeSwitcher.getCurrentSubtypeLocale(), mThemeContext); // TODO: revisit this for multi-lingual input
mKeyboardTextsSet.setLocale(mSubtypeSwitcher.getCurrentSubtypeLocales()[0],
mThemeContext);
} catch (KeyboardLayoutSetException e) { } catch (KeyboardLayoutSetException e) {
Log.w(TAG, "loading keyboard failed: " + e.mKeyboardId, e.getCause()); Log.w(TAG, "loading keyboard failed: " + e.mKeyboardId, e.getCause());
return; return;
@ -161,7 +163,7 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
currentSettingsValues.mKeyPreviewDismissDuration); currentSettingsValues.mKeyPreviewDismissDuration);
keyboardView.updateShortcutKey(mSubtypeSwitcher.isShortcutImeReady()); keyboardView.updateShortcutKey(mSubtypeSwitcher.isShortcutImeReady());
final boolean subtypeChanged = (oldKeyboard == null) final boolean subtypeChanged = (oldKeyboard == null)
|| !keyboard.mId.mLocale.equals(oldKeyboard.mId.mLocale); || !keyboard.mId.mSubtype.equals(oldKeyboard.mId.mSubtype);
final int languageOnSpacebarFormatType = mSubtypeSwitcher.getLanguageOnSpacebarFormatType( final int languageOnSpacebarFormatType = mSubtypeSwitcher.getLanguageOnSpacebarFormatType(
keyboard.mId.mSubtype); keyboard.mId.mSubtype);
final boolean hasMultipleEnabledIMEsOrSubtypes = RichInputMethodManager.getInstance() final boolean hasMultipleEnabledIMEsOrSubtypes = RichInputMethodManager.getInstance()

View File

@ -875,6 +875,11 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
// Layout language name on spacebar. // Layout language name on spacebar.
private String layoutLanguageOnSpacebar(final Paint paint, private String layoutLanguageOnSpacebar(final Paint paint,
final RichInputMethodSubtype subtype, final int width) { final RichInputMethodSubtype subtype, final int width) {
if (mLanguageOnSpacebarFormatType == LanguageOnSpacebarHelper.FORMAT_TYPE_MULTIPLE) {
// TODO: return an appropriate string
return "";
}
// Choose appropriate language name to fit into the width. // Choose appropriate language name to fit into the width.
if (mLanguageOnSpacebarFormatType == LanguageOnSpacebarHelper.FORMAT_TYPE_FULL_LOCALE) { if (mLanguageOnSpacebarFormatType == LanguageOnSpacebarHelper.FORMAT_TYPE_FULL_LOCALE) {
final String fullText = subtype.getFullDisplayName(); final String fullText = subtype.getFullDisplayName();

View File

@ -45,6 +45,7 @@ import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException; import java.io.IOException;
import java.util.Arrays; import java.util.Arrays;
import java.util.Locale;
/** /**
* Keyboard Building helper. * Keyboard Building helper.
@ -281,7 +282,8 @@ public class KeyboardBuilder<KP extends KeyboardParams> {
params.mThemeId = keyboardAttr.getInt(R.styleable.Keyboard_themeId, 0); params.mThemeId = keyboardAttr.getInt(R.styleable.Keyboard_themeId, 0);
params.mIconsSet.loadIcons(keyboardAttr); params.mIconsSet.loadIcons(keyboardAttr);
params.mTextsSet.setLocale(params.mId.mLocale, mContext); // TODO: this needs to be revisited for multi-lingual input.
params.mTextsSet.setLocale(params.mId.getLocales()[0], mContext);
final int resourceId = keyboardAttr.getResourceId( final int resourceId = keyboardAttr.getResourceId(
R.styleable.Keyboard_touchPositionCorrectionData, 0); R.styleable.Keyboard_touchPositionCorrectionData, 0);
@ -672,12 +674,10 @@ public class KeyboardBuilder<KP extends KeyboardParams> {
R.styleable.Keyboard_Case_imeAction, id.imeAction()); R.styleable.Keyboard_Case_imeAction, id.imeAction());
final boolean isIconDefinedMatched = isIconDefined(caseAttr, final boolean isIconDefinedMatched = isIconDefined(caseAttr,
R.styleable.Keyboard_Case_isIconDefined, mParams.mIconsSet); R.styleable.Keyboard_Case_isIconDefined, mParams.mIconsSet);
final boolean localeCodeMatched = matchString(caseAttr, final Locale[] locales = id.getLocales();
R.styleable.Keyboard_Case_localeCode, id.mLocale.toString()); final boolean localeCodeMatched = matchLocaleCodes(caseAttr, locales);
final boolean languageCodeMatched = matchString(caseAttr, final boolean languageCodeMatched = matchLanguageCodes(caseAttr, locales);
R.styleable.Keyboard_Case_languageCode, id.mLocale.getLanguage()); final boolean countryCodeMatched = matchCountryCodes(caseAttr, locales);
final boolean countryCodeMatched = matchString(caseAttr,
R.styleable.Keyboard_Case_countryCode, id.mLocale.getCountry());
final boolean splitLayoutMatched = matchBoolean(caseAttr, final boolean splitLayoutMatched = matchBoolean(caseAttr,
R.styleable.Keyboard_Case_isSplitLayout, id.mIsSplitLayout); R.styleable.Keyboard_Case_isSplitLayout, id.mIsSplitLayout);
final boolean selected = keyboardLayoutSetMatched && keyboardLayoutSetElementMatched final boolean selected = keyboardLayoutSetMatched && keyboardLayoutSetElementMatched
@ -733,6 +733,23 @@ public class KeyboardBuilder<KP extends KeyboardParams> {
} }
} }
private boolean matchLocaleCodes(TypedArray caseAttr, final Locale[] locales) {
// TODO: adujst this for multilingual input
return matchString(caseAttr, R.styleable.Keyboard_Case_languageCode, locales[0].toString());
}
private boolean matchLanguageCodes(TypedArray caseAttr, Locale[] locales) {
// TODO: adujst this for multilingual input
return matchString(caseAttr, R.styleable.Keyboard_Case_languageCode,
locales[0].getLanguage());
}
private boolean matchCountryCodes(TypedArray caseAttr, Locale[] locales) {
// TODO: adujst this for multilingual input
return matchString(caseAttr, R.styleable.Keyboard_Case_countryCode,
locales[0].getCountry());
}
private static boolean matchInteger(final TypedArray a, final int index, final int value) { private static boolean matchInteger(final TypedArray a, final int index, final int value) {
// If <case> does not have "index" attribute, that means this <case> is wild-card for // If <case> does not have "index" attribute, that means this <case> is wild-card for
// the attribute. // the attribute.

View File

@ -23,6 +23,7 @@ import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Locale;
/** /**
* This class determines that the language name on the spacebar should be displayed in what format. * This class determines that the language name on the spacebar should be displayed in what format.
@ -31,6 +32,7 @@ public final class LanguageOnSpacebarHelper {
public static final int FORMAT_TYPE_NONE = 0; public static final int FORMAT_TYPE_NONE = 0;
public static final int FORMAT_TYPE_LANGUAGE_ONLY = 1; public static final int FORMAT_TYPE_LANGUAGE_ONLY = 1;
public static final int FORMAT_TYPE_FULL_LOCALE = 2; public static final int FORMAT_TYPE_FULL_LOCALE = 2;
public static final int FORMAT_TYPE_MULTIPLE = 3;
private List<InputMethodSubtype> mEnabledSubtypes = Collections.emptyList(); private List<InputMethodSubtype> mEnabledSubtypes = Collections.emptyList();
private boolean mIsSystemLanguageSameAsInputLanguage; private boolean mIsSystemLanguageSameAsInputLanguage;
@ -43,7 +45,11 @@ public final class LanguageOnSpacebarHelper {
if (mEnabledSubtypes.size() < 2 && mIsSystemLanguageSameAsInputLanguage) { if (mEnabledSubtypes.size() < 2 && mIsSystemLanguageSameAsInputLanguage) {
return FORMAT_TYPE_NONE; return FORMAT_TYPE_NONE;
} }
final String keyboardLanguage = SubtypeLocaleUtils.getSubtypeLocale(subtype).getLanguage(); final Locale[] locales = subtype.getLocales();
if (1 < locales.length) {
return FORMAT_TYPE_MULTIPLE;
}
final String keyboardLanguage = locales[0].getLanguage();
final String keyboardLayout = SubtypeLocaleUtils.getKeyboardLayoutSetName(subtype); final String keyboardLayout = SubtypeLocaleUtils.getKeyboardLayoutSetName(subtype);
int sameLanguageAndLayoutCount = 0; int sameLanguageAndLayoutCount = 0;
for (final InputMethodSubtype ims : mEnabledSubtypes) { for (final InputMethodSubtype ims : mEnabledSubtypes) {

View File

@ -416,33 +416,38 @@ public class DictionaryFacilitator {
} }
@UsedForTesting @UsedForTesting
public void resetDictionariesForTesting(final Context context, final Locale locale, public void resetDictionariesForTesting(final Context context, final Locale[] locales,
final ArrayList<String> dictionaryTypes, final HashMap<String, File> dictionaryFiles, final ArrayList<String> dictionaryTypes, final HashMap<String, File> dictionaryFiles,
final Map<String, Map<String, String>> additionalDictAttributes) { final Map<String, Map<String, String>> additionalDictAttributes) {
Dictionary mainDictionary = null; Dictionary mainDictionary = null;
final Map<String, ExpandableBinaryDictionary> subDicts = new HashMap<>(); final Map<String, ExpandableBinaryDictionary> subDicts = new HashMap<>();
for (final String dictType : dictionaryTypes) { final DictionaryGroup[] dictionaryGroups = new DictionaryGroup[locales.length];
if (dictType.equals(Dictionary.TYPE_MAIN)) { for (int i = 0; i < locales.length; ++i) {
mainDictionary = DictionaryFactory.createMainDictionaryFromManager(context, locale); final Locale locale = locales[i];
} else { for (final String dictType : dictionaryTypes) {
final File dictFile = dictionaryFiles.get(dictType); if (dictType.equals(Dictionary.TYPE_MAIN)) {
final ExpandableBinaryDictionary dict = getSubDict( mainDictionary = DictionaryFactory.createMainDictionaryFromManager(context,
dictType, context, locale, dictFile, "" /* dictNamePrefix */); locale);
if (additionalDictAttributes.containsKey(dictType)) { } else {
dict.clearAndFlushDictionaryWithAdditionalAttributes( final File dictFile = dictionaryFiles.get(dictType);
additionalDictAttributes.get(dictType)); final ExpandableBinaryDictionary dict = getSubDict(
dictType, context, locale, dictFile, "" /* dictNamePrefix */);
if (additionalDictAttributes.containsKey(dictType)) {
dict.clearAndFlushDictionaryWithAdditionalAttributes(
additionalDictAttributes.get(dictType));
}
if (dict == null) {
throw new RuntimeException("Unknown dictionary type: " + dictType);
}
dict.reloadDictionaryIfRequired();
dict.waitAllTasksForTests();
subDicts.put(dictType, dict);
} }
if (dict == null) {
throw new RuntimeException("Unknown dictionary type: " + dictType);
}
dict.reloadDictionaryIfRequired();
dict.waitAllTasksForTests();
subDicts.put(dictType, dict);
} }
dictionaryGroups[i] = new DictionaryGroup(locale, mainDictionary, subDicts);
} }
mDictionaryGroups = new DictionaryGroup[] { mDictionaryGroups = dictionaryGroups;
new DictionaryGroup(locale, mainDictionary, subDicts) };
} }
public void closeDictionaries() { public void closeDictionaries() {

View File

@ -102,7 +102,7 @@ import com.android.inputmethod.latin.utils.ViewLayoutUtils;
import java.io.FileDescriptor; import java.io.FileDescriptor;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -575,18 +575,19 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// Has to be package-visible for unit tests // Has to be package-visible for unit tests
@UsedForTesting @UsedForTesting
void loadSettings() { void loadSettings() {
final Locale locale = mSubtypeSwitcher.getCurrentSubtypeLocale(); final Locale[] locales = mSubtypeSwitcher.getCurrentSubtypeLocales();
final EditorInfo editorInfo = getCurrentInputEditorInfo(); final EditorInfo editorInfo = getCurrentInputEditorInfo();
final InputAttributes inputAttributes = new InputAttributes( final InputAttributes inputAttributes = new InputAttributes(
editorInfo, isFullscreenMode(), getPackageName()); editorInfo, isFullscreenMode(), getPackageName());
mSettings.loadSettings(this, locale, inputAttributes); // TODO: pass the array instead
mSettings.loadSettings(this, locales[0], inputAttributes);
final SettingsValues currentSettingsValues = mSettings.getCurrent(); final SettingsValues currentSettingsValues = mSettings.getCurrent();
AudioAndHapticFeedbackManager.getInstance().onSettingsChanged(currentSettingsValues); AudioAndHapticFeedbackManager.getInstance().onSettingsChanged(currentSettingsValues);
// This method is called on startup and language switch, before the new layout has // This method is called on startup and language switch, before the new layout has
// been displayed. Opening dictionaries never affects responsivity as dictionaries are // been displayed. Opening dictionaries never affects responsivity as dictionaries are
// asynchronously loaded. // asynchronously loaded.
if (!mHandler.hasPendingReopenDictionaries()) { if (!mHandler.hasPendingReopenDictionaries()) {
resetDictionaryFacilitatorForLocale(locale); resetDictionaryFacilitatorForLocale(locales);
} }
mDictionaryFacilitator.updateEnabledSubtypes(mRichImm.getMyEnabledInputMethodSubtypeList( mDictionaryFacilitator.updateEnabledSubtypes(mRichImm.getMyEnabledInputMethodSubtypeList(
true /* allowsImplicitlySelectedSubtypes */)); true /* allowsImplicitlySelectedSubtypes */));
@ -628,35 +629,34 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
} }
private void resetDictionaryFacilitatorIfNecessary() { private void resetDictionaryFacilitatorIfNecessary() {
final Locale switcherSubtypeLocale = mSubtypeSwitcher.getCurrentSubtypeLocale(); final Locale[] subtypeSwitcherLocales = mSubtypeSwitcher.getCurrentSubtypeLocales();
if (mDictionaryFacilitator.isForLocales(new Locale[] { switcherSubtypeLocale })) { if (mDictionaryFacilitator.isForLocales(subtypeSwitcherLocales)) {
return; return;
} }
final String switcherLocaleStr = switcherSubtypeLocale.toString(); final Locale[] subtypeLocales;
final Locale subtypeLocale; if (0 == subtypeSwitcherLocales.length) {
if (TextUtils.isEmpty(switcherLocaleStr)) {
// This happens in very rare corner cases - for example, immediately after a switch // This happens in very rare corner cases - for example, immediately after a switch
// to LatinIME has been requested, about a frame later another switch happens. In this // to LatinIME has been requested, about a frame later another switch happens. In this
// case, we are about to go down but we still don't know it, however the system tells // case, we are about to go down but we still don't know it, however the system tells
// us there is no current subtype so the locale is the empty string. Take the best // us there is no current subtype.
// possible guess instead -- it's bound to have no consequences, and we have no way
// of knowing anyway.
Log.e(TAG, "System is reporting no current subtype."); Log.e(TAG, "System is reporting no current subtype.");
subtypeLocale = getResources().getConfiguration().locale; subtypeLocales = new Locale[] { getResources().getConfiguration().locale };
} else { } else {
subtypeLocale = switcherSubtypeLocale; subtypeLocales = subtypeSwitcherLocales;
} }
resetDictionaryFacilitatorForLocale(subtypeLocale); resetDictionaryFacilitatorForLocale(subtypeLocales);
} }
/** /**
* Reset the facilitator by loading dictionaries for the locale and the current settings values. * Reset the facilitator by loading dictionaries for the locales and the current settings values
* *
* @param locale the locale * @param locales the locales
*/ */
// TODO: make sure the current settings always have the right locale, and read from them // TODO: make sure the current settings always have the right locales, and read from them
private void resetDictionaryFacilitatorForLocale(final Locale locale) { private void resetDictionaryFacilitatorForLocale(final Locale[] locales) {
final SettingsValues settingsValues = mSettings.getCurrent(); final SettingsValues settingsValues = mSettings.getCurrent();
// TODO: pass the array instead
final Locale locale = locales[0];
mDictionaryFacilitator.resetDictionaries(this /* context */, locale, mDictionaryFacilitator.resetDictionaries(this /* context */, locale,
settingsValues.mUseContactsDict, settingsValues.mUsePersonalizedDicts, settingsValues.mUseContactsDict, settingsValues.mUsePersonalizedDicts,
false /* forceReloadMainDictionary */, this); false /* forceReloadMainDictionary */, this);
@ -881,7 +881,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// Update to a gesture consumer with the current editor and IME state. // Update to a gesture consumer with the current editor and IME state.
mGestureConsumer = GestureConsumer.newInstance(editorInfo, mGestureConsumer = GestureConsumer.newInstance(editorInfo,
mInputLogic.getPrivateCommandPerformer(), mInputLogic.getPrivateCommandPerformer(),
Collections.singletonList(mSubtypeSwitcher.getCurrentSubtypeLocale()), Arrays.asList(mSubtypeSwitcher.getCurrentSubtypeLocales()),
switcher.getKeyboard()); switcher.getKeyboard());
// Forward this event to the accessibility utilities, if enabled. // Forward this event to the accessibility utilities, if enabled.
@ -1434,7 +1434,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
public void onStartBatchInput() { public void onStartBatchInput() {
mInputLogic.onStartBatchInput(mSettings.getCurrent(), mKeyboardSwitcher, mHandler); mInputLogic.onStartBatchInput(mSettings.getCurrent(), mKeyboardSwitcher, mHandler);
mGestureConsumer.onGestureStarted( mGestureConsumer.onGestureStarted(
Collections.singletonList(mSubtypeSwitcher.getCurrentSubtypeLocale()), Arrays.asList(mSubtypeSwitcher.getCurrentSubtypeLocales()),
mKeyboardSwitcher.getKeyboard()); mKeyboardSwitcher.getKeyboard());
} }
@ -1558,7 +1558,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// We should clear the contextual strip if there is no suggestion from dictionaries. // We should clear the contextual strip if there is no suggestion from dictionaries.
|| noSuggestionsFromDictionaries) { || noSuggestionsFromDictionaries) {
mSuggestionStripView.setSuggestions(suggestedWords, mSuggestionStripView.setSuggestions(suggestedWords,
SubtypeLocaleUtils.isRtlLanguage(mSubtypeSwitcher.getCurrentSubtype())); mSubtypeSwitcher.getCurrentSubtype().isRtlSubtype());
} }
} }

View File

@ -114,10 +114,13 @@ public final class RichInputMethodSubtype {
return "Multi-lingual subtype: " + mSubtype.toString() + ", " + Arrays.toString(mLocales); return "Multi-lingual subtype: " + mSubtype.toString() + ", " + Arrays.toString(mLocales);
} }
// TODO: remove this method! We can always have several locales. Multi-lingual input will only public Locale[] getLocales() {
// be done when this method is gone. return mLocales;
public String getLocale() { }
return mSubtype.getLocale();
public boolean isRtlSubtype() {
// The subtype is considered RTL if the language of the main subtype is RTL.
return SubtypeLocaleUtils.isRtlLanguage(mLocales[0]);
} }
// TODO: remove this method // TODO: remove this method

View File

@ -170,15 +170,21 @@ public final class SubtypeSwitcher {
Log.w(TAG, "onSubtypeChanged: " + newSubtype.getNameForLogging()); Log.w(TAG, "onSubtypeChanged: " + newSubtype.getNameForLogging());
} }
final Locale newLocale = SubtypeLocaleUtils.getSubtypeLocale(newSubtype); final Locale[] newLocales = newSubtype.getLocales();
final Locale systemLocale = mResources.getConfiguration().locale; if (newLocales.length > 1) {
final boolean sameLocale = systemLocale.equals(newLocale); // In multi-locales mode, the system language is never the same as the input language
final boolean sameLanguage = systemLocale.getLanguage().equals(newLocale.getLanguage()); // because there is no single input language.
final boolean implicitlyEnabled = mRichImm mLanguageOnSpacebarHelper.updateIsSystemLanguageSameAsInputLanguage(false);
.checkIfSubtypeBelongsToThisImeAndImplicitlyEnabled(newSubtype.getRawSubtype()); } else {
mLanguageOnSpacebarHelper.updateIsSystemLanguageSameAsInputLanguage( final Locale newLocale = newLocales[0];
sameLocale || (sameLanguage && implicitlyEnabled)); final Locale systemLocale = mResources.getConfiguration().locale;
final boolean sameLocale = systemLocale.equals(newLocale);
final boolean sameLanguage = systemLocale.getLanguage().equals(newLocale.getLanguage());
final boolean implicitlyEnabled = mRichImm
.checkIfSubtypeBelongsToThisImeAndImplicitlyEnabled(newSubtype.getRawSubtype());
mLanguageOnSpacebarHelper.updateIsSystemLanguageSameAsInputLanguage(
sameLocale || (sameLanguage && implicitlyEnabled));
}
updateShortcutIME(); updateShortcutIME();
} }
@ -284,11 +290,11 @@ public final class SubtypeSwitcher {
sForcedSubtypeForTesting = new RichInputMethodSubtype(subtype); sForcedSubtypeForTesting = new RichInputMethodSubtype(subtype);
} }
public Locale getCurrentSubtypeLocale() { public Locale[] getCurrentSubtypeLocales() {
if (null != sForcedSubtypeForTesting) { if (null != sForcedSubtypeForTesting) {
return LocaleUtils.constructLocaleFromString(sForcedSubtypeForTesting.getLocale()); return sForcedSubtypeForTesting.getLocales();
} }
return SubtypeLocaleUtils.getSubtypeLocale(getCurrentSubtype()); return getCurrentSubtype().getLocales();
} }
public RichInputMethodSubtype getCurrentSubtype() { public RichInputMethodSubtype getCurrentSubtype() {

View File

@ -293,13 +293,6 @@ public final class SubtypeLocaleUtils {
return LocaleUtils.constructLocaleFromString(localeString); return LocaleUtils.constructLocaleFromString(localeString);
} }
// TODO: remove this. When RichInputMethodSubtype#getLocale is removed we can do away with this
// method at the same time.
public static Locale getSubtypeLocale(final RichInputMethodSubtype subtype) {
final String localeString = subtype.getLocale();
return LocaleUtils.constructLocaleFromString(localeString);
}
public static String getKeyboardLayoutSetDisplayName(final InputMethodSubtype subtype) { public static String getKeyboardLayoutSetDisplayName(final InputMethodSubtype subtype) {
final String layoutName = getKeyboardLayoutSetName(subtype); final String layoutName = getKeyboardLayoutSetName(subtype);
return getKeyboardLayoutSetDisplayName(layoutName); return getKeyboardLayoutSetDisplayName(layoutName);
@ -348,10 +341,6 @@ public final class SubtypeLocaleUtils {
return Arrays.binarySearch(SORTED_RTL_LANGUAGES, language) >= 0; return Arrays.binarySearch(SORTED_RTL_LANGUAGES, language) >= 0;
} }
public static boolean isRtlLanguage(final RichInputMethodSubtype subtype) {
return isRtlLanguage(getSubtypeLocale(subtype));
}
public static String getCombiningRulesExtraValue(final InputMethodSubtype subtype) { public static String getCombiningRulesExtraValue(final InputMethodSubtype subtype) {
return subtype.getExtraValueOf(Constants.Subtype.ExtraValue.COMBINING_RULES); return subtype.getExtraValueOf(Constants.Subtype.ExtraValue.COMBINING_RULES);
} }

View File

@ -42,8 +42,9 @@ public class ContextualDictionaryTests extends AndroidTestCase {
final ArrayList<String> dictTypes = new ArrayList<>(); final ArrayList<String> dictTypes = new ArrayList<>();
dictTypes.add(Dictionary.TYPE_CONTEXTUAL); dictTypes.add(Dictionary.TYPE_CONTEXTUAL);
final DictionaryFacilitator dictionaryFacilitator = new DictionaryFacilitator(); final DictionaryFacilitator dictionaryFacilitator = new DictionaryFacilitator();
dictionaryFacilitator.resetDictionariesForTesting(getContext(), LOCALE_EN_US, dictTypes, dictionaryFacilitator.resetDictionariesForTesting(getContext(),
new HashMap<String, File>(), new HashMap<String, Map<String, String>>()); new Locale[] { LOCALE_EN_US }, dictTypes, new HashMap<String, File>(),
new HashMap<String, Map<String, String>>());
return dictionaryFacilitator; return dictionaryFacilitator;
} }

View File

@ -55,8 +55,9 @@ public class PersonalizationDictionaryTests extends AndroidTestCase {
dictTypes.add(Dictionary.TYPE_MAIN); dictTypes.add(Dictionary.TYPE_MAIN);
dictTypes.add(Dictionary.TYPE_PERSONALIZATION); dictTypes.add(Dictionary.TYPE_PERSONALIZATION);
final DictionaryFacilitator dictionaryFacilitator = new DictionaryFacilitator(getContext()); final DictionaryFacilitator dictionaryFacilitator = new DictionaryFacilitator(getContext());
dictionaryFacilitator.resetDictionariesForTesting(getContext(), LOCALE_EN_US, dictTypes, dictionaryFacilitator.resetDictionariesForTesting(getContext(),
new HashMap<String, File>(), new HashMap<String, Map<String, String>>()); new Locale[] { LOCALE_EN_US }, dictTypes, new HashMap<String, File>(),
new HashMap<String, Map<String, String>>());
// Set subtypes. // Set subtypes.
RichInputMethodManager.init(getContext()); RichInputMethodManager.init(getContext());
final RichInputMethodManager richImm = RichInputMethodManager.getInstance(); final RichInputMethodManager richImm = RichInputMethodManager.getInstance();

View File

@ -119,12 +119,17 @@ public class SpacebarLanguageUtilsTests extends AndroidTestCase {
final String subtypeName = SubtypeLocaleUtils final String subtypeName = SubtypeLocaleUtils
.getSubtypeDisplayNameInSystemLocale(subtype.getRawSubtype()); .getSubtypeDisplayNameInSystemLocale(subtype.getRawSubtype());
final String spacebarText = subtype.getFullDisplayName(); final String spacebarText = subtype.getFullDisplayName();
final String languageName = SubtypeLocaleUtils final Locale[] locales = subtype.getLocales();
.getSubtypeLocaleDisplayName(subtype.getLocale()); if (1 == locales.length) {
if (subtype.isNoLanguage()) { final String languageName = SubtypeLocaleUtils
assertFalse(subtypeName, spacebarText.contains(languageName)); .getSubtypeLocaleDisplayName(locales[0].toString());
if (subtype.isNoLanguage()) {
assertFalse(subtypeName, spacebarText.contains(languageName));
} else {
assertTrue(subtypeName, spacebarText.contains(languageName));
}
} else { } else {
assertTrue(subtypeName, spacebarText.contains(languageName)); // TODO: test multi-lingual subtype spacebar display
} }
} }
} }
@ -133,8 +138,14 @@ public class SpacebarLanguageUtilsTests extends AndroidTestCase {
for (final RichInputMethodSubtype subtype : mSubtypesList) { for (final RichInputMethodSubtype subtype : mSubtypesList) {
final String subtypeName = SubtypeLocaleUtils final String subtypeName = SubtypeLocaleUtils
.getSubtypeDisplayNameInSystemLocale(subtype.getRawSubtype()); .getSubtypeDisplayNameInSystemLocale(subtype.getRawSubtype());
final Locale[] locales = subtype.getLocales();
if (locales.length > 1) {
// TODO: test multi-lingual subtype spacebar display
continue;
}
final Locale locale = locales[0];
if (SubtypeLocaleUtils.sExceptionalLocaleDisplayedInRootLocale.contains( if (SubtypeLocaleUtils.sExceptionalLocaleDisplayedInRootLocale.contains(
subtype.getLocale())) { locale.toString())) {
// Skip test because the language part of this locale string doesn't represent // Skip test because the language part of this locale string doesn't represent
// the locale to be displayed on the spacebar (for example hi_ZZ and Hinglish). // the locale to be displayed on the spacebar (for example hi_ZZ and Hinglish).
continue; continue;
@ -144,7 +155,6 @@ public class SpacebarLanguageUtilsTests extends AndroidTestCase {
assertEquals(subtypeName, SubtypeLocaleUtils.getKeyboardLayoutSetDisplayName( assertEquals(subtypeName, SubtypeLocaleUtils.getKeyboardLayoutSetDisplayName(
subtype.getRawSubtype()), spacebarText); subtype.getRawSubtype()), spacebarText);
} else { } else {
final Locale locale = SubtypeLocaleUtils.getSubtypeLocale(subtype);
assertEquals(subtypeName, assertEquals(subtypeName,
SubtypeLocaleUtils.getSubtypeLocaleDisplayName(locale.getLanguage()), SubtypeLocaleUtils.getSubtypeLocaleDisplayName(locale.getLanguage()),
spacebarText); spacebarText);

View File

@ -111,14 +111,19 @@ public class SubtypeLocaleUtilsTests extends AndroidTestCase {
for (final RichInputMethodSubtype subtype : mSubtypesList) { for (final RichInputMethodSubtype subtype : mSubtypesList) {
final String subtypeName = SubtypeLocaleUtils final String subtypeName = SubtypeLocaleUtils
.getSubtypeDisplayNameInSystemLocale(subtype.getRawSubtype()); .getSubtypeDisplayNameInSystemLocale(subtype.getRawSubtype());
if (subtype.isNoLanguage()) { final Locale[] locales = subtype.getLocales();
final String layoutName = SubtypeLocaleUtils if (1 == locales.length) {
.getKeyboardLayoutSetDisplayName(subtype.getRawSubtype()); if (subtype.isNoLanguage()) {
assertTrue(subtypeName, subtypeName.contains(layoutName)); final String layoutName = SubtypeLocaleUtils
.getKeyboardLayoutSetDisplayName(subtype.getRawSubtype());
assertTrue(subtypeName, subtypeName.contains(layoutName));
} else {
final String languageName = SubtypeLocaleUtils
.getSubtypeLocaleDisplayNameInSystemLocale(locales[0].toString());
assertTrue(subtypeName, subtypeName.contains(languageName));
}
} else { } else {
final String languageName = SubtypeLocaleUtils // TODO: test multi-lingual subtype spacebar display
.getSubtypeLocaleDisplayNameInSystemLocale(subtype.getLocale());
assertTrue(subtypeName, subtypeName.contains(languageName));
} }
} }
} }
@ -315,9 +320,9 @@ public class SubtypeLocaleUtilsTests extends AndroidTestCase {
.getSubtypeDisplayNameInSystemLocale(rawSubtype); .getSubtypeDisplayNameInSystemLocale(rawSubtype);
if (rawSubtype.equals(ARABIC) || rawSubtype.equals(FARSI) if (rawSubtype.equals(ARABIC) || rawSubtype.equals(FARSI)
|| rawSubtype.equals(HEBREW)) { || rawSubtype.equals(HEBREW)) {
assertTrue(subtypeName, SubtypeLocaleUtils.isRtlLanguage(subtype)); assertTrue(subtypeName, subtype.isRtlSubtype());
} else { } else {
assertFalse(subtypeName, SubtypeLocaleUtils.isRtlLanguage(subtype)); assertFalse(subtypeName, subtype.isRtlSubtype());
} }
} }
} }