Merge "Add API to differentiate grammar suggestions."
This commit is contained in:
committed by
Android (Google) Code Review
commit
95733e3cb5
@@ -50874,6 +50874,7 @@ package android.text.style {
|
||||
field @NonNull public static final android.os.Parcelable.Creator<android.text.style.SuggestionSpan> CREATOR;
|
||||
field public static final int FLAG_AUTO_CORRECTION = 4; // 0x4
|
||||
field public static final int FLAG_EASY_CORRECT = 1; // 0x1
|
||||
field public static final int FLAG_GRAMMAR_ERROR = 8; // 0x8
|
||||
field public static final int FLAG_MISSPELLED = 2; // 0x2
|
||||
field public static final int SUGGESTIONS_MAX_SIZE = 5; // 0x5
|
||||
field @Deprecated public static final String SUGGESTION_SPAN_PICKED_AFTER = "after";
|
||||
@@ -58248,6 +58249,7 @@ package android.view.textservice {
|
||||
field @NonNull public static final android.os.Parcelable.Creator<android.view.textservice.SuggestionsInfo> CREATOR;
|
||||
field public static final int RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS = 4; // 0x4
|
||||
field public static final int RESULT_ATTR_IN_THE_DICTIONARY = 1; // 0x1
|
||||
field public static final int RESULT_ATTR_LOOKS_LIKE_GRAMMAR_ERROR = 8; // 0x8
|
||||
field public static final int RESULT_ATTR_LOOKS_LIKE_TYPO = 2; // 0x2
|
||||
}
|
||||
|
||||
|
||||
@@ -70,6 +70,12 @@ public class SuggestionSpan extends CharacterStyle implements ParcelableSpan {
|
||||
*/
|
||||
public static final int FLAG_AUTO_CORRECTION = 0x0004;
|
||||
|
||||
/**
|
||||
* Sets this flag if the suggestions apply to a grammar error. This type of suggestion is
|
||||
* rendered differently to highlight the error.
|
||||
*/
|
||||
public static final int FLAG_GRAMMAR_ERROR = 0x0008;
|
||||
|
||||
/**
|
||||
* This action is deprecated in {@link android.os.Build.VERSION_CODES#Q}.
|
||||
*
|
||||
@@ -136,6 +142,9 @@ public class SuggestionSpan extends CharacterStyle implements ParcelableSpan {
|
||||
private float mAutoCorrectionUnderlineThickness;
|
||||
private int mAutoCorrectionUnderlineColor;
|
||||
|
||||
private float mGrammarErrorUnderlineThickness;
|
||||
private int mGrammarErrorUnderlineColor;
|
||||
|
||||
/**
|
||||
* @param context Context for the application
|
||||
* @param suggestions Suggestions for the string under the span
|
||||
@@ -190,9 +199,11 @@ public class SuggestionSpan extends CharacterStyle implements ParcelableSpan {
|
||||
private void initStyle(Context context) {
|
||||
if (context == null) {
|
||||
mMisspelledUnderlineThickness = 0;
|
||||
mGrammarErrorUnderlineThickness = 0;
|
||||
mEasyCorrectUnderlineThickness = 0;
|
||||
mAutoCorrectionUnderlineThickness = 0;
|
||||
mMisspelledUnderlineColor = Color.BLACK;
|
||||
mGrammarErrorUnderlineColor = Color.BLACK;
|
||||
mEasyCorrectUnderlineColor = Color.BLACK;
|
||||
mAutoCorrectionUnderlineColor = Color.BLACK;
|
||||
return;
|
||||
@@ -206,6 +217,14 @@ public class SuggestionSpan extends CharacterStyle implements ParcelableSpan {
|
||||
mMisspelledUnderlineColor = typedArray.getColor(
|
||||
com.android.internal.R.styleable.SuggestionSpan_textUnderlineColor, Color.BLACK);
|
||||
|
||||
defStyleAttr = com.android.internal.R.attr.textAppearanceGrammarErrorSuggestion;
|
||||
typedArray = context.obtainStyledAttributes(
|
||||
null, com.android.internal.R.styleable.SuggestionSpan, defStyleAttr, 0);
|
||||
mGrammarErrorUnderlineThickness = typedArray.getDimension(
|
||||
com.android.internal.R.styleable.SuggestionSpan_textUnderlineThickness, 0);
|
||||
mGrammarErrorUnderlineColor = typedArray.getColor(
|
||||
com.android.internal.R.styleable.SuggestionSpan_textUnderlineColor, Color.BLACK);
|
||||
|
||||
defStyleAttr = com.android.internal.R.attr.textAppearanceEasyCorrectSuggestion;
|
||||
typedArray = context.obtainStyledAttributes(
|
||||
null, com.android.internal.R.styleable.SuggestionSpan, defStyleAttr, 0);
|
||||
@@ -235,6 +254,8 @@ public class SuggestionSpan extends CharacterStyle implements ParcelableSpan {
|
||||
mMisspelledUnderlineThickness = src.readFloat();
|
||||
mAutoCorrectionUnderlineColor = src.readInt();
|
||||
mAutoCorrectionUnderlineThickness = src.readFloat();
|
||||
mGrammarErrorUnderlineColor = src.readInt();
|
||||
mGrammarErrorUnderlineThickness = src.readFloat();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -313,6 +334,8 @@ public class SuggestionSpan extends CharacterStyle implements ParcelableSpan {
|
||||
dest.writeFloat(mMisspelledUnderlineThickness);
|
||||
dest.writeInt(mAutoCorrectionUnderlineColor);
|
||||
dest.writeFloat(mAutoCorrectionUnderlineThickness);
|
||||
dest.writeInt(mGrammarErrorUnderlineColor);
|
||||
dest.writeFloat(mGrammarErrorUnderlineThickness);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -362,13 +385,19 @@ public class SuggestionSpan extends CharacterStyle implements ParcelableSpan {
|
||||
final boolean misspelled = (mFlags & FLAG_MISSPELLED) != 0;
|
||||
final boolean easy = (mFlags & FLAG_EASY_CORRECT) != 0;
|
||||
final boolean autoCorrection = (mFlags & FLAG_AUTO_CORRECTION) != 0;
|
||||
final boolean grammarError = (mFlags & FLAG_GRAMMAR_ERROR) != 0;
|
||||
if (easy) {
|
||||
if (!misspelled) {
|
||||
if (!misspelled && !grammarError) {
|
||||
tp.setUnderlineText(mEasyCorrectUnderlineColor, mEasyCorrectUnderlineThickness);
|
||||
} else if (tp.underlineColor == 0) {
|
||||
// Spans are rendered in an arbitrary order. Since misspelled is less prioritary
|
||||
// than just easy, do not apply misspelled if an easy (or a mispelled) has been set
|
||||
tp.setUnderlineText(mMisspelledUnderlineColor, mMisspelledUnderlineThickness);
|
||||
if (grammarError) {
|
||||
tp.setUnderlineText(
|
||||
mGrammarErrorUnderlineColor, mGrammarErrorUnderlineThickness);
|
||||
} else {
|
||||
tp.setUnderlineText(mMisspelledUnderlineColor, mMisspelledUnderlineThickness);
|
||||
}
|
||||
}
|
||||
} else if (autoCorrection) {
|
||||
tp.setUnderlineText(mAutoCorrectionUnderlineColor, mAutoCorrectionUnderlineThickness);
|
||||
@@ -384,11 +413,14 @@ public class SuggestionSpan extends CharacterStyle implements ParcelableSpan {
|
||||
final boolean misspelled = (mFlags & FLAG_MISSPELLED) != 0;
|
||||
final boolean easy = (mFlags & FLAG_EASY_CORRECT) != 0;
|
||||
final boolean autoCorrection = (mFlags & FLAG_AUTO_CORRECTION) != 0;
|
||||
final boolean grammarError = (mFlags & FLAG_GRAMMAR_ERROR) != 0;
|
||||
if (easy) {
|
||||
if (!misspelled) {
|
||||
return mEasyCorrectUnderlineColor;
|
||||
} else {
|
||||
if (grammarError) {
|
||||
return mGrammarErrorUnderlineColor;
|
||||
} else if (misspelled) {
|
||||
return mMisspelledUnderlineColor;
|
||||
} else {
|
||||
return mEasyCorrectUnderlineColor;
|
||||
}
|
||||
} else if (autoCorrection) {
|
||||
return mAutoCorrectionUnderlineColor;
|
||||
|
||||
@@ -45,6 +45,14 @@ public final class SuggestionsInfo implements Parcelable {
|
||||
* the result suggestions include highly recommended ones.
|
||||
*/
|
||||
public static final int RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS = 0x0004;
|
||||
|
||||
/**
|
||||
* Flag of the attributes of the suggestions that can be obtained by
|
||||
* {@link #getSuggestionsAttributes}: this tells that the text service thinks the requested
|
||||
* sentence contains a grammar error.
|
||||
*/
|
||||
public static final int RESULT_ATTR_LOOKS_LIKE_GRAMMAR_ERROR = 0x0008;
|
||||
|
||||
private final int mSuggestionsAttributes;
|
||||
private final String[] mSuggestions;
|
||||
private final boolean mSuggestionsAvailable;
|
||||
|
||||
@@ -186,6 +186,9 @@ public class Editor {
|
||||
private static final int MENU_ITEM_ORDER_SECONDARY_ASSIST_ACTIONS_START = 50;
|
||||
private static final int MENU_ITEM_ORDER_PROCESS_TEXT_INTENT_ACTIONS_START = 100;
|
||||
|
||||
private static final int FLAG_MISSPELLED_OR_GRAMMAR_ERROR =
|
||||
SuggestionSpan.FLAG_MISSPELLED | SuggestionSpan.FLAG_GRAMMAR_ERROR;
|
||||
|
||||
@IntDef({MagnifierHandleTrigger.SELECTION_START,
|
||||
MagnifierHandleTrigger.SELECTION_END,
|
||||
MagnifierHandleTrigger.INSERTION})
|
||||
@@ -1552,7 +1555,7 @@ public class Editor {
|
||||
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) {
|
||||
&& (flags & FLAG_MISSPELLED_OR_GRAMMAR_ERROR) == 0) {
|
||||
flags &= ~SuggestionSpan.FLAG_EASY_CORRECT;
|
||||
suggestionSpans[i].setFlags(flags);
|
||||
}
|
||||
@@ -3064,8 +3067,9 @@ public class Editor {
|
||||
|
||||
// Remove potential misspelled flags
|
||||
int suggestionSpanFlags = suggestionSpan.getFlags();
|
||||
if ((suggestionSpanFlags & SuggestionSpan.FLAG_MISSPELLED) != 0) {
|
||||
if ((suggestionSpanFlags & FLAG_MISSPELLED_OR_GRAMMAR_ERROR) != 0) {
|
||||
suggestionSpanFlags &= ~SuggestionSpan.FLAG_MISSPELLED;
|
||||
suggestionSpanFlags &= ~SuggestionSpan.FLAG_GRAMMAR_ERROR;
|
||||
suggestionSpanFlags &= ~SuggestionSpan.FLAG_EASY_CORRECT;
|
||||
suggestionSpan.setFlags(suggestionSpanFlags);
|
||||
}
|
||||
@@ -3601,19 +3605,29 @@ public class Editor {
|
||||
final int flag1 = span1.getFlags();
|
||||
final int flag2 = span2.getFlags();
|
||||
if (flag1 != flag2) {
|
||||
// The order here should match what is used in updateDrawState
|
||||
final boolean easy1 = (flag1 & SuggestionSpan.FLAG_EASY_CORRECT) != 0;
|
||||
final boolean easy2 = (flag2 & SuggestionSpan.FLAG_EASY_CORRECT) != 0;
|
||||
final boolean misspelled1 = (flag1 & SuggestionSpan.FLAG_MISSPELLED) != 0;
|
||||
final boolean misspelled2 = (flag2 & SuggestionSpan.FLAG_MISSPELLED) != 0;
|
||||
if (easy1 && !misspelled1) return -1;
|
||||
if (easy2 && !misspelled2) return 1;
|
||||
if (misspelled1) return -1;
|
||||
if (misspelled2) return 1;
|
||||
// Compare so that the order will be: easy -> misspelled -> grammarError
|
||||
int easy = compareFlag(SuggestionSpan.FLAG_EASY_CORRECT, flag1, flag2);
|
||||
if (easy != 0) return easy;
|
||||
int misspelled = compareFlag(SuggestionSpan.FLAG_MISSPELLED, flag1, flag2);
|
||||
if (misspelled != 0) return misspelled;
|
||||
int grammarError = compareFlag(SuggestionSpan.FLAG_GRAMMAR_ERROR, flag1, flag2);
|
||||
if (grammarError != 0) return grammarError;
|
||||
}
|
||||
|
||||
return mSpansLengths.get(span1).intValue() - mSpansLengths.get(span2).intValue();
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns -1 if flags1 has flagToCompare but flags2 does not.
|
||||
* Returns 1 if flags2 has flagToCompare but flags1 does not.
|
||||
* Otherwise, returns 0.
|
||||
*/
|
||||
private int compareFlag(int flagToCompare, int flags1, int flags2) {
|
||||
boolean hasFlag1 = (flags1 & flagToCompare) != 0;
|
||||
boolean hasFlag2 = (flags2 & flagToCompare) != 0;
|
||||
if (hasFlag1 == hasFlag2) return 0;
|
||||
return hasFlag1 ? -1 : 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3632,8 +3646,9 @@ public class Editor {
|
||||
mSpansLengths.put(suggestionSpan, Integer.valueOf(end - start));
|
||||
}
|
||||
|
||||
// The suggestions are sorted according to their types (easy correction first, then
|
||||
// misspelled) and to the length of the text that they cover (shorter first).
|
||||
// The suggestions are sorted according to their types (easy correction first,
|
||||
// misspelled second, then grammar error) and to the length of the text that they cover
|
||||
// (shorter first).
|
||||
Arrays.sort(suggestionSpans, mSuggestionSpanComparator);
|
||||
mSpansLengths.clear();
|
||||
|
||||
@@ -3661,7 +3676,7 @@ public class Editor {
|
||||
final int spanEnd = spannable.getSpanEnd(suggestionSpan);
|
||||
|
||||
if (misspelledSpanInfo != null
|
||||
&& (suggestionSpan.getFlags() & SuggestionSpan.FLAG_MISSPELLED) != 0) {
|
||||
&& (suggestionSpan.getFlags() & FLAG_MISSPELLED_OR_GRAMMAR_ERROR) != 0) {
|
||||
misspelledSpanInfo.mSuggestionSpan = suggestionSpan;
|
||||
misspelledSpanInfo.mSpanStart = spanStart;
|
||||
misspelledSpanInfo.mSpanEnd = spanEnd;
|
||||
|
||||
@@ -338,11 +338,13 @@ public class SpellChecker implements SpellCheckerSessionListener {
|
||||
((attributes & SuggestionsInfo.RESULT_ATTR_IN_THE_DICTIONARY) > 0);
|
||||
final boolean looksLikeTypo =
|
||||
((attributes & SuggestionsInfo.RESULT_ATTR_LOOKS_LIKE_TYPO) > 0);
|
||||
final boolean looksLikeGrammarError =
|
||||
((attributes & SuggestionsInfo.RESULT_ATTR_LOOKS_LIKE_GRAMMAR_ERROR) > 0);
|
||||
|
||||
final SpellCheckSpan spellCheckSpan = mSpellCheckSpans[k];
|
||||
//TODO: we need to change that rule for results from a sentence-level spell
|
||||
// checker that will probably be in dictionary.
|
||||
if (!isInDictionary && looksLikeTypo) {
|
||||
if (!isInDictionary && (looksLikeTypo || looksLikeGrammarError)) {
|
||||
createMisspelledSuggestionSpan(
|
||||
editable, suggestionsInfo, spellCheckSpan, offset, length);
|
||||
} else {
|
||||
@@ -482,8 +484,16 @@ public class SpellChecker implements SpellCheckerSessionListener {
|
||||
suggestions = ArrayUtils.emptyArray(String.class);
|
||||
}
|
||||
|
||||
SuggestionSpan suggestionSpan = new SuggestionSpan(mTextView.getContext(), suggestions,
|
||||
SuggestionSpan.FLAG_EASY_CORRECT | SuggestionSpan.FLAG_MISSPELLED);
|
||||
final int suggestionsAttrs = suggestionsInfo.getSuggestionsAttributes();
|
||||
int flags = SuggestionSpan.FLAG_EASY_CORRECT;
|
||||
if ((suggestionsAttrs & SuggestionsInfo.RESULT_ATTR_LOOKS_LIKE_TYPO) != 0) {
|
||||
flags |= SuggestionSpan.FLAG_MISSPELLED;
|
||||
}
|
||||
if ((suggestionsAttrs & SuggestionsInfo.RESULT_ATTR_LOOKS_LIKE_GRAMMAR_ERROR) != 0) {
|
||||
flags |= SuggestionSpan.FLAG_GRAMMAR_ERROR;
|
||||
}
|
||||
SuggestionSpan suggestionSpan =
|
||||
new SuggestionSpan(mTextView.getContext(), suggestions, flags);
|
||||
// TODO: Remove mIsSentenceSpellCheckSupported by extracting an interface
|
||||
// to share the logic of word level spell checker and sentence level spell checker
|
||||
if (mIsSentenceSpellCheckSupported) {
|
||||
|
||||
@@ -199,6 +199,9 @@
|
||||
<!-- The underline color and thickness for auto correction suggestion -->
|
||||
<attr name="textAppearanceAutoCorrectionSuggestion" format="reference" />
|
||||
|
||||
<!-- The underline color and thickness for grammar error suggestion -->
|
||||
<attr name="textAppearanceGrammarErrorSuggestion" format="reference" />
|
||||
|
||||
<!-- The underline color -->
|
||||
<attr name="textUnderlineColor" format="reference|color" />
|
||||
<!-- The underline thickness -->
|
||||
|
||||
@@ -306,6 +306,10 @@ please see styles_device_defaults.xml.
|
||||
<item name="textUnderlineColor">@color/holo_blue_light</item>
|
||||
</style>
|
||||
|
||||
<style name="TextAppearance.GrammarErrorSuggestion" parent="TextAppearance.Suggestion">
|
||||
<item name="textUnderlineColor">@color/holo_blue_light</item>
|
||||
</style>
|
||||
|
||||
<!-- Widget Styles -->
|
||||
|
||||
<style name="Widget">
|
||||
|
||||
@@ -263,6 +263,7 @@
|
||||
<java-symbol type="attr" name="searchDialogTheme" />
|
||||
<java-symbol type="attr" name="textAppearanceAutoCorrectionSuggestion" />
|
||||
<java-symbol type="attr" name="textAppearanceEasyCorrectSuggestion" />
|
||||
<java-symbol type="attr" name="textAppearanceGrammarErrorSuggestion" />
|
||||
<java-symbol type="attr" name="textAppearanceMisspelledSuggestion" />
|
||||
<java-symbol type="attr" name="textColorSearchUrl" />
|
||||
<java-symbol type="attr" name="timePickerStyle" />
|
||||
|
||||
@@ -93,6 +93,7 @@ please see themes_device_defaults.xml.
|
||||
<item name="textAppearanceEasyCorrectSuggestion">@style/TextAppearance.EasyCorrectSuggestion</item>
|
||||
<item name="textAppearanceMisspelledSuggestion">@style/TextAppearance.MisspelledSuggestion</item>
|
||||
<item name="textAppearanceAutoCorrectionSuggestion">@style/TextAppearance.AutoCorrectionSuggestion</item>
|
||||
<item name="textAppearanceGrammarErrorSuggestion">@style/TextAppearance.GrammarErrorSuggestion</item>
|
||||
|
||||
<item name="textAppearanceButton">@style/TextAppearance.Widget.Button</item>
|
||||
|
||||
|
||||
@@ -49010,6 +49010,7 @@ package android.text.style {
|
||||
field @NonNull public static final android.os.Parcelable.Creator<android.text.style.SuggestionSpan> CREATOR;
|
||||
field public static final int FLAG_AUTO_CORRECTION = 4; // 0x4
|
||||
field public static final int FLAG_EASY_CORRECT = 1; // 0x1
|
||||
field public static final int FLAG_GRAMMAR_ERROR = 8; // 0x8
|
||||
field public static final int FLAG_MISSPELLED = 2; // 0x2
|
||||
field public static final int SUGGESTIONS_MAX_SIZE = 5; // 0x5
|
||||
field @Deprecated public static final String SUGGESTION_SPAN_PICKED_AFTER = "after";
|
||||
@@ -56377,6 +56378,7 @@ package android.view.textservice {
|
||||
field @NonNull public static final android.os.Parcelable.Creator<android.view.textservice.SuggestionsInfo> CREATOR;
|
||||
field public static final int RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS = 4; // 0x4
|
||||
field public static final int RESULT_ATTR_IN_THE_DICTIONARY = 1; // 0x1
|
||||
field public static final int RESULT_ATTR_LOOKS_LIKE_GRAMMAR_ERROR = 8; // 0x8
|
||||
field public static final int RESULT_ATTR_LOOKS_LIKE_TYPO = 2; // 0x2
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user