Loading core/java/android/widget/TextView.java +113 −78 Original line number Diff line number Diff line Loading @@ -9613,6 +9613,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener private class SuggestionsPopupWindow extends PinnedPopupWindow implements OnItemClickListener { private static final int MAX_NUMBER_SUGGESTIONS = SuggestionSpan.SUGGESTIONS_MAX_SIZE; private static final int ADD_TO_DICTIONARY = -1; private static final int DELETE_TEXT = -2; private SuggestionInfo[] mSuggestionInfos; private int mNumberOfSuggestions; private boolean mCursorWasVisibleBeforeSuggestions; Loading Loading @@ -9664,9 +9666,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener listView.setOnItemClickListener(this); mContentView = listView; // Inflate the suggestion items once and for all. +1 for add to dictionary mSuggestionInfos = new SuggestionInfo[MAX_NUMBER_SUGGESTIONS + 1]; for (int i = 0; i < MAX_NUMBER_SUGGESTIONS + 1; i++) { // Inflate the suggestion items once and for all. + 2 for add to dictionary and delete mSuggestionInfos = new SuggestionInfo[MAX_NUMBER_SUGGESTIONS + 2]; for (int i = 0; i < mSuggestionInfos.length; i++) { mSuggestionInfos[i] = new SuggestionInfo(); } } Loading Loading @@ -9717,7 +9719,19 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener false); } textView.setText(mSuggestionInfos[position].text); final SuggestionInfo suggestionInfo = mSuggestionInfos[position]; textView.setText(suggestionInfo.text); if (suggestionInfo.suggestionIndex == ADD_TO_DICTIONARY) { textView.setCompoundDrawablesWithIntrinsicBounds( com.android.internal.R.drawable.ic_suggestions_add, 0, 0, 0); } else if (suggestionInfo.suggestionIndex == DELETE_TEXT) { textView.setCompoundDrawablesWithIntrinsicBounds( com.android.internal.R.drawable.ic_suggestions_delete, 0, 0, 0); } else { textView.setCompoundDrawables(null, null, null, null); } return textView; } } Loading Loading @@ -9768,12 +9782,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener public void show() { if (!(mText instanceof Editable)) return; if (updateSuggestions()) { updateSuggestions(); mCursorWasVisibleBeforeSuggestions = mCursorVisible; setCursorVisible(false); super.show(); } } @Override protected void measureContent() { Loading Loading @@ -9828,7 +9841,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener super.hide(); } private boolean updateSuggestions() { private void updateSuggestions() { Spannable spannable = (Spannable) TextView.this.mText; SuggestionSpan[] suggestionSpans = getSuggestionSpans(); Loading Loading @@ -9877,13 +9890,14 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener highlightTextDifferences(mSuggestionInfos[i], spanUnionStart, spanUnionEnd); } // Add to dictionary item is there a span with the misspelled flag if (misspelledSpan != null) { final int misspelledStart = spannable.getSpanStart(misspelledSpan); final int misspelledEnd = spannable.getSpanEnd(misspelledSpan); if (misspelledStart >= 0 && misspelledEnd > misspelledStart) { SuggestionInfo suggestionInfo = mSuggestionInfos[mNumberOfSuggestions]; suggestionInfo.suggestionSpan = misspelledSpan; suggestionInfo.suggestionIndex = -1; suggestionInfo.suggestionIndex = ADD_TO_DICTIONARY; suggestionInfo.text.replace(0, suggestionInfo.text.length(), getContext().getString(com.android.internal.R.string.addToDictionary)); Loading @@ -9891,7 +9905,13 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } } if (mNumberOfSuggestions == 0) return false; // Delete item SuggestionInfo suggestionInfo = mSuggestionInfos[mNumberOfSuggestions]; suggestionInfo.suggestionSpan = null; suggestionInfo.suggestionIndex = DELETE_TEXT; suggestionInfo.text.replace(0, suggestionInfo.text.length(), getContext().getString(com.android.internal.R.string.deleteText)); mNumberOfSuggestions++; if (mSuggestionRangeSpan == null) mSuggestionRangeSpan = new SuggestionRangeSpan(); if (underlineColor == 0) { Loading @@ -9907,8 +9927,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); mSuggestionsAdapter.notifyDataSetChanged(); return true; } private void highlightTextDifferences(SuggestionInfo suggestionInfo, int unionStart, Loading @@ -9933,19 +9951,36 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { hide(); if (view instanceof TextView) { TextView textView = (TextView) view; Editable editable = (Editable) mText; SuggestionInfo suggestionInfo = mSuggestionInfos[position]; if (suggestionInfo.suggestionIndex == DELETE_TEXT) { final int spanUnionStart = editable.getSpanStart(mSuggestionRangeSpan); int spanUnionEnd = editable.getSpanEnd(mSuggestionRangeSpan); // Do not leave two adjacent spaces after deletion, or one at beginning of text if (spanUnionEnd < editable.length() && Character.isSpaceChar(editable.charAt(spanUnionEnd)) && (spanUnionStart == 0 || Character.isSpaceChar(editable.charAt(spanUnionStart - 1)))) { spanUnionEnd = spanUnionEnd + 1; } editable.replace(spanUnionStart, spanUnionEnd, ""); hide(); return; } final int spanStart = editable.getSpanStart(suggestionInfo.suggestionSpan); final int spanEnd = editable.getSpanEnd(suggestionInfo.suggestionSpan); if (spanStart < 0 || spanEnd < 0) return; // Span has been removed if (spanStart < 0 || spanEnd < 0) { // Span has been removed hide(); return; } final String originalText = mText.subSequence(spanStart, spanEnd).toString(); if (suggestionInfo.suggestionIndex < 0) { if (suggestionInfo.suggestionIndex == ADD_TO_DICTIONARY) { Intent intent = new Intent(Settings.ACTION_USER_DICTIONARY_INSERT); intent.putExtra("word", originalText); intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK); Loading Loading @@ -9995,15 +10030,15 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (suggestionSpansStarts[i] <= spanStart && suggestionSpansEnds[i] >= spanEnd) { editable.setSpan(suggestionSpans[i], suggestionSpansStarts[i], suggestionSpansEnds[i] + lengthDifference, suggestionSpansFlags[i]); suggestionSpansEnds[i] + lengthDifference, suggestionSpansFlags[i]); } } // Move cursor at the end of the replacement word Selection.setSelection(editable, spanEnd + lengthDifference); } } hide(); } } Loading core/res/res/drawable-hdpi/ic_suggestions_add.png 0 → 100644 +381 B Loading image diff... core/res/res/drawable-hdpi/ic_suggestions_delete.png 0 → 100644 +478 B Loading image diff... core/res/res/drawable-mdpi/ic_suggestions_add.png 0 → 100644 +353 B Loading image diff... core/res/res/drawable-mdpi/ic_suggestions_delete.png 0 → 100644 +401 B Loading image diff... Loading
core/java/android/widget/TextView.java +113 −78 Original line number Diff line number Diff line Loading @@ -9613,6 +9613,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener private class SuggestionsPopupWindow extends PinnedPopupWindow implements OnItemClickListener { private static final int MAX_NUMBER_SUGGESTIONS = SuggestionSpan.SUGGESTIONS_MAX_SIZE; private static final int ADD_TO_DICTIONARY = -1; private static final int DELETE_TEXT = -2; private SuggestionInfo[] mSuggestionInfos; private int mNumberOfSuggestions; private boolean mCursorWasVisibleBeforeSuggestions; Loading Loading @@ -9664,9 +9666,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener listView.setOnItemClickListener(this); mContentView = listView; // Inflate the suggestion items once and for all. +1 for add to dictionary mSuggestionInfos = new SuggestionInfo[MAX_NUMBER_SUGGESTIONS + 1]; for (int i = 0; i < MAX_NUMBER_SUGGESTIONS + 1; i++) { // Inflate the suggestion items once and for all. + 2 for add to dictionary and delete mSuggestionInfos = new SuggestionInfo[MAX_NUMBER_SUGGESTIONS + 2]; for (int i = 0; i < mSuggestionInfos.length; i++) { mSuggestionInfos[i] = new SuggestionInfo(); } } Loading Loading @@ -9717,7 +9719,19 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener false); } textView.setText(mSuggestionInfos[position].text); final SuggestionInfo suggestionInfo = mSuggestionInfos[position]; textView.setText(suggestionInfo.text); if (suggestionInfo.suggestionIndex == ADD_TO_DICTIONARY) { textView.setCompoundDrawablesWithIntrinsicBounds( com.android.internal.R.drawable.ic_suggestions_add, 0, 0, 0); } else if (suggestionInfo.suggestionIndex == DELETE_TEXT) { textView.setCompoundDrawablesWithIntrinsicBounds( com.android.internal.R.drawable.ic_suggestions_delete, 0, 0, 0); } else { textView.setCompoundDrawables(null, null, null, null); } return textView; } } Loading Loading @@ -9768,12 +9782,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener public void show() { if (!(mText instanceof Editable)) return; if (updateSuggestions()) { updateSuggestions(); mCursorWasVisibleBeforeSuggestions = mCursorVisible; setCursorVisible(false); super.show(); } } @Override protected void measureContent() { Loading Loading @@ -9828,7 +9841,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener super.hide(); } private boolean updateSuggestions() { private void updateSuggestions() { Spannable spannable = (Spannable) TextView.this.mText; SuggestionSpan[] suggestionSpans = getSuggestionSpans(); Loading Loading @@ -9877,13 +9890,14 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener highlightTextDifferences(mSuggestionInfos[i], spanUnionStart, spanUnionEnd); } // Add to dictionary item is there a span with the misspelled flag if (misspelledSpan != null) { final int misspelledStart = spannable.getSpanStart(misspelledSpan); final int misspelledEnd = spannable.getSpanEnd(misspelledSpan); if (misspelledStart >= 0 && misspelledEnd > misspelledStart) { SuggestionInfo suggestionInfo = mSuggestionInfos[mNumberOfSuggestions]; suggestionInfo.suggestionSpan = misspelledSpan; suggestionInfo.suggestionIndex = -1; suggestionInfo.suggestionIndex = ADD_TO_DICTIONARY; suggestionInfo.text.replace(0, suggestionInfo.text.length(), getContext().getString(com.android.internal.R.string.addToDictionary)); Loading @@ -9891,7 +9905,13 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } } if (mNumberOfSuggestions == 0) return false; // Delete item SuggestionInfo suggestionInfo = mSuggestionInfos[mNumberOfSuggestions]; suggestionInfo.suggestionSpan = null; suggestionInfo.suggestionIndex = DELETE_TEXT; suggestionInfo.text.replace(0, suggestionInfo.text.length(), getContext().getString(com.android.internal.R.string.deleteText)); mNumberOfSuggestions++; if (mSuggestionRangeSpan == null) mSuggestionRangeSpan = new SuggestionRangeSpan(); if (underlineColor == 0) { Loading @@ -9907,8 +9927,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); mSuggestionsAdapter.notifyDataSetChanged(); return true; } private void highlightTextDifferences(SuggestionInfo suggestionInfo, int unionStart, Loading @@ -9933,19 +9951,36 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { hide(); if (view instanceof TextView) { TextView textView = (TextView) view; Editable editable = (Editable) mText; SuggestionInfo suggestionInfo = mSuggestionInfos[position]; if (suggestionInfo.suggestionIndex == DELETE_TEXT) { final int spanUnionStart = editable.getSpanStart(mSuggestionRangeSpan); int spanUnionEnd = editable.getSpanEnd(mSuggestionRangeSpan); // Do not leave two adjacent spaces after deletion, or one at beginning of text if (spanUnionEnd < editable.length() && Character.isSpaceChar(editable.charAt(spanUnionEnd)) && (spanUnionStart == 0 || Character.isSpaceChar(editable.charAt(spanUnionStart - 1)))) { spanUnionEnd = spanUnionEnd + 1; } editable.replace(spanUnionStart, spanUnionEnd, ""); hide(); return; } final int spanStart = editable.getSpanStart(suggestionInfo.suggestionSpan); final int spanEnd = editable.getSpanEnd(suggestionInfo.suggestionSpan); if (spanStart < 0 || spanEnd < 0) return; // Span has been removed if (spanStart < 0 || spanEnd < 0) { // Span has been removed hide(); return; } final String originalText = mText.subSequence(spanStart, spanEnd).toString(); if (suggestionInfo.suggestionIndex < 0) { if (suggestionInfo.suggestionIndex == ADD_TO_DICTIONARY) { Intent intent = new Intent(Settings.ACTION_USER_DICTIONARY_INSERT); intent.putExtra("word", originalText); intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK); Loading Loading @@ -9995,15 +10030,15 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (suggestionSpansStarts[i] <= spanStart && suggestionSpansEnds[i] >= spanEnd) { editable.setSpan(suggestionSpans[i], suggestionSpansStarts[i], suggestionSpansEnds[i] + lengthDifference, suggestionSpansFlags[i]); suggestionSpansEnds[i] + lengthDifference, suggestionSpansFlags[i]); } } // Move cursor at the end of the replacement word Selection.setSelection(editable, spanEnd + lengthDifference); } } hide(); } } Loading