Allow to add/remove background color to/from the committed text

This is a groundwork for subsequent CLs where we need to
add/remove background color to/from the commited text.

In this CL, we use Spanned#SPAN_COMPOSING so that we can easily
remove such a background color by calling
InputConnection#finishComposingText. To make this operation easy
and realiable, we need to track whether we have specified the
background color to the commited text or not at one place. Here
we use RichInputConnection for this purpose.

Change-Id: I5f9bc4425c5d1b80a719a20e5baf336729ec08d2
This commit is contained in:
Yohei Yukawa 2014-08-24 17:41:49 -07:00
parent cd6ef9a8b1
commit 4a71d2c480
2 changed files with 97 additions and 4 deletions

View file

@ -16,9 +16,13 @@
package com.android.inputmethod.latin;
import android.graphics.Color;
import android.inputmethodservice.InputMethodService;
import android.os.Build;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.TextUtils;
import android.text.style.BackgroundColorSpan;
import android.util.Log;
import android.view.KeyEvent;
import android.view.inputmethod.CompletionInfo;
@ -81,6 +85,18 @@ public final class RichInputConnection {
*/
private final StringBuilder mComposingText = new StringBuilder();
/**
* This variable is a temporary object used in
* {@link #commitTextWithBackgroundColor(CharSequence, int, int)} to avoid object creation.
*/
private SpannableStringBuilder mTempObjectForCommitText = new SpannableStringBuilder();
/**
* This variable is used to track whether the last committed text had the background color or
* not.
* TODO: Omit this flag if possible.
*/
private boolean mLastCommittedTextHasBackgroundColor = false;
private final InputMethodService mParent;
InputConnection mIC;
int mNestLevel;
@ -219,12 +235,37 @@ public final class RichInputConnection {
// it works, but it's wrong and should be fixed.
mCommittedTextBeforeComposingText.append(mComposingText);
mComposingText.setLength(0);
// TODO: Clear this flag in setComposingRegion() and setComposingText() as well if needed.
mLastCommittedTextHasBackgroundColor = false;
if (null != mIC) {
mIC.finishComposingText();
}
}
public void commitText(final CharSequence text, final int i) {
/**
* Synonym of {@code commitTextWithBackgroundColor(text, newCursorPosition, Color.TRANSPARENT}.
* @param text The text to commit. This may include styles.
* See {@link InputConnection#commitText(CharSequence, int)}.
* @param newCursorPosition The new cursor position around the text.
* See {@link InputConnection#commitText(CharSequence, int)}.
*/
public void commitText(final CharSequence text, final int newCursorPosition) {
commitTextWithBackgroundColor(text, newCursorPosition, Color.TRANSPARENT);
}
/**
* Calls {@link InputConnection#commitText(CharSequence, int)} with the given background color.
* @param text The text to commit. This may include styles.
* See {@link InputConnection#commitText(CharSequence, int)}.
* @param newCursorPosition The new cursor position around the text.
* See {@link InputConnection#commitText(CharSequence, int)}.
* @param color The background color to be attached. Set {@link Color#TRANSPARENT} to disable
* the background color. Note that this method specifies {@link BackgroundColorSpan} with
* {@link Spanned#SPAN_COMPOSING} flag, meaning that the background color persists until
* {@link #finishComposingText()} is called.
*/
public void commitTextWithBackgroundColor(final CharSequence text, final int newCursorPosition,
final int color) {
if (DEBUG_BATCH_NESTING) checkBatchEdit();
if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug();
mCommittedTextBeforeComposingText.append(text);
@ -234,10 +275,42 @@ public final class RichInputConnection {
mExpectedSelStart += text.length() - mComposingText.length();
mExpectedSelEnd = mExpectedSelStart;
mComposingText.setLength(0);
mLastCommittedTextHasBackgroundColor = false;
if (null != mIC) {
mIC.commitText(text, i);
if (color == Color.TRANSPARENT) {
mIC.commitText(text, newCursorPosition);
} else {
mTempObjectForCommitText.clear();
mTempObjectForCommitText.append(text);
final BackgroundColorSpan backgroundColorSpan = new BackgroundColorSpan(color);
mTempObjectForCommitText.setSpan(backgroundColorSpan, 0, text.length(),
Spanned.SPAN_COMPOSING | Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
mIC.commitText(mTempObjectForCommitText, newCursorPosition);
mLastCommittedTextHasBackgroundColor = true;
}
}
}
/**
* Removes the background color from the highlighted text if necessary. Should be called while
* there is no on-going composing text.
*
* <p>CAVEAT: This method internally calls {@link InputConnection#finishComposingText()}.
* Be careful of any unexpected side effects.</p>
*/
public void removeBackgroundColorFromHighlightedTextIfNecessary() {
// TODO: We haven't yet full tested if we really need to check this flag or not. Omit this
// flag if everything works fine without this condition.
if (!mLastCommittedTextHasBackgroundColor) {
return;
}
if (mComposingText.length() > 0) {
Log.e(TAG, "clearSpansWithComposingFlags should be called when composing text is " +
"empty. mComposingText=" + mComposingText);
return;
}
finishComposingText();
}
public CharSequence getSelectedText(final int flags) {
return (null == mIC) ? null : mIC.getSelectedText(flags);

View file

@ -16,6 +16,7 @@
package com.android.inputmethod.latin.inputlogic;
import android.graphics.Color;
import android.os.SystemClock;
import android.text.SpannableString;
import android.text.TextUtils;
@ -1994,7 +1995,9 @@ public final class InputLogic {
}
/**
* Commits the chosen word to the text field and saves it for later retrieval.
* Commits the chosen word to the text field and saves it for later retrieval. This is a
* synonym of {@code commitChosenWordWithBackgroundColor(settingsValues, chosenWord,
* commitType, separatorString, Color.TRANSPARENT}.
*
* @param settingsValues the current values of the settings.
* @param chosenWord the word we want to commit.
@ -2003,6 +2006,23 @@ public final class InputLogic {
*/
private void commitChosenWord(final SettingsValues settingsValues, final String chosenWord,
final int commitType, final String separatorString) {
commitChosenWordWithBackgroundColor(settingsValues, chosenWord, commitType, separatorString,
Color.TRANSPARENT);
}
/**
* Commits the chosen word to the text field and saves it for later retrieval.
*
* @param settingsValues the current values of the settings.
* @param chosenWord the word we want to commit.
* @param commitType the type of the commit, as one of LastComposedWord.COMMIT_TYPE_*
* @param separatorString the separator that's causing the commit, or NOT_A_SEPARATOR if none.
* @param backgroundColor the background color to be specified with the committed text. Pass
* {@link Color#TRANSPARENT} to not specify the background color.
*/
private void commitChosenWordWithBackgroundColor(final SettingsValues settingsValues,
final String chosenWord, final int commitType, final String separatorString,
final int backgroundColor) {
final SuggestedWords suggestedWords = mSuggestedWords;
final CharSequence chosenWordWithSuggestions =
SuggestionSpanUtils.getTextWithSuggestionSpan(mLatinIME, chosenWord,
@ -2012,7 +2032,7 @@ public final class InputLogic {
// information from the 1st previous word.
final PrevWordsInfo prevWordsInfo = mConnection.getPrevWordsInfoFromNthPreviousWord(
settingsValues.mSpacingAndPunctuations, mWordComposer.isComposingWord() ? 2 : 1);
mConnection.commitText(chosenWordWithSuggestions, 1);
mConnection.commitTextWithBackgroundColor(chosenWordWithSuggestions, 1, backgroundColor);
// Add the word to the user history dictionary
performAdditionToUserHistoryDictionary(settingsValues, chosenWord, prevWordsInfo);
// TODO: figure out here if this is an auto-correct or if the best word is actually