aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--java/src/com/android/inputmethod/keyboard/Key.java4
-rw-r--r--java/src/com/android/inputmethod/keyboard/MiniKeyboard.java14
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyStyles.java102
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/MoreKeySpecParser.java26
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java8
-rw-r--r--tests/src/com/android/inputmethod/keyboard/internal/KeyStylesTests.java7
-rw-r--r--tests/src/com/android/inputmethod/latin/InputLogicTests.java106
7 files changed, 185 insertions, 82 deletions
diff --git a/java/src/com/android/inputmethod/keyboard/Key.java b/java/src/com/android/inputmethod/keyboard/Key.java
index ebd61505d..6003d9723 100644
--- a/java/src/com/android/inputmethod/keyboard/Key.java
+++ b/java/src/com/android/inputmethod/keyboard/Key.java
@@ -101,7 +101,7 @@ public class Key {
/** Text to output when pressed. This can be multiple characters, like ".com" */
public final CharSequence mOutputText;
/** More keys */
- public final CharSequence[] mMoreKeys;
+ public final String[] mMoreKeys;
/** More keys maximum column number */
public final int mMaxMoreKeysColumn;
@@ -255,7 +255,7 @@ public class Key {
// Update row to have current x coordinate.
row.setXPos(keyXPos + keyWidth);
- final CharSequence[] moreKeys = style.getTextArray(keyAttr,
+ final String[] moreKeys = style.getTextArray(keyAttr,
R.styleable.Keyboard_Key_moreKeys);
// In Arabic symbol layouts, we'd like to keep digits in more keys regardless of
// config_digit_more_keys_enabled.
diff --git a/java/src/com/android/inputmethod/keyboard/MiniKeyboard.java b/java/src/com/android/inputmethod/keyboard/MiniKeyboard.java
index 548b5ea85..974291373 100644
--- a/java/src/com/android/inputmethod/keyboard/MiniKeyboard.java
+++ b/java/src/com/android/inputmethod/keyboard/MiniKeyboard.java
@@ -34,7 +34,7 @@ public class MiniKeyboard extends Keyboard {
}
public static class Builder extends Keyboard.Builder<Builder.MiniKeyboardParams> {
- private final CharSequence[] mMoreKeys;
+ private final String[] mMoreKeys;
public static class MiniKeyboardParams extends Keyboard.Params {
/* package */int mTopRowAdjustment;
@@ -230,16 +230,14 @@ public class MiniKeyboard extends Keyboard {
parentKey.mX + (mParams.mDefaultKeyWidth - width) / 2, view.getMeasuredWidth());
}
- private static int getMaxKeyWidth(KeyboardView view, CharSequence[] moreKeys,
- int minKeyWidth) {
+ private static int getMaxKeyWidth(KeyboardView view, String[] moreKeys, int minKeyWidth) {
final int padding = (int) view.getContext().getResources()
.getDimension(R.dimen.mini_keyboard_key_horizontal_padding);
Paint paint = null;
int maxWidth = minKeyWidth;
- for (CharSequence moreKeySpec : moreKeys) {
- final CharSequence label = MoreKeySpecParser.getLabel(moreKeySpec.toString());
- // If the label is single letter, minKeyWidth is enough to hold
- // the label.
+ for (String moreKeySpec : moreKeys) {
+ final String label = MoreKeySpecParser.getLabel(moreKeySpec);
+ // If the label is single letter, minKeyWidth is enough to hold the label.
if (label != null && label.length() > 1) {
if (paint == null) {
paint = new Paint();
@@ -258,7 +256,7 @@ public class MiniKeyboard extends Keyboard {
public MiniKeyboard build() {
final MiniKeyboardParams params = mParams;
for (int n = 0; n < mMoreKeys.length; n++) {
- final String moreKeySpec = mMoreKeys[n].toString();
+ final String moreKeySpec = mMoreKeys[n];
final int row = n / params.mNumColumns;
final Key key = new Key(mResources, params, moreKeySpec, params.getX(n, row),
params.getY(row), params.mDefaultKeyWidth, params.mDefaultRowHeight);
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyStyles.java b/java/src/com/android/inputmethod/keyboard/internal/KeyStyles.java
index 5dd8340fc..0f84c4563 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyStyles.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyStyles.java
@@ -37,20 +37,22 @@ public class KeyStyles {
new HashMap<String, DeclaredKeyStyle>();
private static final KeyStyle EMPTY_KEY_STYLE = new EmptyKeyStyle();
+ private static final char ESCAPE_CHAR = '\\';
+
public interface KeyStyle {
- public CharSequence[] getTextArray(TypedArray a, int index);
+ public String[] getTextArray(TypedArray a, int index);
public CharSequence getText(TypedArray a, int index);
public int getInt(TypedArray a, int index, int defaultValue);
public int getFlag(TypedArray a, int index, int defaultValue);
}
- /* package */ static class EmptyKeyStyle implements KeyStyle {
+ private static class EmptyKeyStyle implements KeyStyle {
EmptyKeyStyle() {
// Nothing to do.
}
@Override
- public CharSequence[] getTextArray(TypedArray a, int index) {
+ public String[] getTextArray(TypedArray a, int index) {
return parseTextArray(a, index);
}
@@ -69,64 +71,66 @@ public class KeyStyles {
return a.getInt(index, defaultValue);
}
- protected static CharSequence[] parseTextArray(TypedArray a, int index) {
+ protected static String[] parseTextArray(TypedArray a, int index) {
if (!a.hasValue(index))
return null;
final CharSequence text = a.getText(index);
- return parseCsvText(text);
- }
-
- /* package */ static CharSequence[] parseCsvText(CharSequence text) {
- final int size = text.length();
- if (size == 0) return null;
- if (size == 1) return new CharSequence[] { text };
- final StringBuilder sb = new StringBuilder();
- ArrayList<CharSequence> list = null;
- int start = 0;
- for (int pos = 0; pos < size; pos++) {
- final char c = text.charAt(pos);
- if (c == ',') {
- if (list == null) list = new ArrayList<CharSequence>();
- if (sb.length() == 0) {
- list.add(text.subSequence(start, pos));
- } else {
- list.add(sb.toString());
- sb.setLength(0);
- }
- start = pos + 1;
- continue;
- } else if (c == '\\') {
- if (start == pos) {
- // Skip escape character at the beginning of the value.
- start++;
- pos++;
- } else {
- if (start < pos && sb.length() == 0)
- sb.append(text.subSequence(start, pos));
- pos++;
- if (pos < size)
- sb.append(text.charAt(pos));
- }
- } else if (sb.length() > 0) {
- sb.append(c);
+ return parseCsvText(text.toString());
+ }
+
+ }
+
+ /* package for test */
+ static String[] parseCsvText(String text) {
+ final int size = text.length();
+ if (size == 0) return null;
+ if (size == 1) return new String[] { text };
+ final StringBuilder sb = new StringBuilder();
+ ArrayList<String> list = null;
+ int start = 0;
+ for (int pos = 0; pos < size; pos++) {
+ final char c = text.charAt(pos);
+ if (c == ',') {
+ if (list == null) list = new ArrayList<String>();
+ if (sb.length() == 0) {
+ list.add(text.substring(start, pos));
+ } else {
+ list.add(sb.toString());
+ sb.setLength(0);
}
+ start = pos + 1;
+ continue;
+ } else if (c == ESCAPE_CHAR) {
+ if (start == pos) {
+ // Skip escape character at the beginning of the value.
+ start++;
+ pos++;
+ } else {
+ if (start < pos && sb.length() == 0)
+ sb.append(text.subSequence(start, pos));
+ pos++;
+ if (pos < size)
+ sb.append(text.charAt(pos));
+ }
+ } else if (sb.length() > 0) {
+ sb.append(c);
}
- if (list == null) {
- return new CharSequence[] { sb.length() > 0 ? sb : text.subSequence(start, size) };
- } else {
- list.add(sb.length() > 0 ? sb : text.subSequence(start, size));
- return list.toArray(new CharSequence[list.size()]);
- }
+ }
+ if (list == null) {
+ return new String[] { sb.length() > 0 ? sb.toString() : text.substring(start) };
+ } else {
+ list.add(sb.length() > 0 ? sb.toString() : text.substring(start));
+ return list.toArray(new String[list.size()]);
}
}
- /* package */ static class DeclaredKeyStyle extends EmptyKeyStyle {
+ private static class DeclaredKeyStyle extends EmptyKeyStyle {
private final HashMap<Integer, Object> mAttributes = new HashMap<Integer, Object>();
@Override
- public CharSequence[] getTextArray(TypedArray a, int index) {
+ public String[] getTextArray(TypedArray a, int index) {
return a.hasValue(index)
- ? super.getTextArray(a, index) : (CharSequence[])mAttributes.get(index);
+ ? super.getTextArray(a, index) : (String[])mAttributes.get(index);
}
@Override
diff --git a/java/src/com/android/inputmethod/keyboard/internal/MoreKeySpecParser.java b/java/src/com/android/inputmethod/keyboard/internal/MoreKeySpecParser.java
index d29a9e5ee..d4c85c33d 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/MoreKeySpecParser.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/MoreKeySpecParser.java
@@ -41,7 +41,7 @@ import java.util.ArrayList;
public class MoreKeySpecParser {
private static final String TAG = MoreKeySpecParser.class.getSimpleName();
- private static final char ESCAPE = '\\';
+ private static final char ESCAPE_CHAR = '\\';
private static final String LABEL_END = "|";
private static final String PREFIX_AT = "@";
private static final String PREFIX_ICON = PREFIX_AT + "icon/";
@@ -72,14 +72,14 @@ public class MoreKeySpecParser {
}
private static String parseEscape(String text) {
- if (text.indexOf(ESCAPE) < 0) {
+ if (text.indexOf(ESCAPE_CHAR) < 0) {
return text;
}
final int length = text.length();
final StringBuilder sb = new StringBuilder();
for (int pos = 0; pos < length; pos++) {
final char c = text.charAt(pos);
- if (c == ESCAPE && pos + 1 < length) {
+ if (c == ESCAPE_CHAR && pos + 1 < length) {
sb.append(text.charAt(++pos));
} else {
sb.append(c);
@@ -89,7 +89,7 @@ public class MoreKeySpecParser {
}
private static int indexOfLabelEnd(String moreKeySpec, int start) {
- if (moreKeySpec.indexOf(ESCAPE, start) < 0) {
+ if (moreKeySpec.indexOf(ESCAPE_CHAR, start) < 0) {
final int end = moreKeySpec.indexOf(LABEL_END, start);
if (end == 0) {
throw new MoreKeySpecParserError(LABEL_END + " at " + start + ": " + moreKeySpec);
@@ -99,7 +99,7 @@ public class MoreKeySpecParser {
final int length = moreKeySpec.length();
for (int pos = start; pos < length; pos++) {
final char c = moreKeySpec.charAt(pos);
- if (c == ESCAPE && pos + 1 < length) {
+ if (c == ESCAPE_CHAR && pos + 1 < length) {
pos++;
} else if (moreKeySpec.startsWith(LABEL_END, pos)) {
return pos;
@@ -200,21 +200,19 @@ public class MoreKeySpecParser {
}
};
- public static CharSequence[] filterOut(Resources res, CharSequence[] moreKeys,
- CodeFilter filter) {
+ public static String[] filterOut(Resources res, String[] moreKeys, CodeFilter filter) {
if (moreKeys == null || moreKeys.length < 1) {
return null;
}
- if (moreKeys.length == 1
- && filter.shouldFilterOut(getCode(res, moreKeys[0].toString()))) {
+ if (moreKeys.length == 1 && filter.shouldFilterOut(getCode(res, moreKeys[0]))) {
return null;
}
- ArrayList<CharSequence> filtered = null;
+ ArrayList<String> filtered = null;
for (int i = 0; i < moreKeys.length; i++) {
- final CharSequence moreKeySpec = moreKeys[i];
- if (filter.shouldFilterOut(getCode(res, moreKeySpec.toString()))) {
+ final String moreKeySpec = moreKeys[i];
+ if (filter.shouldFilterOut(getCode(res, moreKeySpec))) {
if (filtered == null) {
- filtered = new ArrayList<CharSequence>();
+ filtered = new ArrayList<String>();
for (int j = 0; j < i; j++) {
filtered.add(moreKeys[j]);
}
@@ -229,6 +227,6 @@ public class MoreKeySpecParser {
if (filtered.size() == 0) {
return null;
}
- return filtered.toArray(new CharSequence[filtered.size()]);
+ return filtered.toArray(new String[filtered.size()]);
}
}
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index d36140de6..78e6602d8 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -1881,6 +1881,10 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
}
return;
}
+ // We need to log before we commit, because the word composer will store away the user
+ // typed word.
+ LatinImeLogger.logOnManualSuggestion(mWordComposer.getTypedWord().toString(),
+ suggestion.toString(), index, suggestions.mWords);
mExpectingUpdateSelection = true;
commitChosenWord(suggestion, WordComposer.COMMIT_TYPE_MANUAL_PICK);
// Add the word to the auto dictionary if it's not a known word
@@ -1890,10 +1894,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
} else {
addToOnlyBigramDictionary(suggestion, 1);
}
- // TODO: the following is fishy, because it seems there may be cases where we are not
- // composing a word at all. Maybe throw an exception if !mWordComposer.isComposingWord() ?
- LatinImeLogger.logOnManualSuggestion(mWordComposer.getTypedWord().toString(),
- suggestion.toString(), index, suggestions.mWords);
// Follow it with a space
if (mInputAttributes.mInsertSpaceOnPickSuggestionManually) {
sendMagicSpace();
diff --git a/tests/src/com/android/inputmethod/keyboard/internal/KeyStylesTests.java b/tests/src/com/android/inputmethod/keyboard/internal/KeyStylesTests.java
index 4050a7123..cebe40958 100644
--- a/tests/src/com/android/inputmethod/keyboard/internal/KeyStylesTests.java
+++ b/tests/src/com/android/inputmethod/keyboard/internal/KeyStylesTests.java
@@ -16,8 +16,6 @@
package com.android.inputmethod.keyboard.internal;
-import com.android.inputmethod.keyboard.internal.KeyStyles.EmptyKeyStyle;
-
import android.test.AndroidTestCase;
import android.text.TextUtils;
@@ -26,9 +24,8 @@ public class KeyStylesTests extends AndroidTestCase {
return message + " expected:<" + expected + "> but was:<" + actual + ">";
}
- private static void assertTextArray(String message, CharSequence value,
- CharSequence ... expected) {
- final CharSequence actual[] = EmptyKeyStyle.parseCsvText(value);
+ private static void assertTextArray(String message, String value, String ... expected) {
+ final String actual[] = KeyStyles.parseCsvText(value);
if (expected.length == 0) {
assertNull(message, actual);
return;
diff --git a/tests/src/com/android/inputmethod/latin/InputLogicTests.java b/tests/src/com/android/inputmethod/latin/InputLogicTests.java
new file mode 100644
index 000000000..18afe1198
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/InputLogicTests.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.inputmethod.latin;
+
+import android.content.Context;
+import android.content.Intent;
+import android.test.ServiceTestCase;
+import android.text.InputType;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.ViewGroup;
+import android.view.View;
+import android.view.inputmethod.BaseInputConnection;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputConnection;
+import android.widget.FrameLayout;
+import android.widget.TextView;
+
+import com.android.inputmethod.keyboard.Keyboard;
+import com.android.inputmethod.keyboard.KeyboardActionListener;
+
+public class InputLogicTests extends ServiceTestCase<LatinIME> {
+
+ private LatinIME mLatinIME;
+ private TextView mTextView;
+
+ public InputLogicTests() {
+ super(LatinIME.class);
+ }
+
+ @Override
+ protected void setUp() {
+ try {
+ super.setUp();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ mTextView = new TextView(getContext());
+ mTextView.setInputType(InputType.TYPE_CLASS_TEXT);
+ mTextView.setEnabled(true);
+ setupService();
+ mLatinIME = getService();
+ mLatinIME.onCreate();
+ final EditorInfo ei = new EditorInfo();
+ final InputConnection ic = mTextView.onCreateInputConnection(ei);
+ final LayoutInflater inflater =
+ (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ final ViewGroup vg = new FrameLayout(getContext());
+ final View inputView = inflater.inflate(R.layout.input_view, vg);
+ mLatinIME.setInputView(inputView);
+ mLatinIME.onBindInput();
+ mLatinIME.onCreateInputView();
+ mLatinIME.onStartInputView(ei, false);
+ mLatinIME.onCreateInputMethodInterface().startInput(ic, ei);
+ }
+
+ // type(int) and type(String): helper methods to send a code point resp. a string to LatinIME.
+ private void type(final int codePoint) {
+ // onPressKey and onReleaseKey are explicitly deactivated here, but they do happen in the
+ // code (although multitouch/slide input and other factors make the sequencing complicated).
+ // They are supposed to be entirely deconnected from the input logic from LatinIME point of
+ // view and only delegates to the parts of the code that care. So we don't include them here
+ // to keep these tests as pinpoint as possible and avoid bringing it too many dependencies,
+ // but keep them in mind if something breaks. Commenting them out as is should work.
+ //mLatinIME.onPressKey(codePoint);
+ mLatinIME.onCodeInput(codePoint, new int[] { codePoint },
+ KeyboardActionListener.NOT_A_TOUCH_COORDINATE,
+ KeyboardActionListener.NOT_A_TOUCH_COORDINATE);
+ //mLatinIME.onReleaseKey(codePoint, false);
+ }
+
+ private void type(final String stringToType) {
+ for (int i = 0; i < stringToType.length(); ++i) {
+ type(stringToType.codePointAt(i));
+ }
+ }
+
+ public void testTypeWord() {
+ final String wordToType = "abcd";
+ type(wordToType);
+ assertEquals("type word", wordToType, mTextView.getText().toString());
+ }
+
+ public void testPickSuggestionThenBackspace() {
+ final String wordToType = "tgis";
+ type(wordToType);
+ mLatinIME.pickSuggestionManually(0, wordToType);
+ type(Keyboard.CODE_DELETE);
+ assertEquals("press suggestion then backspace", wordToType, mTextView.getText().toString());
+ }
+
+}