Loading core/java/android/text/method/ArrowKeyMovementMethod.java +6 −6 Original line number Diff line number Diff line Loading @@ -197,16 +197,18 @@ public class ArrowKeyMovementMethod extends BaseMovementMethod implements Moveme @Override protected boolean leftWord(TextView widget, Spannable buffer) { final int selectionEnd = widget.getSelectionEnd(); mWordIterator.setCharSequence(buffer, selectionEnd, selectionEnd); return Selection.moveToPreceding(buffer, mWordIterator, isSelecting(buffer)); final WordIterator wordIterator = widget.getWordIterator(); wordIterator.setCharSequence(buffer, selectionEnd, selectionEnd); return Selection.moveToPreceding(buffer, wordIterator, isSelecting(buffer)); } /** {@hide} */ @Override protected boolean rightWord(TextView widget, Spannable buffer) { final int selectionEnd = widget.getSelectionEnd(); mWordIterator.setCharSequence(buffer, selectionEnd, selectionEnd); return Selection.moveToFollowing(buffer, mWordIterator, isSelecting(buffer)); final WordIterator wordIterator = widget.getWordIterator(); wordIterator.setCharSequence(buffer, selectionEnd, selectionEnd); return Selection.moveToFollowing(buffer, wordIterator, isSelecting(buffer)); } @Override Loading Loading @@ -322,8 +324,6 @@ public class ArrowKeyMovementMethod extends BaseMovementMethod implements Moveme return sInstance; } private WordIterator mWordIterator = new WordIterator(); private static final Object LAST_TAP_DOWN = new Object(); private static ArrowKeyMovementMethod sInstance; } core/java/android/widget/SpellChecker.java +56 −17 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ import android.view.textservice.TextServicesManager; import com.android.internal.util.ArrayUtils; import java.text.BreakIterator; import java.util.Locale; /** Loading @@ -45,7 +46,7 @@ public class SpellChecker implements SpellCheckerSessionListener { private final TextView mTextView; final SpellCheckerSession mSpellCheckerSession; SpellCheckerSession mSpellCheckerSession; final int mCookie; // Paired arrays for the (id, spellCheckSpan) pair. A negative id means the associated Loading @@ -61,23 +62,54 @@ public class SpellChecker implements SpellCheckerSessionListener { private int mSpanSequenceCounter = 0; private Locale mCurrentLocale; // Shared by all SpellParsers. Cannot be shared with TextView since it may be used // concurrently due to the asynchronous nature of onGetSuggestions. private WordIterator mWordIterator; public SpellChecker(TextView textView) { mTextView = textView; final TextServicesManager textServicesManager = (TextServicesManager) textView.getContext(). getSystemService(Context.TEXT_SERVICES_MANAGER_SERVICE); mSpellCheckerSession = textServicesManager.newSpellCheckerSession( null /* not currently used by the textServicesManager */, null /* null locale means use the languages defined in Settings if referToSpellCheckerLanguageSettings is true */, this, true /* means use the languages defined in Settings */); mCookie = hashCode(); // Arbitrary: 4 simultaneous spell check spans. Will automatically double size on demand // Arbitrary: these arrays will automatically double their sizes on demand final int size = ArrayUtils.idealObjectArraySize(1); mIds = new int[size]; mSpellCheckSpans = new SpellCheckSpan[size]; setLocale(mTextView.getLocale()); mCookie = hashCode(); } private void setLocale(Locale locale) { final TextServicesManager textServicesManager = (TextServicesManager) mTextView.getContext().getSystemService(Context.TEXT_SERVICES_MANAGER_SERVICE); mSpellCheckerSession = textServicesManager.newSpellCheckerSession( null /* Bundle not currently used by the textServicesManager */, locale, this, false /* means any available languages from current spell checker */); mCurrentLocale = locale; // Restore SpellCheckSpans in pool for (int i = 0; i < mLength; i++) { mSpellCheckSpans[i].setSpellCheckInProgress(false); mIds[i] = -1; } mLength = 0; // Change SpellParsers' wordIterator locale mWordIterator = new WordIterator(locale); // Stop all SpellParsers final int length = mSpellParsers.length; for (int i = 0; i < length; i++) { mSpellParsers[i].finish(); } // Remove existing misspelled SuggestionSpans mTextView.removeMisspelledSpans((Editable) mTextView.getText()); // This class is the listener for locale change: warn other locale-aware objects mTextView.onLocaleChanged(); } /** Loading @@ -95,7 +127,7 @@ public class SpellChecker implements SpellCheckerSessionListener { final int length = mSpellParsers.length; for (int i = 0; i < length; i++) { mSpellParsers[i].close(); mSpellParsers[i].finish(); } } Loading Loading @@ -140,12 +172,20 @@ public class SpellChecker implements SpellCheckerSessionListener { } public void spellCheck(int start, int end) { final Locale locale = mTextView.getLocale(); if (mCurrentLocale == null || (!(mCurrentLocale.equals(locale)))) { setLocale(locale); // Re-check the entire text start = 0; end = mTextView.getText().length(); } if (!isSessionActive()) return; final int length = mSpellParsers.length; for (int i = 0; i < length; i++) { final SpellParser spellParser = mSpellParsers[i]; if (spellParser.isDone()) { if (spellParser.isFinished()) { spellParser.init(start, end); spellParser.parse(); return; Loading Loading @@ -229,7 +269,7 @@ public class SpellChecker implements SpellCheckerSessionListener { final int length = mSpellParsers.length; for (int i = 0; i < length; i++) { final SpellParser spellParser = mSpellParsers[i]; if (!spellParser.isDone()) { if (!spellParser.isFinished()) { spellParser.parse(); } } Loading Loading @@ -301,7 +341,6 @@ public class SpellChecker implements SpellCheckerSessionListener { } private class SpellParser { private WordIterator mWordIterator = new WordIterator(/*TODO Locale*/); private Object mRange = new Object(); public void init(int start, int end) { Loading @@ -309,11 +348,11 @@ public class SpellChecker implements SpellCheckerSessionListener { Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } public void close() { public void finish() { ((Editable) mTextView.getText()).removeSpan(mRange); } public boolean isDone() { public boolean isFinished() { return ((Editable) mTextView.getText()).getSpanStart(mRange) < 0; } Loading core/java/android/widget/TextView.java +56 −15 Original line number Diff line number Diff line Loading @@ -132,6 +132,7 @@ import android.view.inputmethod.ExtractedText; import android.view.inputmethod.ExtractedTextRequest; import android.view.inputmethod.InputConnection; import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodSubtype; import android.widget.AdapterView.OnItemClickListener; import android.widget.RemoteViews.RemoteView; Loading @@ -147,6 +148,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; import java.util.HashMap; import java.util.Locale; /** * Displays text to the user and optionally allows them to edit it. A TextView Loading Loading @@ -2973,15 +2975,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener sp.removeSpan(cw); } SuggestionSpan[] suggestionSpans = sp.getSpans(0, sp.length(), SuggestionSpan.class); for (int i = 0; i < suggestionSpans.length; i++) { int flags = suggestionSpans[i].getFlags(); if ((flags & SuggestionSpan.FLAG_EASY_CORRECT) != 0 && (flags & SuggestionSpan.FLAG_MISSPELLED) != 0) { sp.removeSpan(suggestionSpans[i]); } } removeMisspelledSpans(sp); sp.removeSpan(mSuggestionRangeSpan); ss.text = sp; Loading @@ -3001,6 +2995,18 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener return superState; } void removeMisspelledSpans(Spannable spannable) { SuggestionSpan[] suggestionSpans = spannable.getSpans(0, spannable.length(), SuggestionSpan.class); for (int i = 0; i < suggestionSpans.length; i++) { int flags = suggestionSpans[i].getFlags(); if ((flags & SuggestionSpan.FLAG_EASY_CORRECT) != 0 && (flags & SuggestionSpan.FLAG_MISSPELLED) != 0) { spannable.removeSpan(suggestionSpans[i]); } } } @Override public void onRestoreInstanceState(Parcelable state) { if (!(state instanceof SavedState)) { Loading Loading @@ -8870,15 +8876,13 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener selectionStart = ((Spanned) mText).getSpanStart(urlSpan); selectionEnd = ((Spanned) mText).getSpanEnd(urlSpan); } else { if (mWordIterator == null) { mWordIterator = new WordIterator(); } mWordIterator.setCharSequence(mText, minOffset, maxOffset); final WordIterator wordIterator = getWordIterator(); wordIterator.setCharSequence(mText, minOffset, maxOffset); selectionStart = mWordIterator.getBeginning(minOffset); selectionStart = wordIterator.getBeginning(minOffset); if (selectionStart == BreakIterator.DONE) return false; selectionEnd = mWordIterator.getEnd(maxOffset); selectionEnd = wordIterator.getEnd(maxOffset); if (selectionEnd == BreakIterator.DONE) return false; if (selectionStart == selectionEnd) { Loading @@ -8893,6 +8897,43 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener return selectionEnd > selectionStart; } /** * This is a temporary method. Future versions may support multi-locale text. * * @return The current locale used in this TextView, based on the current IME's locale, * or the system default locale if this is not defined. * @hide */ public Locale getLocale() { Locale locale = Locale.getDefault(); final InputMethodManager imm = InputMethodManager.peekInstance(); if (imm != null) { final InputMethodSubtype currentInputMethodSubtype = imm.getCurrentInputMethodSubtype(); if (currentInputMethodSubtype != null) { String localeString = currentInputMethodSubtype.getLocale(); if (!TextUtils.isEmpty(localeString)) { locale = new Locale(localeString); } } } return locale; } void onLocaleChanged() { // Will be re-created on demand in getWordIterator with the proper new locale mWordIterator = null; } /** * @hide */ public WordIterator getWordIterator() { if (mWordIterator == null) { mWordIterator = new WordIterator(getLocale()); } return mWordIterator; } private long getCharRange(int offset) { final int textLength = mText.length(); if (offset + 1 < textLength) { Loading Loading
core/java/android/text/method/ArrowKeyMovementMethod.java +6 −6 Original line number Diff line number Diff line Loading @@ -197,16 +197,18 @@ public class ArrowKeyMovementMethod extends BaseMovementMethod implements Moveme @Override protected boolean leftWord(TextView widget, Spannable buffer) { final int selectionEnd = widget.getSelectionEnd(); mWordIterator.setCharSequence(buffer, selectionEnd, selectionEnd); return Selection.moveToPreceding(buffer, mWordIterator, isSelecting(buffer)); final WordIterator wordIterator = widget.getWordIterator(); wordIterator.setCharSequence(buffer, selectionEnd, selectionEnd); return Selection.moveToPreceding(buffer, wordIterator, isSelecting(buffer)); } /** {@hide} */ @Override protected boolean rightWord(TextView widget, Spannable buffer) { final int selectionEnd = widget.getSelectionEnd(); mWordIterator.setCharSequence(buffer, selectionEnd, selectionEnd); return Selection.moveToFollowing(buffer, mWordIterator, isSelecting(buffer)); final WordIterator wordIterator = widget.getWordIterator(); wordIterator.setCharSequence(buffer, selectionEnd, selectionEnd); return Selection.moveToFollowing(buffer, wordIterator, isSelecting(buffer)); } @Override Loading Loading @@ -322,8 +324,6 @@ public class ArrowKeyMovementMethod extends BaseMovementMethod implements Moveme return sInstance; } private WordIterator mWordIterator = new WordIterator(); private static final Object LAST_TAP_DOWN = new Object(); private static ArrowKeyMovementMethod sInstance; }
core/java/android/widget/SpellChecker.java +56 −17 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ import android.view.textservice.TextServicesManager; import com.android.internal.util.ArrayUtils; import java.text.BreakIterator; import java.util.Locale; /** Loading @@ -45,7 +46,7 @@ public class SpellChecker implements SpellCheckerSessionListener { private final TextView mTextView; final SpellCheckerSession mSpellCheckerSession; SpellCheckerSession mSpellCheckerSession; final int mCookie; // Paired arrays for the (id, spellCheckSpan) pair. A negative id means the associated Loading @@ -61,23 +62,54 @@ public class SpellChecker implements SpellCheckerSessionListener { private int mSpanSequenceCounter = 0; private Locale mCurrentLocale; // Shared by all SpellParsers. Cannot be shared with TextView since it may be used // concurrently due to the asynchronous nature of onGetSuggestions. private WordIterator mWordIterator; public SpellChecker(TextView textView) { mTextView = textView; final TextServicesManager textServicesManager = (TextServicesManager) textView.getContext(). getSystemService(Context.TEXT_SERVICES_MANAGER_SERVICE); mSpellCheckerSession = textServicesManager.newSpellCheckerSession( null /* not currently used by the textServicesManager */, null /* null locale means use the languages defined in Settings if referToSpellCheckerLanguageSettings is true */, this, true /* means use the languages defined in Settings */); mCookie = hashCode(); // Arbitrary: 4 simultaneous spell check spans. Will automatically double size on demand // Arbitrary: these arrays will automatically double their sizes on demand final int size = ArrayUtils.idealObjectArraySize(1); mIds = new int[size]; mSpellCheckSpans = new SpellCheckSpan[size]; setLocale(mTextView.getLocale()); mCookie = hashCode(); } private void setLocale(Locale locale) { final TextServicesManager textServicesManager = (TextServicesManager) mTextView.getContext().getSystemService(Context.TEXT_SERVICES_MANAGER_SERVICE); mSpellCheckerSession = textServicesManager.newSpellCheckerSession( null /* Bundle not currently used by the textServicesManager */, locale, this, false /* means any available languages from current spell checker */); mCurrentLocale = locale; // Restore SpellCheckSpans in pool for (int i = 0; i < mLength; i++) { mSpellCheckSpans[i].setSpellCheckInProgress(false); mIds[i] = -1; } mLength = 0; // Change SpellParsers' wordIterator locale mWordIterator = new WordIterator(locale); // Stop all SpellParsers final int length = mSpellParsers.length; for (int i = 0; i < length; i++) { mSpellParsers[i].finish(); } // Remove existing misspelled SuggestionSpans mTextView.removeMisspelledSpans((Editable) mTextView.getText()); // This class is the listener for locale change: warn other locale-aware objects mTextView.onLocaleChanged(); } /** Loading @@ -95,7 +127,7 @@ public class SpellChecker implements SpellCheckerSessionListener { final int length = mSpellParsers.length; for (int i = 0; i < length; i++) { mSpellParsers[i].close(); mSpellParsers[i].finish(); } } Loading Loading @@ -140,12 +172,20 @@ public class SpellChecker implements SpellCheckerSessionListener { } public void spellCheck(int start, int end) { final Locale locale = mTextView.getLocale(); if (mCurrentLocale == null || (!(mCurrentLocale.equals(locale)))) { setLocale(locale); // Re-check the entire text start = 0; end = mTextView.getText().length(); } if (!isSessionActive()) return; final int length = mSpellParsers.length; for (int i = 0; i < length; i++) { final SpellParser spellParser = mSpellParsers[i]; if (spellParser.isDone()) { if (spellParser.isFinished()) { spellParser.init(start, end); spellParser.parse(); return; Loading Loading @@ -229,7 +269,7 @@ public class SpellChecker implements SpellCheckerSessionListener { final int length = mSpellParsers.length; for (int i = 0; i < length; i++) { final SpellParser spellParser = mSpellParsers[i]; if (!spellParser.isDone()) { if (!spellParser.isFinished()) { spellParser.parse(); } } Loading Loading @@ -301,7 +341,6 @@ public class SpellChecker implements SpellCheckerSessionListener { } private class SpellParser { private WordIterator mWordIterator = new WordIterator(/*TODO Locale*/); private Object mRange = new Object(); public void init(int start, int end) { Loading @@ -309,11 +348,11 @@ public class SpellChecker implements SpellCheckerSessionListener { Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } public void close() { public void finish() { ((Editable) mTextView.getText()).removeSpan(mRange); } public boolean isDone() { public boolean isFinished() { return ((Editable) mTextView.getText()).getSpanStart(mRange) < 0; } Loading
core/java/android/widget/TextView.java +56 −15 Original line number Diff line number Diff line Loading @@ -132,6 +132,7 @@ import android.view.inputmethod.ExtractedText; import android.view.inputmethod.ExtractedTextRequest; import android.view.inputmethod.InputConnection; import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodSubtype; import android.widget.AdapterView.OnItemClickListener; import android.widget.RemoteViews.RemoteView; Loading @@ -147,6 +148,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; import java.util.HashMap; import java.util.Locale; /** * Displays text to the user and optionally allows them to edit it. A TextView Loading Loading @@ -2973,15 +2975,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener sp.removeSpan(cw); } SuggestionSpan[] suggestionSpans = sp.getSpans(0, sp.length(), SuggestionSpan.class); for (int i = 0; i < suggestionSpans.length; i++) { int flags = suggestionSpans[i].getFlags(); if ((flags & SuggestionSpan.FLAG_EASY_CORRECT) != 0 && (flags & SuggestionSpan.FLAG_MISSPELLED) != 0) { sp.removeSpan(suggestionSpans[i]); } } removeMisspelledSpans(sp); sp.removeSpan(mSuggestionRangeSpan); ss.text = sp; Loading @@ -3001,6 +2995,18 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener return superState; } void removeMisspelledSpans(Spannable spannable) { SuggestionSpan[] suggestionSpans = spannable.getSpans(0, spannable.length(), SuggestionSpan.class); for (int i = 0; i < suggestionSpans.length; i++) { int flags = suggestionSpans[i].getFlags(); if ((flags & SuggestionSpan.FLAG_EASY_CORRECT) != 0 && (flags & SuggestionSpan.FLAG_MISSPELLED) != 0) { spannable.removeSpan(suggestionSpans[i]); } } } @Override public void onRestoreInstanceState(Parcelable state) { if (!(state instanceof SavedState)) { Loading Loading @@ -8870,15 +8876,13 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener selectionStart = ((Spanned) mText).getSpanStart(urlSpan); selectionEnd = ((Spanned) mText).getSpanEnd(urlSpan); } else { if (mWordIterator == null) { mWordIterator = new WordIterator(); } mWordIterator.setCharSequence(mText, minOffset, maxOffset); final WordIterator wordIterator = getWordIterator(); wordIterator.setCharSequence(mText, minOffset, maxOffset); selectionStart = mWordIterator.getBeginning(minOffset); selectionStart = wordIterator.getBeginning(minOffset); if (selectionStart == BreakIterator.DONE) return false; selectionEnd = mWordIterator.getEnd(maxOffset); selectionEnd = wordIterator.getEnd(maxOffset); if (selectionEnd == BreakIterator.DONE) return false; if (selectionStart == selectionEnd) { Loading @@ -8893,6 +8897,43 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener return selectionEnd > selectionStart; } /** * This is a temporary method. Future versions may support multi-locale text. * * @return The current locale used in this TextView, based on the current IME's locale, * or the system default locale if this is not defined. * @hide */ public Locale getLocale() { Locale locale = Locale.getDefault(); final InputMethodManager imm = InputMethodManager.peekInstance(); if (imm != null) { final InputMethodSubtype currentInputMethodSubtype = imm.getCurrentInputMethodSubtype(); if (currentInputMethodSubtype != null) { String localeString = currentInputMethodSubtype.getLocale(); if (!TextUtils.isEmpty(localeString)) { locale = new Locale(localeString); } } } return locale; } void onLocaleChanged() { // Will be re-created on demand in getWordIterator with the proper new locale mWordIterator = null; } /** * @hide */ public WordIterator getWordIterator() { if (mWordIterator == null) { mWordIterator = new WordIterator(getLocale()); } return mWordIterator; } private long getCharRange(int offset) { final int textLength = mText.length(); if (offset + 1 < textLength) { Loading