Loading core/java/android/provider/Settings.java +21 −2 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ import android.speech.tts.TextToSpeech; import android.text.TextUtils; import android.util.AndroidException; import android.util.Log; import android.view.WindowOrientationListener; import java.net.URISyntaxException; import java.util.HashMap; Loading @@ -59,7 +60,7 @@ public final class Settings { * <p> * Input: Nothing. * <p> * Output: nothing. * Output: Nothing. */ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String ACTION_SETTINGS = "android.settings.SETTINGS"; Loading @@ -69,7 +70,7 @@ public final class Settings { * <p> * Input: Nothing. * <p> * Output: nothing. * Output: Nothing. */ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String ACTION_APN_SETTINGS = "android.settings.APN_SETTINGS"; Loading Loading @@ -327,6 +328,23 @@ public final class Settings { public static final String ACTION_USER_DICTIONARY_SETTINGS = "android.settings.USER_DICTIONARY_SETTINGS"; /** * Activity Action: Adds a word to the user dictionary. * <p> * In some cases, a matching Activity may not exist, so ensure you * safeguard against this. * <p> * Input: An extra with key <code>word</code> that contains the word * that should be added to the dictionary. * <p> * Output: Nothing. * * @hide */ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String ACTION_USER_DICTIONARY_INSERT = "com.android.settings.USER_DICTIONARY_INSERT"; /** * Activity Action: Show settings to allow configuration of application-related settings. * <p> Loading Loading @@ -1462,6 +1480,7 @@ public final class Settings { * @hide * @deprecated */ @Deprecated public static final String NOTIFICATIONS_USE_RING_VOLUME = "notifications_use_ring_volume"; Loading core/java/android/widget/TextView.java +53 −44 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import android.content.ClipData; import android.content.ClipData.Item; import android.content.ClipboardManager; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.content.res.ColorStateList; import android.content.res.Resources; Loading @@ -42,6 +43,7 @@ import android.os.Message; import android.os.Parcel; import android.os.Parcelable; import android.os.SystemClock; import android.provider.Settings; import android.text.BoringLayout; import android.text.DynamicLayout; import android.text.Editable; Loading Loading @@ -9417,7 +9419,6 @@ 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 NO_SUGGESTIONS = -1; private static final float AVERAGE_HIGHLIGHTS_PER_SUGGESTION = 1.4f; private WordIterator mSuggestionWordIterator; private TextAppearanceSpan[] mHighlightSpans = new TextAppearanceSpan Loading Loading @@ -9472,9 +9473,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener listView.setOnItemClickListener(this); mContentView = listView; // Inflate the suggestion items once and for all. mSuggestionInfos = new SuggestionInfo[MAX_NUMBER_SUGGESTIONS]; for (int i = 0; i < MAX_NUMBER_SUGGESTIONS; i++) { // 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++) { mSuggestionInfos[i] = new SuggestionInfo(); } } Loading @@ -9485,6 +9486,15 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener SuggestionSpan suggestionSpan; // the SuggestionSpan that this TextView represents int suggestionIndex; // the index of the suggestion inside suggestionSpan SpannableStringBuilder text = new SpannableStringBuilder(); void removeMisspelledFlag() { int suggestionSpanFlags = suggestionSpan.getFlags(); if ((suggestionSpanFlags & SuggestionSpan.FLAG_MISSPELLED) > 0) { suggestionSpanFlags &= ~(SuggestionSpan.FLAG_MISSPELLED); suggestionSpanFlags &= ~(SuggestionSpan.FLAG_EASY_CORRECT); suggestionSpan.setFlags(suggestionSpanFlags); } } } private class SuggestionAdapter extends BaseAdapter { Loading Loading @@ -9623,6 +9633,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener int spanUnionStart = mText.length(); int spanUnionEnd = 0; SuggestionSpan misspelledSpan = null; for (int spanIndex = 0; spanIndex < nbSpans; spanIndex++) { SuggestionSpan suggestionSpan = suggestionSpans[spanIndex]; final int spanStart = spannable.getSpanStart(suggestionSpan); Loading @@ -9630,6 +9642,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener spanUnionStart = Math.min(spanStart, spanUnionStart); spanUnionEnd = Math.max(spanEnd, spanUnionEnd); if ((suggestionSpan.getFlags() & SuggestionSpan.FLAG_MISSPELLED) != 0) { misspelledSpan = suggestionSpan; } String[] suggestions = suggestionSpan.getSuggestions(); int nbSuggestions = suggestions.length; for (int suggestionIndex = 0; suggestionIndex < nbSuggestions; suggestionIndex++) { Loading @@ -9638,7 +9654,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener suggestionInfo.spanEnd = spanEnd; suggestionInfo.suggestionSpan = suggestionSpan; suggestionInfo.suggestionIndex = suggestionIndex; suggestionInfo.text = new SpannableStringBuilder(suggestions[suggestionIndex]); suggestionInfo.text.replace(0, suggestionInfo.text.length(), suggestions[suggestionIndex]); mNumberOfSuggestions++; if (mNumberOfSuggestions == MAX_NUMBER_SUGGESTIONS) { Loading @@ -9649,41 +9666,38 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } } for (int i = 0; i < mNumberOfSuggestions; i++) { highlightTextDifferences(mSuggestionInfos[i], spanUnionStart, spanUnionEnd); } 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.spanStart = misspelledStart; suggestionInfo.spanEnd = misspelledEnd; suggestionInfo.suggestionSpan = misspelledSpan; suggestionInfo.suggestionIndex = -1; suggestionInfo.text.replace(0, suggestionInfo.text.length(), getContext().getString(com.android.internal.R.string.addToDictionary)); mNumberOfSuggestions++; } } if (mNumberOfSuggestions == 0) return false; if (mSuggestionRangeSpan == null) mSuggestionRangeSpan = new SuggestionRangeSpan(mHighlightColor); ((Editable) mText).setSpan(mSuggestionRangeSpan, spanUnionStart, spanUnionEnd, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); for (int i = 0; i < mNumberOfSuggestions; i++) { highlightTextDifferences(mSuggestionInfos[i], spanUnionStart, spanUnionEnd); } mSuggestionsAdapter.notifyDataSetChanged(); return true; } private void onDictionarySuggestionsReceived(String[] suggestions) { if (suggestions.length == 0) { // TODO Actual implementation of this feature suggestions = new String[] {"Add to dictionary"}; } WordIterator wordIterator = getWordIterator(); wordIterator.setCharSequence(mText); final int pos = getSelectionStart(); int wordStart = wordIterator.getBeginning(pos); int wordEnd = wordIterator.getEnd(pos); SuggestionSpan suggestionSpan = new SuggestionSpan(getContext(), suggestions, 0); ((Editable) mText).setSpan(suggestionSpan, wordStart, wordEnd, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); show(); } private long[] getWordLimits(CharSequence text) { // TODO locale for mSuggestionWordIterator if (mSuggestionWordIterator == null) mSuggestionWordIterator = new WordIterator(); Loading Loading @@ -9836,10 +9850,19 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener public void onItemClick(AdapterView<?> parent, View view, int position, long id) { if (view instanceof TextView) { TextView textView = (TextView) view; SuggestionInfo suggestionInfo = mSuggestionInfos[position]; final int spanStart = suggestionInfo.spanStart; final int spanEnd = suggestionInfo.spanEnd; if (spanStart != NO_SUGGESTIONS) { final String originalText = mText.subSequence(spanStart, spanEnd).toString(); if (suggestionInfo.suggestionIndex < 0) { Intent intent = new Intent(Settings.ACTION_USER_DICTIONARY_INSERT); intent.putExtra("word", originalText); intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK); getContext().startActivity(intent); suggestionInfo.removeMisspelledFlag(); } else { // SuggestionSpans are removed by replace: save them before Editable editable = (Editable) mText; SuggestionSpan[] suggestionSpans = editable.getSpans(spanStart, spanEnd, Loading @@ -9859,17 +9882,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener final int suggestionEnd = suggestionInfo.suggestionEnd; final String suggestion = textView.getText().subSequence( suggestionStart, suggestionEnd).toString(); final String originalText = mText.subSequence(spanStart, spanEnd).toString(); editable.replace(spanStart, spanEnd, suggestion); // A replacement on a misspelled text removes the misspelled flag. // TODO restore the flag if the misspelled word is selected back? int suggestionSpanFlags = suggestionInfo.suggestionSpan.getFlags(); if ((suggestionSpanFlags & SuggestionSpan.FLAG_MISSPELLED) > 0) { suggestionSpanFlags &= ~(SuggestionSpan.FLAG_MISSPELLED); suggestionSpanFlags &= ~(SuggestionSpan.FLAG_EASY_CORRECT); suggestionInfo.suggestionSpan.setFlags(suggestionSpanFlags); } suggestionInfo.removeMisspelledFlag(); // Notify source IME of the suggestion pick. Do this before swaping texts. if (!TextUtils.isEmpty( Loading Loading @@ -9916,12 +9931,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener return mSuggestionsPopupWindow != null && mSuggestionsPopupWindow.isShowing(); } void onDictionarySuggestionsReceived(String[] suggestions) { if (mSuggestionsPopupWindow != null) { mSuggestionsPopupWindow.onDictionarySuggestionsReceived(suggestions); } } /** * Return whether or not suggestions are enabled on this TextView. The suggestions are generated * by the IME or by the spell checker as the user types. This is done by adding Loading core/res/res/values/strings.xml +3 −0 Original line number Diff line number Diff line Loading @@ -2484,6 +2484,9 @@ <!-- Text selection contextual mode title, displayed in the CAB. [CHAR LIMIT=20] --> <string name="textSelectionCABTitle">Text selection</string> <!-- Option to add the current misspelled word to the user dictionary. [CHAR LIMIT=25] --> <string name="addToDictionary">+ add to dictionary</string> <!-- EditText context menu --> <string name="inputMethod">Input method</string> Loading core/java/android/text/TextUtils.java +1 −1 File changed.Contains only whitespace changes. Show changes Loading
core/java/android/provider/Settings.java +21 −2 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ import android.speech.tts.TextToSpeech; import android.text.TextUtils; import android.util.AndroidException; import android.util.Log; import android.view.WindowOrientationListener; import java.net.URISyntaxException; import java.util.HashMap; Loading @@ -59,7 +60,7 @@ public final class Settings { * <p> * Input: Nothing. * <p> * Output: nothing. * Output: Nothing. */ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String ACTION_SETTINGS = "android.settings.SETTINGS"; Loading @@ -69,7 +70,7 @@ public final class Settings { * <p> * Input: Nothing. * <p> * Output: nothing. * Output: Nothing. */ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String ACTION_APN_SETTINGS = "android.settings.APN_SETTINGS"; Loading Loading @@ -327,6 +328,23 @@ public final class Settings { public static final String ACTION_USER_DICTIONARY_SETTINGS = "android.settings.USER_DICTIONARY_SETTINGS"; /** * Activity Action: Adds a word to the user dictionary. * <p> * In some cases, a matching Activity may not exist, so ensure you * safeguard against this. * <p> * Input: An extra with key <code>word</code> that contains the word * that should be added to the dictionary. * <p> * Output: Nothing. * * @hide */ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String ACTION_USER_DICTIONARY_INSERT = "com.android.settings.USER_DICTIONARY_INSERT"; /** * Activity Action: Show settings to allow configuration of application-related settings. * <p> Loading Loading @@ -1462,6 +1480,7 @@ public final class Settings { * @hide * @deprecated */ @Deprecated public static final String NOTIFICATIONS_USE_RING_VOLUME = "notifications_use_ring_volume"; Loading
core/java/android/widget/TextView.java +53 −44 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import android.content.ClipData; import android.content.ClipData.Item; import android.content.ClipboardManager; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.content.res.ColorStateList; import android.content.res.Resources; Loading @@ -42,6 +43,7 @@ import android.os.Message; import android.os.Parcel; import android.os.Parcelable; import android.os.SystemClock; import android.provider.Settings; import android.text.BoringLayout; import android.text.DynamicLayout; import android.text.Editable; Loading Loading @@ -9417,7 +9419,6 @@ 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 NO_SUGGESTIONS = -1; private static final float AVERAGE_HIGHLIGHTS_PER_SUGGESTION = 1.4f; private WordIterator mSuggestionWordIterator; private TextAppearanceSpan[] mHighlightSpans = new TextAppearanceSpan Loading Loading @@ -9472,9 +9473,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener listView.setOnItemClickListener(this); mContentView = listView; // Inflate the suggestion items once and for all. mSuggestionInfos = new SuggestionInfo[MAX_NUMBER_SUGGESTIONS]; for (int i = 0; i < MAX_NUMBER_SUGGESTIONS; i++) { // 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++) { mSuggestionInfos[i] = new SuggestionInfo(); } } Loading @@ -9485,6 +9486,15 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener SuggestionSpan suggestionSpan; // the SuggestionSpan that this TextView represents int suggestionIndex; // the index of the suggestion inside suggestionSpan SpannableStringBuilder text = new SpannableStringBuilder(); void removeMisspelledFlag() { int suggestionSpanFlags = suggestionSpan.getFlags(); if ((suggestionSpanFlags & SuggestionSpan.FLAG_MISSPELLED) > 0) { suggestionSpanFlags &= ~(SuggestionSpan.FLAG_MISSPELLED); suggestionSpanFlags &= ~(SuggestionSpan.FLAG_EASY_CORRECT); suggestionSpan.setFlags(suggestionSpanFlags); } } } private class SuggestionAdapter extends BaseAdapter { Loading Loading @@ -9623,6 +9633,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener int spanUnionStart = mText.length(); int spanUnionEnd = 0; SuggestionSpan misspelledSpan = null; for (int spanIndex = 0; spanIndex < nbSpans; spanIndex++) { SuggestionSpan suggestionSpan = suggestionSpans[spanIndex]; final int spanStart = spannable.getSpanStart(suggestionSpan); Loading @@ -9630,6 +9642,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener spanUnionStart = Math.min(spanStart, spanUnionStart); spanUnionEnd = Math.max(spanEnd, spanUnionEnd); if ((suggestionSpan.getFlags() & SuggestionSpan.FLAG_MISSPELLED) != 0) { misspelledSpan = suggestionSpan; } String[] suggestions = suggestionSpan.getSuggestions(); int nbSuggestions = suggestions.length; for (int suggestionIndex = 0; suggestionIndex < nbSuggestions; suggestionIndex++) { Loading @@ -9638,7 +9654,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener suggestionInfo.spanEnd = spanEnd; suggestionInfo.suggestionSpan = suggestionSpan; suggestionInfo.suggestionIndex = suggestionIndex; suggestionInfo.text = new SpannableStringBuilder(suggestions[suggestionIndex]); suggestionInfo.text.replace(0, suggestionInfo.text.length(), suggestions[suggestionIndex]); mNumberOfSuggestions++; if (mNumberOfSuggestions == MAX_NUMBER_SUGGESTIONS) { Loading @@ -9649,41 +9666,38 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } } for (int i = 0; i < mNumberOfSuggestions; i++) { highlightTextDifferences(mSuggestionInfos[i], spanUnionStart, spanUnionEnd); } 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.spanStart = misspelledStart; suggestionInfo.spanEnd = misspelledEnd; suggestionInfo.suggestionSpan = misspelledSpan; suggestionInfo.suggestionIndex = -1; suggestionInfo.text.replace(0, suggestionInfo.text.length(), getContext().getString(com.android.internal.R.string.addToDictionary)); mNumberOfSuggestions++; } } if (mNumberOfSuggestions == 0) return false; if (mSuggestionRangeSpan == null) mSuggestionRangeSpan = new SuggestionRangeSpan(mHighlightColor); ((Editable) mText).setSpan(mSuggestionRangeSpan, spanUnionStart, spanUnionEnd, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); for (int i = 0; i < mNumberOfSuggestions; i++) { highlightTextDifferences(mSuggestionInfos[i], spanUnionStart, spanUnionEnd); } mSuggestionsAdapter.notifyDataSetChanged(); return true; } private void onDictionarySuggestionsReceived(String[] suggestions) { if (suggestions.length == 0) { // TODO Actual implementation of this feature suggestions = new String[] {"Add to dictionary"}; } WordIterator wordIterator = getWordIterator(); wordIterator.setCharSequence(mText); final int pos = getSelectionStart(); int wordStart = wordIterator.getBeginning(pos); int wordEnd = wordIterator.getEnd(pos); SuggestionSpan suggestionSpan = new SuggestionSpan(getContext(), suggestions, 0); ((Editable) mText).setSpan(suggestionSpan, wordStart, wordEnd, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); show(); } private long[] getWordLimits(CharSequence text) { // TODO locale for mSuggestionWordIterator if (mSuggestionWordIterator == null) mSuggestionWordIterator = new WordIterator(); Loading Loading @@ -9836,10 +9850,19 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener public void onItemClick(AdapterView<?> parent, View view, int position, long id) { if (view instanceof TextView) { TextView textView = (TextView) view; SuggestionInfo suggestionInfo = mSuggestionInfos[position]; final int spanStart = suggestionInfo.spanStart; final int spanEnd = suggestionInfo.spanEnd; if (spanStart != NO_SUGGESTIONS) { final String originalText = mText.subSequence(spanStart, spanEnd).toString(); if (suggestionInfo.suggestionIndex < 0) { Intent intent = new Intent(Settings.ACTION_USER_DICTIONARY_INSERT); intent.putExtra("word", originalText); intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK); getContext().startActivity(intent); suggestionInfo.removeMisspelledFlag(); } else { // SuggestionSpans are removed by replace: save them before Editable editable = (Editable) mText; SuggestionSpan[] suggestionSpans = editable.getSpans(spanStart, spanEnd, Loading @@ -9859,17 +9882,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener final int suggestionEnd = suggestionInfo.suggestionEnd; final String suggestion = textView.getText().subSequence( suggestionStart, suggestionEnd).toString(); final String originalText = mText.subSequence(spanStart, spanEnd).toString(); editable.replace(spanStart, spanEnd, suggestion); // A replacement on a misspelled text removes the misspelled flag. // TODO restore the flag if the misspelled word is selected back? int suggestionSpanFlags = suggestionInfo.suggestionSpan.getFlags(); if ((suggestionSpanFlags & SuggestionSpan.FLAG_MISSPELLED) > 0) { suggestionSpanFlags &= ~(SuggestionSpan.FLAG_MISSPELLED); suggestionSpanFlags &= ~(SuggestionSpan.FLAG_EASY_CORRECT); suggestionInfo.suggestionSpan.setFlags(suggestionSpanFlags); } suggestionInfo.removeMisspelledFlag(); // Notify source IME of the suggestion pick. Do this before swaping texts. if (!TextUtils.isEmpty( Loading Loading @@ -9916,12 +9931,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener return mSuggestionsPopupWindow != null && mSuggestionsPopupWindow.isShowing(); } void onDictionarySuggestionsReceived(String[] suggestions) { if (mSuggestionsPopupWindow != null) { mSuggestionsPopupWindow.onDictionarySuggestionsReceived(suggestions); } } /** * Return whether or not suggestions are enabled on this TextView. The suggestions are generated * by the IME or by the spell checker as the user types. This is done by adding Loading
core/res/res/values/strings.xml +3 −0 Original line number Diff line number Diff line Loading @@ -2484,6 +2484,9 @@ <!-- Text selection contextual mode title, displayed in the CAB. [CHAR LIMIT=20] --> <string name="textSelectionCABTitle">Text selection</string> <!-- Option to add the current misspelled word to the user dictionary. [CHAR LIMIT=25] --> <string name="addToDictionary">+ add to dictionary</string> <!-- EditText context menu --> <string name="inputMethod">Input method</string> Loading
core/java/android/text/TextUtils.java +1 −1 File changed.Contains only whitespace changes. Show changes