Fix a bug where changing languages kills the composition.

Bug: 14926896
Change-Id: Id2a06c68a51f833db4d8bbc858a232c2696afb6e
main
Jean Chalard 2014-05-14 20:19:16 +09:00
parent 71f4c6b8ea
commit 5ce39dfa78
5 changed files with 30 additions and 15 deletions

View File

@ -56,18 +56,20 @@ public class CombinerChain {
* *
* The combiner chain takes events as inputs and outputs code points and combining state. * The combiner chain takes events as inputs and outputs code points and combining state.
* For example, if the input language is Japanese, the combining chain will typically perform * For example, if the input language is Japanese, the combining chain will typically perform
* kana conversion. * kana conversion. This takes a string for initial text, taken to be present before the
* cursor: we'll start after this.
* *
* @param initialText The text that has already been combined so far.
* @param combinerList A list of combiners to be applied in order. * @param combinerList A list of combiners to be applied in order.
*/ */
public CombinerChain(final Combiner... combinerList) { public CombinerChain(final String initialText, final Combiner... combinerList) {
mCombiners = CollectionUtils.newArrayList(); mCombiners = CollectionUtils.newArrayList();
// The dead key combiner is always active, and always first // The dead key combiner is always active, and always first
mCombiners.add(new DeadKeyCombiner()); mCombiners.add(new DeadKeyCombiner());
for (final Combiner combiner : combinerList) { for (final Combiner combiner : combinerList) {
mCombiners.add(combiner); mCombiners.add(combiner);
} }
mCombinedText = new StringBuilder(); mCombinedText = new StringBuilder(initialText);
mStateFeedback = new SpannableStringBuilder(); mStateFeedback = new SpannableStringBuilder();
} }

View File

@ -80,7 +80,7 @@ public final class WordComposer {
private boolean mIsFirstCharCapitalized; private boolean mIsFirstCharCapitalized;
public WordComposer() { public WordComposer() {
mCombinerChain = new CombinerChain(); mCombinerChain = new CombinerChain("");
mEvents = CollectionUtils.newArrayList(); mEvents = CollectionUtils.newArrayList();
mAutoCorrection = null; mAutoCorrection = null;
mIsResumed = false; mIsResumed = false;
@ -92,18 +92,17 @@ public final class WordComposer {
} }
/** /**
* Restart input with a new combining spec. * Restart the combiners, possibly with a new spec.
* @param combiningSpec The spec string for combining. This is found in the extra value. * @param combiningSpec The spec string for combining. This is found in the extra value.
*/ */
public void restart(final String combiningSpec) { public void restartCombining(final String combiningSpec) {
final String nonNullCombiningSpec = null == combiningSpec ? "" : combiningSpec; final String nonNullCombiningSpec = null == combiningSpec ? "" : combiningSpec;
if (nonNullCombiningSpec.equals(mCombiningSpec)) { if (!nonNullCombiningSpec.equals(mCombiningSpec)) {
mCombinerChain.reset(); mCombinerChain = new CombinerChain(
} else { mCombinerChain.getComposingWordWithCombiningFeedback().toString(),
mCombinerChain = new CombinerChain(CombinerChain.createCombiners(nonNullCombiningSpec)); CombinerChain.createCombiners(nonNullCombiningSpec));
mCombiningSpec = nonNullCombiningSpec; mCombiningSpec = nonNullCombiningSpec;
} }
reset();
} }
/** /**

View File

@ -127,7 +127,7 @@ public final class InputLogic {
public void startInput(final boolean restarting, final EditorInfo editorInfo, public void startInput(final boolean restarting, final EditorInfo editorInfo,
final String combiningSpec) { final String combiningSpec) {
mEnteredText = null; mEnteredText = null;
mWordComposer.restart(combiningSpec); mWordComposer.restartCombining(combiningSpec);
resetComposingState(true /* alsoResetLastComposedWord */); resetComposingState(true /* alsoResetLastComposedWord */);
mDeleteCount = 0; mDeleteCount = 0;
mSpaceState = SpaceState.NONE; mSpaceState = SpaceState.NONE;
@ -150,7 +150,7 @@ public final class InputLogic {
* @param combiningSpec the spec string for the combining rules * @param combiningSpec the spec string for the combining rules
*/ */
public void onSubtypeChanged(final String combiningSpec) { public void onSubtypeChanged(final String combiningSpec) {
mWordComposer.restart(combiningSpec); mWordComposer.restartCombining(combiningSpec);
} }
/** /**

View File

@ -600,4 +600,16 @@ public class InputLogicTests extends InputTestsBase {
assertEquals("type words letter by letter", EXPECTED_RESULT, assertEquals("type words letter by letter", EXPECTED_RESULT,
mEditText.getText().toString()); mEditText.getText().toString());
} }
public void testSwitchLanguages() {
final String WORD_TO_TYPE_FIRST_PART = "com";
final String WORD_TO_TYPE_SECOND_PART = "md ";
final String EXPECTED_RESULT = "comme ";
changeLanguage("en");
type(WORD_TO_TYPE_FIRST_PART);
changeLanguage("fr");
type(WORD_TO_TYPE_SECOND_PART);
assertEquals("Composing continues after switching languages", EXPECTED_RESULT,
mEditText.getText().toString());
}
} }

View File

@ -28,8 +28,10 @@ import java.util.ArrayList;
// TODO: there should not be a dependency to this in dicttool, so there // TODO: there should not be a dependency to this in dicttool, so there
// should be a sensible way to separate them cleanly. // should be a sensible way to separate them cleanly.
public class CombinerChain { public class CombinerChain {
private StringBuilder mComposingWord = new StringBuilder(); private StringBuilder mComposingWord;
public CombinerChain(final Combiner... combinerList) {} public CombinerChain(final String initialText, final Combiner... combinerList) {
mComposingWord = new StringBuilder(initialText);
}
public void processEvent(final ArrayList<Event> previousEvents, final Event newEvent) { public void processEvent(final ArrayList<Event> previousEvents, final Event newEvent) {
mComposingWord.append(newEvent.getTextToCommit()); mComposingWord.append(newEvent.getTextToCommit());