aboutsummaryrefslogtreecommitdiffstats
path: root/java
diff options
context:
space:
mode:
Diffstat (limited to 'java')
-rw-r--r--java/src/com/android/inputmethod/event/Combiner.java11
-rw-r--r--java/src/com/android/inputmethod/event/CombinerChain.java42
-rw-r--r--java/src/com/android/inputmethod/event/DeadKeyCombiner.java10
-rw-r--r--java/src/com/android/inputmethod/event/Event.java16
-rw-r--r--java/src/com/android/inputmethod/latin/WordComposer.java17
5 files changed, 84 insertions, 12 deletions
diff --git a/java/src/com/android/inputmethod/event/Combiner.java b/java/src/com/android/inputmethod/event/Combiner.java
index c3869a299..8b808c6b3 100644
--- a/java/src/com/android/inputmethod/event/Combiner.java
+++ b/java/src/com/android/inputmethod/event/Combiner.java
@@ -34,4 +34,15 @@ public interface Combiner {
* @return the resulting event.
*/
Event processEvent(ArrayList<Event> previousEvents, Event event);
+
+ /**
+ * Get the feedback that should be shown to the user for the current state of this combiner.
+ * @return A CharSequence representing the feedback to show users. It may include styles.
+ */
+ CharSequence getCombiningStateFeedback();
+
+ /**
+ * Reset the state of this combiner, for example when the cursor was moved.
+ */
+ void reset();
}
diff --git a/java/src/com/android/inputmethod/event/CombinerChain.java b/java/src/com/android/inputmethod/event/CombinerChain.java
index 0e01c819a..5ca9842c1 100644
--- a/java/src/com/android/inputmethod/event/CombinerChain.java
+++ b/java/src/com/android/inputmethod/event/CombinerChain.java
@@ -16,6 +16,8 @@
package com.android.inputmethod.event;
+import android.text.SpannableStringBuilder;
+
import com.android.inputmethod.latin.utils.CollectionUtils;
import java.util.ArrayList;
@@ -33,8 +35,10 @@ import java.util.ArrayList;
* a colored background.
*/
public class CombinerChain {
- // TODO: Create an object type to represent input material + visual feedback + decoding state
-
+ // The already combined text, as described above
+ private StringBuilder mCombinedText;
+ // The feedback on the composing state, as described above
+ private SpannableStringBuilder mStateFeedback;
private final ArrayList<Combiner> mCombiners;
/**
@@ -50,9 +54,23 @@ public class CombinerChain {
mCombiners = CollectionUtils.newArrayList();
// The dead key combiner is always active, and always first
mCombiners.add(new DeadKeyCombiner());
+ mCombinedText = new StringBuilder();
+ mStateFeedback = new SpannableStringBuilder();
}
- // Pass a new event through the whole chain.
+ public void reset() {
+ mCombinedText.setLength(0);
+ mStateFeedback.clear();
+ for (final Combiner c : mCombiners) {
+ c.reset();
+ }
+ }
+
+ /**
+ * Pass a new event through the whole chain.
+ * @param previousEvents the list of previous events in this composition
+ * @param newEvent the new event to process
+ */
public void processEvent(final ArrayList<Event> previousEvents, final Event newEvent) {
final ArrayList<Event> modifiablePreviousEvents = new ArrayList<Event>(previousEvents);
Event event = newEvent;
@@ -62,8 +80,24 @@ public class CombinerChain {
event = combiner.processEvent(modifiablePreviousEvents, event);
if (null == event) {
// Combiners return null if they eat the event.
- return;
+ break;
}
}
+ if (null != event) {
+ mCombinedText.append(event.getTextToCommit());
+ }
+ mStateFeedback.clear();
+ for (int i = mCombiners.size() - 1; i >= 0; --i) {
+ mStateFeedback.append(mCombiners.get(i).getCombiningStateFeedback());
+ }
+ }
+
+ /**
+ * Get the char sequence that should be displayed as the composing word. It may include
+ * styling spans.
+ */
+ public CharSequence getComposingWordWithCombiningFeedback() {
+ final SpannableStringBuilder s = new SpannableStringBuilder(mCombinedText);
+ return s.append(mStateFeedback);
}
}
diff --git a/java/src/com/android/inputmethod/event/DeadKeyCombiner.java b/java/src/com/android/inputmethod/event/DeadKeyCombiner.java
index f77ce6347..89e623a1d 100644
--- a/java/src/com/android/inputmethod/event/DeadKeyCombiner.java
+++ b/java/src/com/android/inputmethod/event/DeadKeyCombiner.java
@@ -61,4 +61,14 @@ public class DeadKeyCombiner implements Combiner {
}
}
}
+
+ @Override
+ public void reset() {
+ mDeadSequence.setLength(0);
+ }
+
+ @Override
+ public CharSequence getCombiningStateFeedback() {
+ return mDeadSequence;
+ }
}
diff --git a/java/src/com/android/inputmethod/event/Event.java b/java/src/com/android/inputmethod/event/Event.java
index db4023436..2bfe0732d 100644
--- a/java/src/com/android/inputmethod/event/Event.java
+++ b/java/src/com/android/inputmethod/event/Event.java
@@ -18,6 +18,7 @@ package com.android.inputmethod.event;
import com.android.inputmethod.latin.Constants;
import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
+import com.android.inputmethod.latin.utils.StringUtils;
/**
* Class representing a generic input event as handled by Latin IME.
@@ -223,4 +224,19 @@ public class Event {
public boolean isHandled() {
return EVENT_NOT_HANDLED != mType;
}
+
+ public CharSequence getTextToCommit() {
+ switch (mType) {
+ case EVENT_MODE_KEY:
+ case EVENT_NOT_HANDLED:
+ return "";
+ case EVENT_INPUT_KEYPRESS:
+ case EVENT_TOGGLE:
+ return StringUtils.newSingleCodePointString(mCodePoint);
+ case EVENT_GESTURE:
+ case EVENT_SOFTWARE_GENERATED_STRING:
+ return mText;
+ }
+ throw new RuntimeException("Unknown event type: " + mType);
+ }
}
diff --git a/java/src/com/android/inputmethod/latin/WordComposer.java b/java/src/com/android/inputmethod/latin/WordComposer.java
index 29382fea4..a60ca3d41 100644
--- a/java/src/com/android/inputmethod/latin/WordComposer.java
+++ b/java/src/com/android/inputmethod/latin/WordComposer.java
@@ -127,6 +127,7 @@ public final class WordComposer {
* Clear out the keys registered so far.
*/
public void reset() {
+ mCombinerChain.reset();
mTypedWord.setLength(0);
mEvents.clear();
mAutoCorrection = null;
@@ -166,13 +167,6 @@ public final class WordComposer {
return mPrimaryKeyCodes[index];
}
- public int getCodeBeforeCursor() {
- if (mCursorPositionWithinWord < 1 || mCursorPositionWithinWord > mPrimaryKeyCodes.length) {
- return Constants.NOT_A_CODE;
- }
- return mPrimaryKeyCodes[mCursorPositionWithinWord - 1];
- }
-
public InputPointers getInputPointers() {
return mInputPointers;
}
@@ -193,7 +187,10 @@ public final class WordComposer {
final int keyY = event.mY;
final int newIndex = size();
mCombinerChain.processEvent(mEvents, event);
- mTypedWord.appendCodePoint(primaryCode);
+ // TODO: remove mTypedWord and compute it dynamically when necessary. We also need to
+ // make the views of the composing word a SpannableString.
+ mTypedWord.replace(0, mTypedWord.length(),
+ mCombinerChain.getComposingWordWithCombiningFeedback().toString());
mEvents.add(event);
refreshSize();
mCursorPositionWithinWord = mCodePointSize;
@@ -243,6 +240,8 @@ public final class WordComposer {
* @return true if the cursor is still inside the composing word, false otherwise.
*/
public boolean moveCursorByAndReturnIfInsideComposingWord(final int expectedMoveAmount) {
+ // TODO: should uncommit the composing feedback
+ mCombinerChain.reset();
int actualMoveAmountWithinWord = 0;
int cursorPos = mCursorPositionWithinWord;
final int[] codePoints;
@@ -482,6 +481,7 @@ public final class WordComposer {
mIsBatchMode = false;
mPreviousWordForSuggestion = committedWord.toString();
mTypedWord.setLength(0);
+ mCombinerChain.reset();
mEvents.clear();
mCodePointSize = 0;
mTrailingSingleQuotesCount = 0;
@@ -509,6 +509,7 @@ public final class WordComposer {
Collections.copy(mEvents, lastComposedWord.mEvents);
mInputPointers.set(lastComposedWord.mInputPointers);
mTypedWord.setLength(0);
+ mCombinerChain.reset();
mTypedWord.append(lastComposedWord.mTypedWord);
refreshSize();
mCapitalizedMode = lastComposedWord.mCapitalizedMode;