diff options
Diffstat (limited to 'java/src/com/android/inputmethod/latin')
18 files changed, 432 insertions, 212 deletions
diff --git a/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java index a787ef153..d626ff926 100644 --- a/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java @@ -29,7 +29,6 @@ import android.provider.ContactsContract.Contacts; import android.text.TextUtils; import android.util.Log; -import com.android.inputmethod.annotations.UsedForTesting; import com.android.inputmethod.latin.personalization.AccountUtils; import com.android.inputmethod.latin.utils.StringUtils; @@ -73,8 +72,13 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary { private final boolean mUseFirstLastBigrams; public ContactsBinaryDictionary(final Context context, final Locale locale) { - super(context, getDictNameWithLocale(NAME, locale), locale, - Dictionary.TYPE_CONTACTS, false /* isUpdatable */); + this(context, locale, null /* dictFile */); + } + + public ContactsBinaryDictionary(final Context context, final Locale locale, + final File dictFile) { + super(context, getDictName(NAME, locale, dictFile), locale, Dictionary.TYPE_CONTACTS, + false /* isUpdatable */, dictFile); mLocale = locale; mUseFirstLastBigrams = useFirstLastBigramsForLocale(locale); registerObserver(context); @@ -84,12 +88,6 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary { loadDictionary(); } - // Dummy constructor for tests. - @UsedForTesting - public ContactsBinaryDictionary(final Context context, final Locale locale, final File file) { - this(context, locale); - } - private synchronized void registerObserver(final Context context) { // Perform a managed query. The Activity will handle closing and requerying the cursor // when needed. diff --git a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java index c2451ce8d..3b9be4395 100644 --- a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java @@ -122,7 +122,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { new DictionaryUpdateController(); /* A extension for a binary dictionary file. */ - public static final String DICT_FILE_EXTENSION = ".dict"; + protected static final String DICT_FILE_EXTENSION = ".dict"; private final AtomicReference<Runnable> mUnfinishedFlushingTask = new AtomicReference<Runnable>(); @@ -148,10 +148,6 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { return mBinaryDictionary.isValidDictionary(); } - private File getDictFile() { - return mDictFile; - } - /** * Gets the dictionary update controller for the given dictionary name. */ @@ -213,15 +209,10 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { * @param dictType the dictionary type, as a human-readable string * @param isUpdatable whether to support dynamically updating the dictionary. Please note that * dynamic dictionary has negative effects on memory space and computation time. + * @param dictFile dictionary file path. if null, use default dictionary path based on + * dictionary type. */ public ExpandableBinaryDictionary(final Context context, final String dictName, - final Locale locale, final String dictType, final boolean isUpdatable) { - this(context, dictName, locale, dictType, isUpdatable, - new File(context.getFilesDir(), dictName + DICT_FILE_EXTENSION)); - } - - // Creates an instance that uses a given dictionary file. - public ExpandableBinaryDictionary(final Context context, final String dictName, final Locale locale, final String dictType, final boolean isUpdatable, final File dictFile) { super(dictType); @@ -229,15 +220,22 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { mContext = context; mLocale = locale; mIsUpdatable = isUpdatable; - mDictFile = dictFile; + mDictFile = getDictFile(context, dictName, dictFile); mBinaryDictionary = null; mDictNameDictionaryUpdateController = getDictionaryUpdateController(dictName); // Currently, only dynamic personalization dictionary is updatable. mDictionaryWriter = getDictionaryWriter(isUpdatable); } - protected static String getDictNameWithLocale(final String name, final Locale locale) { - return name + "." + locale.toString(); + public static File getDictFile(final Context context, final String dictName, + final File dictFile) { + return (dictFile != null) ? dictFile + : new File(context.getFilesDir(), dictName + DICT_FILE_EXTENSION); + } + + public static String getDictName(final String name, final Locale locale, + final File dictFile) { + return dictFile != null ? dictFile.getName() : name + "." + locale.toString(); } /** @@ -279,6 +277,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { } protected void clear() { + final File dictFile = mDictFile; getExecutor(mDictName).execute(new Runnable() { @Override public void run() { @@ -286,14 +285,13 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { if (mBinaryDictionary != null) { mBinaryDictionary.close(); } - final File file = getDictFile(); - if (file.exists() && !FileUtils.deleteRecursively(file)) { - Log.e(TAG, "Can't remove a file: " + file.getName()); + if (dictFile.exists() && !FileUtils.deleteRecursively(dictFile)) { + Log.e(TAG, "Can't remove a file: " + dictFile.getName()); } - BinaryDictionary.createEmptyDictFile(file.getAbsolutePath(), + BinaryDictionary.createEmptyDictFile(dictFile.getAbsolutePath(), DICTIONARY_FORMAT_VERSION, mLocale, getHeaderAttributeMap()); mBinaryDictionary = new BinaryDictionary( - file.getAbsolutePath(), 0 /* offset */, file.length(), + dictFile.getAbsolutePath(), 0 /* offset */, dictFile.length(), true /* useFullEditDistance */, mLocale, mDictType, mIsUpdatable); } else { mDictionaryWriter.clear(); @@ -544,9 +542,8 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { } } - final File file = getDictFile(); - final String filename = file.getAbsolutePath(); - final long length = file.length(); + final String filename = mDictFile.getAbsolutePath(); + final long length = mDictFile.length(); // Build the new binary dictionary final BinaryDictionary newBinaryDictionary = new BinaryDictionary(filename, 0 /* offset */, @@ -585,17 +582,16 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { if (needsToReloadBeforeWriting()) { mDictionaryWriter.clear(); loadDictionaryAsync(); - mDictionaryWriter.write(getDictFile(), getHeaderAttributeMap()); + mDictionaryWriter.write(mDictFile, getHeaderAttributeMap()); } else { if (mBinaryDictionary == null || !isValidDictionary() // TODO: remove the check below || !matchesExpectedBinaryDictFormatVersionForThisType( mBinaryDictionary.getFormatVersion())) { - final File file = getDictFile(); - if (file.exists() && !FileUtils.deleteRecursively(file)) { - Log.e(TAG, "Can't remove a file: " + file.getName()); + if (mDictFile.exists() && !FileUtils.deleteRecursively(mDictFile)) { + Log.e(TAG, "Can't remove a file: " + mDictFile.getName()); } - BinaryDictionary.createEmptyDictFile(file.getAbsolutePath(), + BinaryDictionary.createEmptyDictFile(mDictFile.getAbsolutePath(), DICTIONARY_FORMAT_VERSION, mLocale, getHeaderAttributeMap()); } else { if (mBinaryDictionary.needsToRunGC(false /* mindsBlockByGC */)) { @@ -719,7 +715,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { // TODO: cache the file's existence so that we avoid doing a disk access each time. private boolean dictionaryFileExists() { - return getDictFile().exists(); + return mDictFile.exists(); } /** diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 432b8a5a9..d1125afcc 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -1001,7 +1001,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen applicationSuggestedWords, null /* rawSuggestions */, false /* typedWordValid */, false /* willAutoCorrect */, - false /* isPunctuationSuggestions */, false /* isObsoleteSuggestions */, false /* isPrediction */); // When in fullscreen mode, show completions generated by the application @@ -1185,7 +1184,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen new AlertDialog.Builder(context, AlertDialog.THEME_HOLO_DARK); builder.setMessage(R.string.important_notice_contents) .setPositiveButton(android.R.string.ok, listener); - showOptionDialog(builder.create(), false /* cancelable */); + showOptionDialog(builder.create(), true /* cancelable */); } public void displaySettingsDialog() { @@ -1320,6 +1319,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen return false; if (mSuggestionStripView.isShowingAddToDictionaryHint()) return true; + if (ImportantNoticeUtils.hasNewImportantNoticeAndNotInSetupWizard(this)) + return true; if (null == currentSettings) return false; if (!currentSettings.isSuggestionStripVisible()) @@ -1352,7 +1353,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen if (mSuggestionStripView != null) { final boolean showSuggestions; if (SuggestedWords.EMPTY == suggestedWords - || suggestedWords.mIsPunctuationSuggestions) { + || suggestedWords.isPunctuationSuggestions() + || !mSettings.getCurrent().isSuggestionsRequested()) { showSuggestions = !mSuggestionStripView.maybeShowImportantNoticeTitle(); } else { showSuggestions = true; @@ -1430,7 +1432,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen return new SuggestedWords(typedWordAndPreviousSuggestions, null /* rawSuggestions */, false /* typedWordValid */, false /* hasAutoCorrectionCandidate */, - false /* isPunctuationSuggestions */, true /* isObsoleteSuggestions */, false /* isPrediction */); } @@ -1731,13 +1732,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen final int keyboardMode = keyboard != null ? keyboard.mId.mMode : -1; p.println(" Keyboard mode = " + keyboardMode); final SettingsValues settingsValues = mSettings.getCurrent(); - p.println(" mIsSuggestionsRequested = " + settingsValues.isSuggestionsRequested()); - p.println(" mCorrectionEnabled=" + settingsValues.mCorrectionEnabled); - p.println(" isComposingWord=" + mInputLogic.mWordComposer.isComposingWord()); - p.println(" mSoundOn=" + settingsValues.mSoundOn); - p.println(" mVibrateOn=" + settingsValues.mVibrateOn); - p.println(" mKeyPreviewPopupOn=" + settingsValues.mKeyPreviewPopupOn); - p.println(" inputAttributes=" + settingsValues.mInputAttributes); + p.println(settingsValues.dump()); // TODO: Dump all settings values } } diff --git a/java/src/com/android/inputmethod/latin/PunctuationSuggestions.java b/java/src/com/android/inputmethod/latin/PunctuationSuggestions.java new file mode 100644 index 000000000..4911bcdf6 --- /dev/null +++ b/java/src/com/android/inputmethod/latin/PunctuationSuggestions.java @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.inputmethod.latin; + +import com.android.inputmethod.keyboard.internal.KeySpecParser; +import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; +import com.android.inputmethod.latin.utils.CollectionUtils; +import com.android.inputmethod.latin.utils.StringUtils; + +import java.util.ArrayList; +import java.util.Arrays; + +/** + * The extended {@link SuggestedWords} class to represent punctuation suggestions. + * + * Each punctuation specification string is the key specification that can be parsed by + * {@link KeySpecParser}. + */ +public final class PunctuationSuggestions extends SuggestedWords { + private PunctuationSuggestions(final ArrayList<SuggestedWordInfo> punctuationsList) { + super(punctuationsList, + null /* rawSuggestions */, + false /* typedWordValid */, + false /* hasAutoCorrectionCandidate */, + false /* isObsoleteSuggestions */, + false /* isPrediction */); + } + + /** + * Create new instance of {@link PunctuationSuggestions} from the array of punctuation key + * specifications. + * + * @param punctuationSpecs The array of punctuation key specifications. + * @return The {@link PunctuationSuggestions} object. + */ + public static PunctuationSuggestions newPunctuationSuggestions( + final String[] punctuationSpecs) { + final ArrayList<SuggestedWordInfo> puncuationsList = CollectionUtils.newArrayList(); + for (final String puncSpec : punctuationSpecs) { + puncuationsList.add(newHardCodedWordInfo(puncSpec)); + } + return new PunctuationSuggestions(puncuationsList); + } + + /** + * {@inheritDoc} + * Note that {@link super#getWord(int)} returns a punctuation key specification text. + * The suggested punctuation should be gotten by parsing the key specification. + */ + @Override + public String getWord(final int index) { + final String keySpec = super.getWord(index); + final int code = KeySpecParser.getCode(keySpec); + return (code == Constants.CODE_OUTPUT_TEXT) + ? KeySpecParser.getOutputText(keySpec) + : StringUtils.newSingleCodePointString(code); + } + + /** + * {@inheritDoc} + * Note that {@link super#getWord(int)} returns a punctuation key specification text. + * The displayed text should be gotten by parsing the key specification. + */ + @Override + public String getLabel(final int index) { + final String keySpec = super.getWord(index); + return KeySpecParser.getLabel(keySpec); + } + + /** + * {@inheritDoc} + * Note that {@link #getWord(int)} returns a suggested punctuation. We should create a + * {@link SuggestedWordInfo} object that represents a hard coded word. + */ + @Override + public SuggestedWordInfo getInfo(final int index) { + return newHardCodedWordInfo(getWord(index)); + } + + /** + * The predicator to tell whether this object represents punctuation suggestions. + * @return true if this object represents punctuation suggestions. + */ + @Override + public boolean isPunctuationSuggestions() { + return true; + } + + @Override + public String toString() { + return "PunctuationSuggestions: " + + " words=" + Arrays.toString(mSuggestedWordInfoList.toArray()); + } + + private static SuggestedWordInfo newHardCodedWordInfo(final String keySpec) { + return new SuggestedWordInfo(keySpec, SuggestedWordInfo.MAX_SCORE, + SuggestedWordInfo.KIND_HARDCODED, + Dictionary.DICTIONARY_HARDCODED, + SuggestedWordInfo.NOT_AN_INDEX /* indexOfTouchPointOfSecondWord */, + SuggestedWordInfo.NOT_A_CONFIDENCE /* autoCommitFirstWordConfidence */); + } +} diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java index 5e74d75b0..abf831a28 100644 --- a/java/src/com/android/inputmethod/latin/Suggest.java +++ b/java/src/com/android/inputmethod/latin/Suggest.java @@ -227,7 +227,6 @@ public final class Suggest { // rename the attribute or change the value. !allowsToBeAutoCorrected /* typedWordValid */, hasAutoCorrection, /* willAutoCorrect */ - false /* isPunctuationSuggestions */, false /* isObsoleteSuggestions */, !wordComposer.isComposingWord() /* isPrediction */, sequenceNumber)); } @@ -289,7 +288,6 @@ public final class Suggest { callback.onGetSuggestedWords(new SuggestedWords(suggestionsContainer, rawSuggestions, true /* typedWordValid */, false /* willAutoCorrect */, - false /* isPunctuationSuggestions */, false /* isObsoleteSuggestions */, false /* isPrediction */, sequenceNumber)); } diff --git a/java/src/com/android/inputmethod/latin/SuggestedWords.java b/java/src/com/android/inputmethod/latin/SuggestedWords.java index b2efc4a86..46df3e88c 100644 --- a/java/src/com/android/inputmethod/latin/SuggestedWords.java +++ b/java/src/com/android/inputmethod/latin/SuggestedWords.java @@ -26,7 +26,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; -public final class SuggestedWords { +public class SuggestedWords { public static final int INDEX_OF_TYPED_WORD = 0; public static final int INDEX_OF_AUTO_CORRECTION = 1; public static final int NOT_A_SEQUENCE_NUMBER = -1; @@ -37,7 +37,7 @@ public final class SuggestedWords { private static final ArrayList<SuggestedWordInfo> EMPTY_WORD_INFO_LIST = CollectionUtils.newArrayList(0); public static final SuggestedWords EMPTY = new SuggestedWords( - EMPTY_WORD_INFO_LIST, null /* rawSuggestions */, false, false, false, false, false); + EMPTY_WORD_INFO_LIST, null /* rawSuggestions */, false, false, false, false); public final String mTypedWord; public final boolean mTypedWordValid; @@ -45,38 +45,34 @@ public final class SuggestedWords { // of what this flag means would be "the top suggestion is strong enough to auto-correct", // whether this exactly matches the user entry or not. public final boolean mWillAutoCorrect; - public final boolean mIsPunctuationSuggestions; public final boolean mIsObsoleteSuggestions; public final boolean mIsPrediction; public final int mSequenceNumber; // Sequence number for auto-commit. - private final ArrayList<SuggestedWordInfo> mSuggestedWordInfoList; + protected final ArrayList<SuggestedWordInfo> mSuggestedWordInfoList; public final ArrayList<SuggestedWordInfo> mRawSuggestions; public SuggestedWords(final ArrayList<SuggestedWordInfo> suggestedWordInfoList, final ArrayList<SuggestedWordInfo> rawSuggestions, final boolean typedWordValid, final boolean willAutoCorrect, - final boolean isPunctuationSuggestions, final boolean isObsoleteSuggestions, final boolean isPrediction) { this(suggestedWordInfoList, rawSuggestions, typedWordValid, willAutoCorrect, - isPunctuationSuggestions, isObsoleteSuggestions, isPrediction, - NOT_A_SEQUENCE_NUMBER); + isObsoleteSuggestions, isPrediction, NOT_A_SEQUENCE_NUMBER); } public SuggestedWords(final ArrayList<SuggestedWordInfo> suggestedWordInfoList, final ArrayList<SuggestedWordInfo> rawSuggestions, final boolean typedWordValid, final boolean willAutoCorrect, - final boolean isPunctuationSuggestions, final boolean isObsoleteSuggestions, final boolean isPrediction, final int sequenceNumber) { this(suggestedWordInfoList, rawSuggestions, suggestedWordInfoList.isEmpty() ? null : suggestedWordInfoList.get(INDEX_OF_TYPED_WORD).mWord, - typedWordValid, willAutoCorrect, isPunctuationSuggestions, - isObsoleteSuggestions, isPrediction, sequenceNumber); + typedWordValid, willAutoCorrect, isObsoleteSuggestions, isPrediction, + sequenceNumber); } public SuggestedWords(final ArrayList<SuggestedWordInfo> suggestedWordInfoList, @@ -84,7 +80,6 @@ public final class SuggestedWords { final String typedWord, final boolean typedWordValid, final boolean willAutoCorrect, - final boolean isPunctuationSuggestions, final boolean isObsoleteSuggestions, final boolean isPrediction, final int sequenceNumber) { @@ -92,7 +87,6 @@ public final class SuggestedWords { mRawSuggestions = rawSuggestions; mTypedWordValid = typedWordValid; mWillAutoCorrect = willAutoCorrect; - mIsPunctuationSuggestions = isPunctuationSuggestions; mIsObsoleteSuggestions = isObsoleteSuggestions; mIsPrediction = isPrediction; mSequenceNumber = sequenceNumber; @@ -107,10 +101,32 @@ public final class SuggestedWords { return mSuggestedWordInfoList.size(); } + /** + * Get suggested word at <code>index</code>. + * @param index The index of the suggested word. + * @return The suggested word. + */ public String getWord(final int index) { return mSuggestedWordInfoList.get(index).mWord; } + /** + * Get displayed text at <code>index</code>. + * In RTL languages, the displayed text on the suggestion strip may be different from the + * suggested word that is returned from {@link #getWord(int)}. For example the displayed text + * of punctuation suggestion "(" should be ")". + * @param index The index of the text to display. + * @return The text to be displayed. + */ + public String getLabel(final int index) { + return mSuggestedWordInfoList.get(index).mWord; + } + + /** + * Get {@link SuggestedWordInfo} object at <code>index</code>. + * @param index The index of the {@link SuggestedWordInfo}. + * @return The {@link SuggestedWordInfo} object. + */ public SuggestedWordInfo getInfo(final int index) { return mSuggestedWordInfoList.get(index); } @@ -130,13 +146,20 @@ public final class SuggestedWords { return debugString; } + /** + * The predicator to tell whether this object represents punctuation suggestions. + * @return false if this object desn't represent punctuation suggestions. + */ + public boolean isPunctuationSuggestions() { + return false; + } + @Override public String toString() { // Pretty-print method to help debug return "SuggestedWords:" + " mTypedWordValid=" + mTypedWordValid + " mWillAutoCorrect=" + mWillAutoCorrect - + " mIsPunctuationSuggestions=" + mIsPunctuationSuggestions + " words=" + Arrays.toString(mSuggestedWordInfoList.toArray()); } @@ -313,8 +336,8 @@ public final class SuggestedWords { // We should never autocorrect, so we say the typed word is valid. Also, in this case, // no auto-correction should take place hence willAutoCorrect = false. return new SuggestedWords(newSuggestions, null /* rawSuggestions */, typedWord, - true /* typedWordValid */, false /* willAutoCorrect */, mIsPunctuationSuggestions, - mIsObsoleteSuggestions, mIsPrediction, NOT_A_SEQUENCE_NUMBER); + true /* typedWordValid */, false /* willAutoCorrect */, mIsObsoleteSuggestions, + mIsPrediction, NOT_A_SEQUENCE_NUMBER); } // Creates a new SuggestedWordInfo from the currently suggested words that removes all but the @@ -333,7 +356,6 @@ public final class SuggestedWords { SuggestedWordInfo.NOT_A_CONFIDENCE)); } return new SuggestedWords(newSuggestions, null /* rawSuggestions */, mTypedWordValid, - mWillAutoCorrect, mIsPunctuationSuggestions, mIsObsoleteSuggestions, - mIsPrediction); + mWillAutoCorrect, mIsObsoleteSuggestions, mIsPrediction); } } diff --git a/java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserBinaryDictionary.java b/java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserBinaryDictionary.java index 9ccd9e4e8..801fb5b89 100644 --- a/java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserBinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/SynchronouslyLoadedUserBinaryDictionary.java @@ -28,12 +28,12 @@ public final class SynchronouslyLoadedUserBinaryDictionary extends UserBinaryDic private final Object mLock = new Object(); public SynchronouslyLoadedUserBinaryDictionary(final Context context, final Locale locale) { - this(context, locale, false); + this(context, locale, false /* alsoUseMoreRestrictiveLocales */); } public SynchronouslyLoadedUserBinaryDictionary(final Context context, final Locale locale, final boolean alsoUseMoreRestrictiveLocales) { - super(context, locale, alsoUseMoreRestrictiveLocales); + super(context, locale, alsoUseMoreRestrictiveLocales, null /* dictFile */); } @Override diff --git a/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java b/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java index 8011247c6..2a195f58b 100644 --- a/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java @@ -28,7 +28,6 @@ import android.provider.UserDictionary.Words; import android.text.TextUtils; import android.util.Log; -import com.android.inputmethod.annotations.UsedForTesting; import com.android.inputmethod.compat.UserDictionaryCompatUtils; import com.android.inputmethod.latin.utils.LocaleUtils; import com.android.inputmethod.latin.utils.SubtypeLocaleUtils; @@ -78,19 +77,17 @@ public class UserBinaryDictionary extends ExpandableBinaryDictionary { final public boolean mEnabled; public UserBinaryDictionary(final Context context, final Locale locale) { - this(context, locale, false); + this(context, locale, false /* alsoUseMoreRestrictiveLocales */, null /* dictFile */); } - // Dummy constructor for tests. - @UsedForTesting - public UserBinaryDictionary(final Context context, final Locale locale, final File file) { - this(context, locale); + public UserBinaryDictionary(final Context context, final Locale locale, final File dictFile) { + this(context, locale, false /* alsoUseMoreRestrictiveLocales */, dictFile); } public UserBinaryDictionary(final Context context, final Locale locale, - final boolean alsoUseMoreRestrictiveLocales) { - super(context, getDictNameWithLocale(NAME, locale), locale, Dictionary.TYPE_USER, - false /* isUpdatable */); + final boolean alsoUseMoreRestrictiveLocales, final File dictFile) { + super(context, getDictName(NAME, locale, dictFile), locale, Dictionary.TYPE_USER, + false /* isUpdatable */, dictFile); if (null == locale) throw new NullPointerException(); // Catch the error earlier final String localeStr = locale.toString(); if (SubtypeLocaleUtils.NO_LANGUAGE.equals(localeStr)) { diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java index 6e9050593..6f73859e8 100644 --- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java +++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java @@ -973,7 +973,13 @@ public final class InputLogic { } else { final int codePointBeforeCursor = mConnection.getCodePointBeforeCursor(); if (codePointBeforeCursor == Constants.NOT_A_CODE) { - // Nothing to delete before the cursor. + // HACK for backward compatibility with broken apps that haven't realized + // yet that hardware keyboards are not the only way of inputting text. + // Nothing to delete before the cursor. We should not do anything, but many + // broken apps expect something to happen in this case so that they can + // catch it and have their broken interface react. If you need the keyboard + // to do this, you're doing it wrong -- please fix your app. + mConnection.deleteSurroundingText(1, 0); return; } final int lengthToDelete = @@ -1335,8 +1341,8 @@ public final class InputLogic { final SuggestedWords suggestedWords = new SuggestedWords(suggestions, null /* rawSuggestions */, typedWord, true /* typedWordValid */, false /* willAutoCorrect */, - false /* isPunctuationSuggestions */, false /* isObsoleteSuggestions */, - false /* isPrediction */, SuggestedWords.NOT_A_SEQUENCE_NUMBER); + false /* isObsoleteSuggestions */, false /* isPrediction */, + SuggestedWords.NOT_A_SEQUENCE_NUMBER); mIsAutoCorrectionIndicatorOn = false; mLatinIME.mHandler.showSuggestionStrip(suggestedWords); } @@ -1355,6 +1361,7 @@ public final class InputLogic { final String previousWord = mLastComposedWord.mPrevWord; final CharSequence originallyTypedWord = mLastComposedWord.mTypedWord; final CharSequence committedWord = mLastComposedWord.mCommittedWord; + final String committedWordString = committedWord.toString(); final int cancelLength = committedWord.length(); // We want java chars, not codepoints for the following. final int separatorLength = mLastComposedWord.mSeparatorString.length(); @@ -1376,33 +1383,44 @@ public final class InputLogic { if (!TextUtils.isEmpty(previousWord) && !TextUtils.isEmpty(committedWord)) { if (mSuggest != null) { mSuggest.mDictionaryFacilitator.cancelAddingUserHistory( - previousWord, committedWord.toString()); + previousWord, committedWordString); } } final String stringToCommit = originallyTypedWord + mLastComposedWord.mSeparatorString; final SpannableString textToCommit = new SpannableString(stringToCommit); if (committedWord instanceof SpannableString) { - final int lastCharIndex = textToCommit.length() - 1; - // Add the auto-correction to the list of suggestions. - textToCommit.setSpan(new SuggestionSpan(settingsValues.mLocale, - new String[] { committedWord.toString() }, 0 /* flags */), - 0 /* start */, lastCharIndex /* end */, 0 /* flags */); final SpannableString committedWordWithSuggestionSpans = (SpannableString)committedWord; final Object[] spans = committedWordWithSuggestionSpans.getSpans(0, committedWord.length(), Object.class); + final int lastCharIndex = textToCommit.length() - 1; + // We will collect all suggestions in the following array. + final ArrayList<String> suggestions = CollectionUtils.newArrayList(); + // First, add the committed word to the list of suggestions. + suggestions.add(committedWordString); for (final Object span : spans) { - // Put all the spans in the original text on this new text. We could remove the - // typed word from the suggestions, but we'd have to make more dynamic instanceof - // checks, to copy the span, copy all suggestions and attributes... And there is - // the risk to drop the originally typed string if there is a subtle bug. There is - // still the committed auto-correction that we reverted from, which is not included - // in the suggestions, that's why we added it with another call to setSpan a few - // lines above. - // The code that re-reads these spans already knows to do the right thing whether - // the typed word is included or not. That should be enough. - textToCommit.setSpan(span, 0 /* start */, lastCharIndex /* end */, - committedWordWithSuggestionSpans.getSpanFlags(span)); + // If this is a suggestion span, we check that the locale is the right one, and + // that the word is not the committed word. That should mostly be the case. + // Given this, we add it to the list of suggestions, otherwise we discard it. + if (span instanceof SuggestionSpan) { + final SuggestionSpan suggestionSpan = (SuggestionSpan)span; + if (!suggestionSpan.getLocale().equals(settingsValues.mLocale.toString())) { + continue; + } + for (final String suggestion : suggestionSpan.getSuggestions()) { + if (!suggestion.equals(committedWordString)) { + suggestions.add(suggestion); + } + } + } else { + // If this is not a suggestion span, we just add it as is. + textToCommit.setSpan(span, 0 /* start */, lastCharIndex /* end */, + committedWordWithSuggestionSpans.getSpanFlags(span)); + } } + // Add the suggestion list to the list of suggestions. + textToCommit.setSpan(new SuggestionSpan(settingsValues.mLocale, + suggestions.toArray(new String[suggestions.size()]), 0 /* flags */), + 0 /* start */, lastCharIndex /* end */, 0 /* flags */); } if (settingsValues.mSpacingAndPunctuations.mCurrentLanguageHasSpaces) { // For languages with spaces, we revert to the typed string, but the cursor is still diff --git a/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java b/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java index 6a7a3368e..8f7378c58 100644 --- a/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java +++ b/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java @@ -51,22 +51,10 @@ public abstract class DecayingExpandableBinaryDictionaryBase extends ExpandableB private final String mDictName; - /* package */ DecayingExpandableBinaryDictionaryBase(final Context context, - final Locale locale, final String dictionaryType, final String dictName) { - super(context, dictName, locale, dictionaryType, true); - mLocale = locale; - mDictName = dictName; - if (mLocale != null && mLocale.toString().length() > 1) { - reloadDictionaryIfRequired(); - } - } - - // Creates an instance that uses a given dictionary file for testing. - @UsedForTesting - /* package */ DecayingExpandableBinaryDictionaryBase(final Context context, - final Locale locale, final String dictionaryType, final String dictName, + protected DecayingExpandableBinaryDictionaryBase(final Context context, + final String dictName, final Locale locale, final String dictionaryType, final File dictFile) { - super(context, dictName, locale, dictionaryType, true, dictFile); + super(context, dictName, locale, dictionaryType, true /* isUpdatable */, dictFile); mLocale = locale; mDictName = dictName; if (mLocale != null && mLocale.toString().length() > 1) { diff --git a/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionary.java b/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionary.java index 652614876..4afd5b4c9 100644 --- a/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionary.java +++ b/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionary.java @@ -16,27 +16,23 @@ package com.android.inputmethod.latin.personalization; -import com.android.inputmethod.annotations.UsedForTesting; +import android.content.Context; + import com.android.inputmethod.latin.Dictionary; import java.io.File; import java.util.Locale; -import android.content.Context; - public class PersonalizationDictionary extends DecayingExpandableBinaryDictionaryBase { /* package */ static final String NAME = PersonalizationDictionary.class.getSimpleName(); /* package */ PersonalizationDictionary(final Context context, final Locale locale) { - super(context, locale, Dictionary.TYPE_PERSONALIZATION, - getDictNameWithLocale(NAME, locale)); + this(context, locale, null /* dictFile */); } - // Creates an instance that uses a given dictionary file for testing. - @UsedForTesting public PersonalizationDictionary(final Context context, final Locale locale, final File dictFile) { - super(context, locale, Dictionary.TYPE_PERSONALIZATION, getDictNameWithLocale(NAME, locale), + super(context, getDictName(NAME, locale, dictFile), locale, Dictionary.TYPE_PERSONALIZATION, dictFile); } diff --git a/java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java b/java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java index 6778c2334..504e9b2f3 100644 --- a/java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java +++ b/java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java @@ -16,29 +16,27 @@ package com.android.inputmethod.latin.personalization; -import com.android.inputmethod.annotations.UsedForTesting; +import android.content.Context; + import com.android.inputmethod.latin.Dictionary; import java.io.File; import java.util.Locale; -import android.content.Context; - /** * Locally gathers stats about the words user types and various other signals like auto-correction * cancellation or manual picks. This allows the keyboard to adapt to the typist over time. */ public class UserHistoryDictionary extends DecayingExpandableBinaryDictionaryBase { /* package */ static final String NAME = UserHistoryDictionary.class.getSimpleName(); + /* package */ UserHistoryDictionary(final Context context, final Locale locale) { - super(context, locale, Dictionary.TYPE_USER_HISTORY, getDictNameWithLocale(NAME, locale)); + this(context, locale, null /* dictFile */); } - // Creates an instance that uses a given dictionary file for testing. - @UsedForTesting public UserHistoryDictionary(final Context context, final Locale locale, final File dictFile) { - super(context, locale, Dictionary.TYPE_USER_HISTORY, getDictNameWithLocale(NAME, locale), + super(context, getDictName(NAME, locale, dictFile), locale, Dictionary.TYPE_USER_HISTORY, dictFile); } diff --git a/java/src/com/android/inputmethod/latin/settings/SettingsValues.java b/java/src/com/android/inputmethod/latin/settings/SettingsValues.java index 90d3519a4..77968f79a 100644 --- a/java/src/com/android/inputmethod/latin/settings/SettingsValues.java +++ b/java/src/com/android/inputmethod/latin/settings/SettingsValues.java @@ -329,4 +329,86 @@ public final class SettingsValues { } return prefs.getBoolean(Settings.PREF_VOICE_INPUT_KEY, true); } + + public String dump() { + final StringBuilder sb = new StringBuilder("Current settings :"); + sb.append("\n mSpacingAndPunctuations = "); + sb.append("" + mSpacingAndPunctuations.dump()); + sb.append("\n mDelayUpdateOldSuggestions = "); + sb.append("" + mDelayUpdateOldSuggestions); + sb.append("\n mAutoCap = "); + sb.append("" + mAutoCap); + sb.append("\n mVibrateOn = "); + sb.append("" + mVibrateOn); + sb.append("\n mSoundOn = "); + sb.append("" + mSoundOn); + sb.append("\n mKeyPreviewPopupOn = "); + sb.append("" + mKeyPreviewPopupOn); + sb.append("\n mShowsVoiceInputKey = "); + sb.append("" + mShowsVoiceInputKey); + sb.append("\n mIncludesOtherImesInLanguageSwitchList = "); + sb.append("" + mIncludesOtherImesInLanguageSwitchList); + sb.append("\n mShowsLanguageSwitchKey = "); + sb.append("" + mShowsLanguageSwitchKey); + sb.append("\n mUseContactsDict = "); + sb.append("" + mUseContactsDict); + sb.append("\n mUsePersonalizedDicts = "); + sb.append("" + mUsePersonalizedDicts); + sb.append("\n mUseDoubleSpacePeriod = "); + sb.append("" + mUseDoubleSpacePeriod); + sb.append("\n mBlockPotentiallyOffensive = "); + sb.append("" + mBlockPotentiallyOffensive); + sb.append("\n mBigramPredictionEnabled = "); + sb.append("" + mBigramPredictionEnabled); + sb.append("\n mGestureInputEnabled = "); + sb.append("" + mGestureInputEnabled); + sb.append("\n mGestureTrailEnabled = "); + sb.append("" + mGestureTrailEnabled); + sb.append("\n mGestureFloatingPreviewTextEnabled = "); + sb.append("" + mGestureFloatingPreviewTextEnabled); + sb.append("\n mSlidingKeyInputPreviewEnabled = "); + sb.append("" + mSlidingKeyInputPreviewEnabled); + sb.append("\n mPhraseGestureEnabled = "); + sb.append("" + mPhraseGestureEnabled); + sb.append("\n mKeyLongpressTimeout = "); + sb.append("" + mKeyLongpressTimeout); + sb.append("\n mLocale = "); + sb.append("" + mLocale); + sb.append("\n mInputAttributes = "); + sb.append("" + mInputAttributes); + sb.append("\n mKeypressVibrationDuration = "); + sb.append("" + mKeypressVibrationDuration); + sb.append("\n mKeypressSoundVolume = "); + sb.append("" + mKeypressSoundVolume); + sb.append("\n mKeyPreviewPopupDismissDelay = "); + sb.append("" + mKeyPreviewPopupDismissDelay); + sb.append("\n mAutoCorrectEnabled = "); + sb.append("" + mAutoCorrectEnabled); + sb.append("\n mAutoCorrectionThreshold = "); + sb.append("" + mAutoCorrectionThreshold); + sb.append("\n mCorrectionEnabled = "); + sb.append("" + mCorrectionEnabled); + sb.append("\n mSuggestionVisibility = "); + sb.append("" + mSuggestionVisibility); + sb.append("\n mUseOnlyPersonalizationDictionaryForDebug = "); + sb.append("" + mUseOnlyPersonalizationDictionaryForDebug); + sb.append("\n mDisplayOrientation = "); + sb.append("" + mDisplayOrientation); + sb.append("\n mAppWorkarounds = "); + final AppWorkaroundsUtils awu = mAppWorkarounds.get(null, 0); + sb.append("" + (null == awu ? "null" : awu.toString())); + sb.append("\n mAdditionalFeaturesSettingValues = "); + sb.append("" + Arrays.toString(mAdditionalFeaturesSettingValues)); + sb.append("\n mIsInternal = "); + sb.append("" + mIsInternal); + sb.append("\n mKeyPreviewShowUpDuration = "); + sb.append("" + mKeyPreviewShowUpDuration); + sb.append("\n mKeyPreviewDismissDuration = "); + sb.append("" + mKeyPreviewDismissDuration); + sb.append("\n mKeyPreviewShowUpStartScale = "); + sb.append("" + mKeyPreviewShowUpStartScale); + sb.append("\n mKeyPreviewDismissEndScale = "); + sb.append("" + mKeyPreviewDismissEndScale); + return sb.toString(); + } } diff --git a/java/src/com/android/inputmethod/latin/settings/SpacingAndPunctuations.java b/java/src/com/android/inputmethod/latin/settings/SpacingAndPunctuations.java index 60ca5baab..5954758aa 100644 --- a/java/src/com/android/inputmethod/latin/settings/SpacingAndPunctuations.java +++ b/java/src/com/android/inputmethod/latin/settings/SpacingAndPunctuations.java @@ -18,17 +18,13 @@ package com.android.inputmethod.latin.settings; import android.content.res.Resources; -import com.android.inputmethod.keyboard.internal.KeySpecParser; +import com.android.inputmethod.keyboard.internal.KeyboardTextsSet; import com.android.inputmethod.keyboard.internal.MoreKeySpec; import com.android.inputmethod.latin.Constants; -import com.android.inputmethod.latin.Dictionary; +import com.android.inputmethod.latin.PunctuationSuggestions; import com.android.inputmethod.latin.R; -import com.android.inputmethod.latin.SuggestedWords; -import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; -import com.android.inputmethod.latin.utils.CollectionUtils; import com.android.inputmethod.latin.utils.StringUtils; -import java.util.ArrayList; import java.util.Arrays; import java.util.Locale; @@ -37,7 +33,7 @@ public final class SpacingAndPunctuations { private final int[] mSortedSymbolsFollowedBySpace; private final int[] mSortedWordConnectors; public final int[] mSortedWordSeparators; - public final SuggestedWords mSuggestPuncList; + public final PunctuationSuggestions mSuggestPuncList; private final int mSentenceSeparator; public final String mSentenceSeparatorAndSpace; public final boolean mCurrentLanguageHasSpaces; @@ -56,9 +52,6 @@ public final class SpacingAndPunctuations { res.getString(R.string.symbols_word_connectors)); mSortedWordSeparators = StringUtils.toSortedCodePointArray( res.getString(R.string.symbols_word_separators)); - final String[] suggestPuncsSpec = MoreKeySpec.splitKeySpecs(res.getString( - R.string.suggested_punctuations)); - mSuggestPuncList = createSuggestPuncList(suggestPuncsSpec); mSentenceSeparator = res.getInteger(R.integer.sentence_separator); mSentenceSeparatorAndSpace = new String(new int[] { mSentenceSeparator, Constants.CODE_SPACE }, 0, 2); @@ -68,28 +61,11 @@ public final class SpacingAndPunctuations { // English variants. German rules (not "German typography") also have small gotchas. mUsesAmericanTypography = Locale.ENGLISH.getLanguage().equals(locale.getLanguage()); mUsesGermanRules = Locale.GERMAN.getLanguage().equals(locale.getLanguage()); - } - - // Helper functions to create member values. - private static SuggestedWords createSuggestPuncList(final String[] puncs) { - final ArrayList<SuggestedWordInfo> puncList = CollectionUtils.newArrayList(); - if (puncs != null) { - for (final String puncSpec : puncs) { - // TODO: Stop using KeySpecParser.getLabel(). - // TODO: Punctuation suggestions should honor RTL languages. - puncList.add(new SuggestedWordInfo(KeySpecParser.getLabel(puncSpec), - SuggestedWordInfo.MAX_SCORE, SuggestedWordInfo.KIND_HARDCODED, - Dictionary.DICTIONARY_HARDCODED, - SuggestedWordInfo.NOT_AN_INDEX /* indexOfTouchPointOfSecondWord */, - SuggestedWordInfo.NOT_A_CONFIDENCE /* autoCommitFirstWordConfidence */)); - } - } - return new SuggestedWords(puncList, null /* rawSuggestions */, - false /* typedWordValid */, - false /* hasAutoCorrectionCandidate */, - true /* isPunctuationSuggestions */, - false /* isObsoleteSuggestions */, - false /* isPrediction */); + final KeyboardTextsSet textsSet = new KeyboardTextsSet(); + textsSet.setLocale(locale); + final String[] suggestPuncsSpec = MoreKeySpec.splitKeySpecs( + textsSet.resolveTextReference(res.getString(R.string.suggested_punctuations))); + mSuggestPuncList = PunctuationSuggestions.newPunctuationSuggestions(suggestPuncsSpec); } public boolean isWordSeparator(final int code) { @@ -115,4 +91,29 @@ public final class SpacingAndPunctuations { public boolean isSentenceSeparator(final int code) { return code == mSentenceSeparator; } + + public String dump() { + final StringBuilder sb = new StringBuilder(); + sb.append("mSortedSymbolsPrecededBySpace = "); + sb.append("" + Arrays.toString(mSortedSymbolsPrecededBySpace)); + sb.append("\n mSortedSymbolsFollowedBySpace = "); + sb.append("" + Arrays.toString(mSortedSymbolsFollowedBySpace)); + sb.append("\n mSortedWordConnectors = "); + sb.append("" + Arrays.toString(mSortedWordConnectors)); + sb.append("\n mSortedWordSeparators = "); + sb.append("" + Arrays.toString(mSortedWordSeparators)); + sb.append("\n mSuggestPuncList = "); + sb.append("" + mSuggestPuncList); + sb.append("\n mSentenceSeparator = "); + sb.append("" + mSentenceSeparator); + sb.append("\n mSentenceSeparatorAndSpace = "); + sb.append("" + mSentenceSeparatorAndSpace); + sb.append("\n mCurrentLanguageHasSpaces = "); + sb.append("" + mCurrentLanguageHasSpaces); + sb.append("\n mUsesAmericanTypography = "); + sb.append("" + mUsesAmericanTypography); + sb.append("\n mUsesGermanRules = "); + sb.append("" + mUsesGermanRules); + return sb.toString(); + } } diff --git a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java index 2f4c1839b..a104baa08 100644 --- a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java +++ b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java @@ -74,7 +74,7 @@ public final class MoreSuggestions extends Keyboard { int rowStartIndex = fromIndex; final int size = Math.min(suggestedWords.size(), SuggestedWords.MAX_SUGGESTIONS); while (index < size) { - final String word = suggestedWords.getWord(index); + final String word = suggestedWords.getLabel(index); // TODO: Should take care of text x-scaling. mWidths[index] = (int)(TypefaceUtils.getStringWidth(word, paint) + padding); final int numColumn = index - rowStartIndex + 1; @@ -206,7 +206,7 @@ public final class MoreSuggestions extends Keyboard { final int x = params.getX(index); final int y = params.getY(index); final int width = params.getWidth(index); - final String word = mSuggestedWords.getWord(index); + final String word = mSuggestedWords.getLabel(index); final String info = mSuggestedWords.getDebugString(index); final int indexInMoreSuggestions = index + SUGGESTION_CODE_BASE; final Key key = new Key(word, KeyboardIconsSet.ICON_UNDEFINED, diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java index 4063edccc..7c11f5432 100644 --- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java +++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java @@ -46,6 +46,7 @@ import android.widget.TextView; import com.android.inputmethod.compat.TextViewCompatUtils; import com.android.inputmethod.latin.LatinImeLogger; +import com.android.inputmethod.latin.PunctuationSuggestions; import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.SuggestedWords; import com.android.inputmethod.latin.utils.AutoCorrectionUtils; @@ -65,7 +66,7 @@ final class SuggestionStripLayoutHelper { public final int mPadding; public final int mDividerWidth; public final int mSuggestionsStripHeight; - public final int mSuggestionsCountInStrip; + private final int mSuggestionsCountInStrip; public final int mMoreSuggestionsRowHeight; private int mMaxMoreSuggestionsRow; public final float mMinMoreSuggestionsWidth; @@ -199,7 +200,7 @@ final class SuggestionStripLayoutHelper { if (indexInSuggestedWords >= suggestedWords.size()) { return null; } - final String word = suggestedWords.getWord(indexInSuggestedWords); + final String word = suggestedWords.getLabel(indexInSuggestedWords); final boolean isAutoCorrect = indexInSuggestedWords == 1 && suggestedWords.mWillAutoCorrect; final boolean isTypedWordValid = indexInSuggestedWords == 0 @@ -264,8 +265,8 @@ final class SuggestionStripLayoutHelper { // is in slot 1. if (positionInStrip == mCenterPositionInStrip && AutoCorrectionUtils.shouldBlockAutoCorrectionBySafetyNet( - suggestedWords.getWord(SuggestedWords.INDEX_OF_AUTO_CORRECTION), - suggestedWords.getWord(SuggestedWords.INDEX_OF_TYPED_WORD))) { + suggestedWords.getLabel(SuggestedWords.INDEX_OF_AUTO_CORRECTION), + suggestedWords.getLabel(SuggestedWords.INDEX_OF_TYPED_WORD))) { return 0xFFFF0000; } } @@ -288,54 +289,65 @@ final class SuggestionStripLayoutHelper { params.gravity = Gravity.CENTER; } - public void layout(final SuggestedWords suggestedWords, final ViewGroup stripView, - final ViewGroup placerView) { - if (suggestedWords.mIsPunctuationSuggestions) { - layoutPunctuationSuggestions(suggestedWords, stripView); - return; + /** + * Layout suggestions to the suggestions strip. And returns the number of suggestions displayed + * in the suggestions strip. + * + * @param suggestedWords suggestions to be shown in the suggestions strip. + * @param stripView the suggestions strip view. + * @param placerView the view where the debug info will be placed. + * @return the number of suggestions displayed in the suggestions strip + */ + public int layoutAndReturnSuggestionCountInStrip(final SuggestedWords suggestedWords, + final ViewGroup stripView, final ViewGroup placerView) { + if (suggestedWords.isPunctuationSuggestions()) { + return layoutPunctuationSuggestionsAndReturnSuggestionCountInStrip( + (PunctuationSuggestions)suggestedWords, stripView); } - final int countInStrip = mSuggestionsCountInStrip; - setupWordViewsTextAndColor(suggestedWords, countInStrip); + setupWordViewsTextAndColor(suggestedWords, mSuggestionsCountInStrip); final TextView centerWordView = mWordViews.get(mCenterPositionInStrip); final int availableStripWidth = placerView.getWidth() - placerView.getPaddingRight() - placerView.getPaddingLeft(); final int centerWidth = getSuggestionWidth(mCenterPositionInStrip, availableStripWidth); - if (getTextScaleX(centerWordView.getText(), centerWidth, centerWordView.getPaint()) - < MIN_TEXT_XSCALE) { + final int countInStrip; + if (suggestedWords.size() == 1 || getTextScaleX(centerWordView.getText(), centerWidth, + centerWordView.getPaint()) < MIN_TEXT_XSCALE) { // Layout only the most relevant suggested word at the center of the suggestion strip // by consolidating all slots in the strip. - mMoreSuggestionsAvailable = (suggestedWords.size() > 1); + countInStrip = 1; + mMoreSuggestionsAvailable = (suggestedWords.size() > countInStrip); layoutWord(mCenterPositionInStrip, availableStripWidth - mPadding); stripView.addView(centerWordView); setLayoutWeight(centerWordView, 1.0f, ViewGroup.LayoutParams.MATCH_PARENT); if (SuggestionStripView.DBG) { layoutDebugInfo(mCenterPositionInStrip, placerView, availableStripWidth); } - return; - } - - mMoreSuggestionsAvailable = (suggestedWords.size() > countInStrip); - int x = 0; - for (int positionInStrip = 0; positionInStrip < countInStrip; positionInStrip++) { - if (positionInStrip != 0) { - final View divider = mDividerViews.get(positionInStrip); - // Add divider if this isn't the left most suggestion in suggestions strip. - addDivider(stripView, divider); - x += divider.getMeasuredWidth(); - } - - final int width = getSuggestionWidth(positionInStrip, availableStripWidth); - final TextView wordView = layoutWord(positionInStrip, width); - stripView.addView(wordView); - setLayoutWeight(wordView, getSuggestionWeight(positionInStrip), - ViewGroup.LayoutParams.MATCH_PARENT); - x += wordView.getMeasuredWidth(); - - if (SuggestionStripView.DBG) { - layoutDebugInfo(positionInStrip, placerView, x); + } else { + countInStrip = mSuggestionsCountInStrip; + mMoreSuggestionsAvailable = (suggestedWords.size() > countInStrip); + int x = 0; + for (int positionInStrip = 0; positionInStrip < countInStrip; positionInStrip++) { + if (positionInStrip != 0) { + final View divider = mDividerViews.get(positionInStrip); + // Add divider if this isn't the left most suggestion in suggestions strip. + addDivider(stripView, divider); + x += divider.getMeasuredWidth(); + } + + final int width = getSuggestionWidth(positionInStrip, availableStripWidth); + final TextView wordView = layoutWord(positionInStrip, width); + stripView.addView(wordView); + setLayoutWeight(wordView, getSuggestionWeight(positionInStrip), + ViewGroup.LayoutParams.MATCH_PARENT); + x += wordView.getMeasuredWidth(); + + if (SuggestionStripView.DBG) { + layoutDebugInfo(positionInStrip, placerView, x); + } } } + return countInStrip; } /** @@ -435,9 +447,9 @@ final class SuggestionStripLayoutHelper { } } - private void layoutPunctuationSuggestions(final SuggestedWords suggestedWords, - final ViewGroup stripView) { - final int countInStrip = Math.min(suggestedWords.size(), PUNCTUATIONS_IN_STRIP); + private int layoutPunctuationSuggestionsAndReturnSuggestionCountInStrip( + final PunctuationSuggestions punctuationSuggestions, final ViewGroup stripView) { + final int countInStrip = Math.min(punctuationSuggestions.size(), PUNCTUATIONS_IN_STRIP); for (int positionInStrip = 0; positionInStrip < countInStrip; positionInStrip++) { if (positionInStrip != 0) { // Add divider if this isn't the left most suggestion in suggestions strip. @@ -450,13 +462,14 @@ final class SuggestionStripLayoutHelper { // {@link TextView#getTag()} is used to get the index in suggestedWords at // {@link SuggestionStripView#onClick(View)}. wordView.setTag(positionInStrip); - wordView.setText(suggestedWords.getWord(positionInStrip)); + wordView.setText(punctuationSuggestions.getLabel(positionInStrip)); wordView.setTextScaleX(1.0f); wordView.setCompoundDrawables(null, null, null, null); stripView.addView(wordView); setLayoutWeight(wordView, 1.0f, mSuggestionsStripHeight); } - mMoreSuggestionsAvailable = (suggestedWords.size() > countInStrip); + mMoreSuggestionsAvailable = (punctuationSuggestions.size() > countInStrip); + return countInStrip; } public void layoutAddToDictionaryHint(final String word, final ViewGroup addToDictionaryStrip, diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java index 68c891bf3..cf0a7a2aa 100644 --- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java +++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java @@ -77,6 +77,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick Listener mListener; private SuggestedWords mSuggestedWords = SuggestedWords.EMPTY; + private int mSuggestionsCountInStrip; private final SuggestionStripLayoutHelper mLayoutHelper; private final StripVisibilityGroup mStripVisibilityGroup; @@ -189,7 +190,8 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick clear(); mStripVisibilityGroup.setLayoutDirection(isRtlLanguage); mSuggestedWords = suggestedWords; - mLayoutHelper.layout(mSuggestedWords, mSuggestionsStrip, this); + mSuggestionsCountInStrip = mLayoutHelper.layoutAndReturnSuggestionCountInStrip( + mSuggestedWords, mSuggestionsStrip, this); if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) { ResearchLogger.suggestionStripView_setSuggestions(mSuggestedWords); } @@ -225,8 +227,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick // it has been shown once already or not, and if in the setup wizard). If applicable, it shows // the notice. In all cases, it returns true if it was shown, false otherwise. public boolean maybeShowImportantNoticeTitle() { - if (!ImportantNoticeUtils.hasNewImportantNotice(getContext()) - || ImportantNoticeUtils.isInSystemSetupWizard(getContext())) { + if (!ImportantNoticeUtils.hasNewImportantNoticeAndNotInSetupWizard(getContext())) { return false; } final int width = getWidth(); @@ -313,7 +314,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick final View container = mMoreSuggestionsContainer; final int maxWidth = stripWidth - container.getPaddingLeft() - container.getPaddingRight(); final MoreSuggestions.Builder builder = mMoreSuggestionsBuilder; - builder.layout(mSuggestedWords, layoutHelper.mSuggestionsCountInStrip, maxWidth, + builder.layout(mSuggestedWords, mSuggestionsCountInStrip, maxWidth, (int)(maxWidth * layoutHelper.mMinMoreSuggestionsWidth), layoutHelper.getMaxMoreSuggestionsRow(), parentKeyboard); mMoreSuggestionsView.setKeyboard(builder.build()); @@ -327,7 +328,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick mMoreSuggestionsMode = MORE_SUGGESTIONS_CHECKING_MODAL_OR_SLIDING; mOriginX = mLastX; mOriginY = mLastY; - for (int i = 0; i < layoutHelper.mSuggestionsCountInStrip; i++) { + for (int i = 0; i < mSuggestionsCountInStrip; i++) { mWordViews.get(i).setPressed(false); } return true; diff --git a/java/src/com/android/inputmethod/latin/utils/ImportantNoticeUtils.java b/java/src/com/android/inputmethod/latin/utils/ImportantNoticeUtils.java index 4a0823155..604c36488 100644 --- a/java/src/com/android/inputmethod/latin/utils/ImportantNoticeUtils.java +++ b/java/src/com/android/inputmethod/latin/utils/ImportantNoticeUtils.java @@ -42,7 +42,7 @@ public final class ImportantNoticeUtils { // This utility class is not publicly instantiable. } - public static boolean isInSystemSetupWizard(final Context context) { + private static boolean isInSystemSetupWizard(final Context context) { try { final int userSetupComplete = Settings.Secure.getInt( context.getContentResolver(), Settings_Secure_USER_SETUP_COMPLETE); @@ -62,10 +62,11 @@ public final class ImportantNoticeUtils { return context.getResources().getInteger(R.integer.config_important_notice_version); } - public static boolean hasNewImportantNotice(final Context context) { + public static boolean hasNewImportantNoticeAndNotInSetupWizard(final Context context) { final SharedPreferences prefs = getImportantNoticePreferences(context); final int lastVersion = prefs.getInt(KEY_IMPORTANT_NOTICE_VERSION, 0); - return getCurrentImportantNoticeVersion(context) > lastVersion; + return getCurrentImportantNoticeVersion(context) > lastVersion + && !isInSystemSetupWizard(context); } public static void updateLastImportantNoticeVersion(final Context context) { |