Fix adjusting key's label/code case
With this fix, we may probably be able to revert I76c3e917 (Make KeySpecParser case insensitive). Bug: 6561272 Change-Id: Ic7571560d7b422ffc9a07f0acecd388e0b330d50
This commit is contained in:
parent
739ff3cfc4
commit
7ab7f66c2d
4 changed files with 62 additions and 50 deletions
|
@ -42,6 +42,7 @@ import org.xmlpull.v1.XmlPullParser;
|
||||||
import org.xmlpull.v1.XmlPullParserException;
|
import org.xmlpull.v1.XmlPullParserException;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class for describing the position and characteristics of a single key in the keyboard.
|
* Class for describing the position and characteristics of a single key in the keyboard.
|
||||||
|
@ -240,7 +241,8 @@ public class Key {
|
||||||
|
|
||||||
mLabelFlags = style.getFlag(keyAttr, R.styleable.Keyboard_Key_keyLabelFlags)
|
mLabelFlags = style.getFlag(keyAttr, R.styleable.Keyboard_Key_keyLabelFlags)
|
||||||
| row.getDefaultKeyLabelFlags();
|
| row.getDefaultKeyLabelFlags();
|
||||||
final boolean preserveCase = (mLabelFlags & LABEL_FLAGS_PRESERVE_CASE) != 0;
|
final boolean needsToUpperCase = needsToUpperCase(mLabelFlags, params.mId.mElementId);
|
||||||
|
final Locale locale = params.mId.mLocale;
|
||||||
int actionFlags = style.getFlag(keyAttr, R.styleable.Keyboard_Key_keyActionFlags);
|
int actionFlags = style.getFlag(keyAttr, R.styleable.Keyboard_Key_keyActionFlags);
|
||||||
String[] moreKeys = style.getStringArray(keyAttr, R.styleable.Keyboard_Key_moreKeys);
|
String[] moreKeys = style.getStringArray(keyAttr, R.styleable.Keyboard_Key_moreKeys);
|
||||||
|
|
||||||
|
@ -276,8 +278,8 @@ public class Key {
|
||||||
actionFlags |= ACTION_FLAGS_ENABLE_LONG_PRESS;
|
actionFlags |= ACTION_FLAGS_ENABLE_LONG_PRESS;
|
||||||
mMoreKeys = new MoreKeySpec[moreKeys.length];
|
mMoreKeys = new MoreKeySpec[moreKeys.length];
|
||||||
for (int i = 0; i < moreKeys.length; i++) {
|
for (int i = 0; i < moreKeys.length; i++) {
|
||||||
mMoreKeys[i] = new MoreKeySpec(adjustCaseOfStringForKeyboardId(
|
mMoreKeys[i] = new MoreKeySpec(
|
||||||
moreKeys[i], preserveCase, params.mId), params.mCodesSet);
|
moreKeys[i], needsToUpperCase, locale, params.mCodesSet);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
mMoreKeys = null;
|
mMoreKeys = null;
|
||||||
|
@ -287,17 +289,17 @@ public class Key {
|
||||||
if ((mLabelFlags & LABEL_FLAGS_FROM_CUSTOM_ACTION_LABEL) != 0) {
|
if ((mLabelFlags & LABEL_FLAGS_FROM_CUSTOM_ACTION_LABEL) != 0) {
|
||||||
mLabel = params.mId.mCustomActionLabel;
|
mLabel = params.mId.mCustomActionLabel;
|
||||||
} else {
|
} else {
|
||||||
mLabel = adjustCaseOfStringForKeyboardId(style.getString(keyAttr,
|
mLabel = KeySpecParser.toUpperCaseOfStringForLocale(style.getString(keyAttr,
|
||||||
R.styleable.Keyboard_Key_keyLabel), preserveCase, params.mId);
|
R.styleable.Keyboard_Key_keyLabel), needsToUpperCase, locale);
|
||||||
}
|
}
|
||||||
if ((mLabelFlags & LABEL_FLAGS_DISABLE_HINT_LABEL) != 0) {
|
if ((mLabelFlags & LABEL_FLAGS_DISABLE_HINT_LABEL) != 0) {
|
||||||
mHintLabel = null;
|
mHintLabel = null;
|
||||||
} else {
|
} else {
|
||||||
mHintLabel = adjustCaseOfStringForKeyboardId(style.getString(keyAttr,
|
mHintLabel = KeySpecParser.toUpperCaseOfStringForLocale(style.getString(keyAttr,
|
||||||
R.styleable.Keyboard_Key_keyHintLabel), preserveCase, params.mId);
|
R.styleable.Keyboard_Key_keyHintLabel), needsToUpperCase, locale);
|
||||||
}
|
}
|
||||||
String outputText = adjustCaseOfStringForKeyboardId(style.getString(keyAttr,
|
String outputText = KeySpecParser.toUpperCaseOfStringForLocale(style.getString(keyAttr,
|
||||||
R.styleable.Keyboard_Key_keyOutputText), preserveCase, params.mId);
|
R.styleable.Keyboard_Key_keyOutputText), needsToUpperCase, locale);
|
||||||
final int code = KeySpecParser.parseCode(style.getString(keyAttr,
|
final int code = KeySpecParser.parseCode(style.getString(keyAttr,
|
||||||
R.styleable.Keyboard_Key_code), params.mCodesSet, CODE_UNSPECIFIED);
|
R.styleable.Keyboard_Key_code), params.mCodesSet, CODE_UNSPECIFIED);
|
||||||
// Choose the first letter of the label as primary code if not specified.
|
// Choose the first letter of the label as primary code if not specified.
|
||||||
|
@ -326,12 +328,13 @@ public class Key {
|
||||||
mCode = CODE_OUTPUT_TEXT;
|
mCode = CODE_OUTPUT_TEXT;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
mCode = adjustCaseOfCodeForKeyboardId(code, preserveCase, params.mId);
|
mCode = KeySpecParser.toUpperCaseOfCodeForLocale(code, needsToUpperCase, locale);
|
||||||
}
|
}
|
||||||
mOutputText = outputText;
|
mOutputText = outputText;
|
||||||
mAltCode = adjustCaseOfCodeForKeyboardId(KeySpecParser.parseCode(style.getString(keyAttr,
|
mAltCode = KeySpecParser.toUpperCaseOfCodeForLocale(
|
||||||
|
KeySpecParser.parseCode(style.getString(keyAttr,
|
||||||
R.styleable.Keyboard_Key_altCode), params.mCodesSet, CODE_UNSPECIFIED),
|
R.styleable.Keyboard_Key_altCode), params.mCodesSet, CODE_UNSPECIFIED),
|
||||||
preserveCase, params.mId);
|
needsToUpperCase, locale);
|
||||||
mHashCode = computeHashCode(this);
|
mHashCode = computeHashCode(this);
|
||||||
|
|
||||||
keyAttr.recycle();
|
keyAttr.recycle();
|
||||||
|
@ -341,26 +344,16 @@ public class Key {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int adjustCaseOfCodeForKeyboardId(int code, boolean preserveCase,
|
private static boolean needsToUpperCase(int labelFlags, int keyboardElementId) {
|
||||||
KeyboardId id) {
|
if ((labelFlags & LABEL_FLAGS_PRESERVE_CASE) != 0) return false;
|
||||||
if (!Keyboard.isLetterCode(code) || preserveCase) return code;
|
switch (keyboardElementId) {
|
||||||
final String text = new String(new int[] { code } , 0, 1);
|
|
||||||
final String casedText = adjustCaseOfStringForKeyboardId(text, preserveCase, id);
|
|
||||||
return StringUtils.codePointCount(casedText) == 1
|
|
||||||
? casedText.codePointAt(0) : CODE_UNSPECIFIED;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String adjustCaseOfStringForKeyboardId(String text, boolean preserveCase,
|
|
||||||
KeyboardId id) {
|
|
||||||
if (text == null || preserveCase) return text;
|
|
||||||
switch (id.mElementId) {
|
|
||||||
case KeyboardId.ELEMENT_ALPHABET_MANUAL_SHIFTED:
|
case KeyboardId.ELEMENT_ALPHABET_MANUAL_SHIFTED:
|
||||||
case KeyboardId.ELEMENT_ALPHABET_AUTOMATIC_SHIFTED:
|
case KeyboardId.ELEMENT_ALPHABET_AUTOMATIC_SHIFTED:
|
||||||
case KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCKED:
|
case KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCKED:
|
||||||
case KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCK_SHIFTED:
|
case KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCK_SHIFTED:
|
||||||
return text.toUpperCase(id.mLocale);
|
return true;
|
||||||
default:
|
default:
|
||||||
return text;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
|
|
||||||
package com.android.inputmethod.keyboard.internal;
|
package com.android.inputmethod.keyboard.internal;
|
||||||
|
|
||||||
|
import static com.android.inputmethod.keyboard.Keyboard.CODE_UNSPECIFIED;
|
||||||
|
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
|
||||||
import com.android.inputmethod.keyboard.Keyboard;
|
import com.android.inputmethod.keyboard.Keyboard;
|
||||||
|
@ -24,6 +26,7 @@ import com.android.inputmethod.latin.StringUtils;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The string parser of more keys specification.
|
* The string parser of more keys specification.
|
||||||
|
@ -63,10 +66,14 @@ public class KeySpecParser {
|
||||||
public final String mOutputText;
|
public final String mOutputText;
|
||||||
public final int mIconId;
|
public final int mIconId;
|
||||||
|
|
||||||
public MoreKeySpec(final String moreKeySpec, final KeyboardCodesSet codesSet) {
|
public MoreKeySpec(final String moreKeySpec, boolean needsToUpperCase, Locale locale,
|
||||||
mCode = getCode(moreKeySpec, codesSet);
|
final KeyboardCodesSet codesSet) {
|
||||||
mLabel = getLabel(moreKeySpec);
|
mCode = toUpperCaseOfCodeForLocale(getCode(moreKeySpec, codesSet),
|
||||||
mOutputText = getOutputText(moreKeySpec);
|
needsToUpperCase, locale);
|
||||||
|
mLabel = toUpperCaseOfStringForLocale(getLabel(moreKeySpec),
|
||||||
|
needsToUpperCase, locale);
|
||||||
|
mOutputText = toUpperCaseOfStringForLocale(getOutputText(moreKeySpec),
|
||||||
|
needsToUpperCase, locale);
|
||||||
mIconId = getIconId(moreKeySpec);
|
mIconId = getIconId(moreKeySpec);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -256,9 +263,8 @@ public class KeySpecParser {
|
||||||
}
|
}
|
||||||
if (out == null) {
|
if (out == null) {
|
||||||
return array;
|
return array;
|
||||||
} else {
|
|
||||||
return out.toArray(new String[out.size()]);
|
|
||||||
}
|
}
|
||||||
|
return out.toArray(new String[out.size()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String[] insertAdditionalMoreKeys(String[] moreKeySpecs,
|
public static String[] insertAdditionalMoreKeys(String[] moreKeySpecs,
|
||||||
|
@ -427,12 +433,11 @@ public class KeySpecParser {
|
||||||
final String remain = (size - start > 0) ? text.substring(start) : null;
|
final String remain = (size - start > 0) ? text.substring(start) : null;
|
||||||
if (list == null) {
|
if (list == null) {
|
||||||
return remain != null ? new String[] { remain } : null;
|
return remain != null ? new String[] { remain } : null;
|
||||||
} else {
|
|
||||||
if (remain != null) {
|
|
||||||
list.add(remain);
|
|
||||||
}
|
|
||||||
return list.toArray(new String[list.size()]);
|
|
||||||
}
|
}
|
||||||
|
if (remain != null) {
|
||||||
|
list.add(remain);
|
||||||
|
}
|
||||||
|
return list.toArray(new String[list.size()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int getIntValue(String[] moreKeys, String key, int defaultValue) {
|
public static int getIntValue(String[] moreKeys, String key, int defaultValue) {
|
||||||
|
@ -476,4 +481,20 @@ public class KeySpecParser {
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static int toUpperCaseOfCodeForLocale(int code, boolean needsToUpperCase,
|
||||||
|
Locale locale) {
|
||||||
|
if (!Keyboard.isLetterCode(code) || !needsToUpperCase) return code;
|
||||||
|
final String text = new String(new int[] { code } , 0, 1);
|
||||||
|
final String casedText = KeySpecParser.toUpperCaseOfStringForLocale(
|
||||||
|
text, needsToUpperCase, locale);
|
||||||
|
return StringUtils.codePointCount(casedText) == 1
|
||||||
|
? casedText.codePointAt(0) : CODE_UNSPECIFIED;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String toUpperCaseOfStringForLocale(String text, boolean needsToUpperCase,
|
||||||
|
Locale locale) {
|
||||||
|
if (text == null || !needsToUpperCase) return text;
|
||||||
|
return text.toUpperCase(locale);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,9 +34,6 @@ public class KeyboardCodesSet {
|
||||||
|
|
||||||
public int getCode(final String name) {
|
public int getCode(final String name) {
|
||||||
Integer id = sNameToIdMap.get(name);
|
Integer id = sNameToIdMap.get(name);
|
||||||
if (id == null) {
|
|
||||||
id = sNameToIdMap.get(name.toLowerCase());
|
|
||||||
}
|
|
||||||
if (id == null) throw new RuntimeException("Unknown key code: " + name);
|
if (id == null) throw new RuntimeException("Unknown key code: " + name);
|
||||||
return mCodes[id];
|
return mCodes[id];
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,7 +62,8 @@ public class KeySpecParserTests extends AndroidTestCase {
|
||||||
private void assertParser(String message, String moreKeySpec, String expectedLabel,
|
private void assertParser(String message, String moreKeySpec, String expectedLabel,
|
||||||
String expectedOutputText, int expectedIcon, int expectedCode) {
|
String expectedOutputText, int expectedIcon, int expectedCode) {
|
||||||
final String labelResolved = KeySpecParser.resolveTextReference(moreKeySpec, mTextsSet);
|
final String labelResolved = KeySpecParser.resolveTextReference(moreKeySpec, mTextsSet);
|
||||||
final MoreKeySpec spec = new MoreKeySpec(labelResolved, mCodesSet);
|
final MoreKeySpec spec = new MoreKeySpec(labelResolved, false /* needsToUpperCase */,
|
||||||
|
Locale.US, mCodesSet);
|
||||||
assertEquals(message + " [label]", expectedLabel, spec.mLabel);
|
assertEquals(message + " [label]", expectedLabel, spec.mLabel);
|
||||||
assertEquals(message + " [ouptputText]", expectedOutputText, spec.mOutputText);
|
assertEquals(message + " [ouptputText]", expectedOutputText, spec.mOutputText);
|
||||||
assertEquals(message + " [icon]",
|
assertEquals(message + " [icon]",
|
||||||
|
@ -149,7 +150,7 @@ public class KeySpecParserTests extends AndroidTestCase {
|
||||||
"|", null, ICON_UNDEFINED, '|');
|
"|", null, ICON_UNDEFINED, '|');
|
||||||
assertParser("Single letter with code", "a|" + CODE_SETTINGS,
|
assertParser("Single letter with code", "a|" + CODE_SETTINGS,
|
||||||
"a", null, ICON_UNDEFINED, mCodeSettings);
|
"a", null, ICON_UNDEFINED, mCodeSettings);
|
||||||
assertParser("Single letter with CODE", "a|" + CODE_SETTINGS_UPPERCASE,
|
assertParserError("Single letter with CODE", "a|" + CODE_SETTINGS_UPPERCASE,
|
||||||
"a", null, ICON_UNDEFINED, mCodeSettings);
|
"a", null, ICON_UNDEFINED, mCodeSettings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,11 +214,11 @@ public class KeySpecParserTests extends AndroidTestCase {
|
||||||
"a|c", "d|f", ICON_UNDEFINED, CODE_OUTPUT_TEXT);
|
"a|c", "d|f", ICON_UNDEFINED, CODE_OUTPUT_TEXT);
|
||||||
assertParser("Label with code", "abc|" + CODE_SETTINGS,
|
assertParser("Label with code", "abc|" + CODE_SETTINGS,
|
||||||
"abc", null, ICON_UNDEFINED, mCodeSettings);
|
"abc", null, ICON_UNDEFINED, mCodeSettings);
|
||||||
assertParser("Label with CODE", "abc|" + CODE_SETTINGS_UPPERCASE,
|
assertParserError("Label with CODE", "abc|" + CODE_SETTINGS_UPPERCASE,
|
||||||
"abc", null, ICON_UNDEFINED, mCodeSettings);
|
"abc", null, ICON_UNDEFINED, mCodeSettings);
|
||||||
assertParser("Escaped label with code", "a\\|c|" + CODE_SETTINGS,
|
assertParser("Escaped label with code", "a\\|c|" + CODE_SETTINGS,
|
||||||
"a|c", null, ICON_UNDEFINED, mCodeSettings);
|
"a|c", null, ICON_UNDEFINED, mCodeSettings);
|
||||||
assertParser("Escaped label with CODE", "a\\|c|" + CODE_SETTINGS_UPPERCASE,
|
assertParserError("Escaped label with CODE", "a\\|c|" + CODE_SETTINGS_UPPERCASE,
|
||||||
"a|c", null, ICON_UNDEFINED, mCodeSettings);
|
"a|c", null, ICON_UNDEFINED, mCodeSettings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -240,19 +241,19 @@ public class KeySpecParserTests extends AndroidTestCase {
|
||||||
null, "!bc", mSettingsIconId, CODE_OUTPUT_TEXT);
|
null, "!bc", mSettingsIconId, CODE_OUTPUT_TEXT);
|
||||||
assertParser("Label starts with bang and code", "!bc|" + CODE_SETTINGS,
|
assertParser("Label starts with bang and code", "!bc|" + CODE_SETTINGS,
|
||||||
"!bc", null, ICON_UNDEFINED, mCodeSettings);
|
"!bc", null, ICON_UNDEFINED, mCodeSettings);
|
||||||
assertParser("Label starts with bang and CODE", "!bc|" + CODE_SETTINGS_UPPERCASE,
|
assertParserError("Label starts with bang and CODE", "!bc|" + CODE_SETTINGS_UPPERCASE,
|
||||||
"!bc", null, ICON_UNDEFINED, mCodeSettings);
|
"!bc", null, ICON_UNDEFINED, mCodeSettings);
|
||||||
assertParser("Label contains bang and code", "a!c|" + CODE_SETTINGS,
|
assertParser("Label contains bang and code", "a!c|" + CODE_SETTINGS,
|
||||||
"a!c", null, ICON_UNDEFINED, mCodeSettings);
|
"a!c", null, ICON_UNDEFINED, mCodeSettings);
|
||||||
assertParser("Label contains bang and CODE", "a!c|" + CODE_SETTINGS_UPPERCASE,
|
assertParserError("Label contains bang and CODE", "a!c|" + CODE_SETTINGS_UPPERCASE,
|
||||||
"a!c", null, ICON_UNDEFINED, mCodeSettings);
|
"a!c", null, ICON_UNDEFINED, mCodeSettings);
|
||||||
assertParser("Escaped bang label with code", "\\!bc|" + CODE_SETTINGS,
|
assertParser("Escaped bang label with code", "\\!bc|" + CODE_SETTINGS,
|
||||||
"!bc", null, ICON_UNDEFINED, mCodeSettings);
|
"!bc", null, ICON_UNDEFINED, mCodeSettings);
|
||||||
assertParser("Escaped bang label with CODE", "\\!bc|" + CODE_SETTINGS_UPPERCASE,
|
assertParserError("Escaped bang label with CODE", "\\!bc|" + CODE_SETTINGS_UPPERCASE,
|
||||||
"!bc", null, ICON_UNDEFINED, mCodeSettings);
|
"!bc", null, ICON_UNDEFINED, mCodeSettings);
|
||||||
assertParser("Icon with code", ICON_SETTINGS + "|" + CODE_SETTINGS,
|
assertParser("Icon with code", ICON_SETTINGS + "|" + CODE_SETTINGS,
|
||||||
null, null, mSettingsIconId, mCodeSettings);
|
null, null, mSettingsIconId, mCodeSettings);
|
||||||
assertParser("ICON with CODE", ICON_SETTINGS_UPPERCASE + "|" + CODE_SETTINGS_UPPERCASE,
|
assertParserError("ICON with CODE", ICON_SETTINGS_UPPERCASE + "|" + CODE_SETTINGS_UPPERCASE,
|
||||||
null, null, mSettingsIconId, mCodeSettings);
|
null, null, mSettingsIconId, mCodeSettings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -264,7 +265,7 @@ public class KeySpecParserTests extends AndroidTestCase {
|
||||||
|
|
||||||
assertParser("Action next as more key", "!text/label_next_key|!code/key_action_next",
|
assertParser("Action next as more key", "!text/label_next_key|!code/key_action_next",
|
||||||
"Next", null, ICON_UNDEFINED, mCodeActionNext);
|
"Next", null, ICON_UNDEFINED, mCodeActionNext);
|
||||||
assertParser("ACTION NEXT AS MORE KEY", "!TEXT/LABEL_NEXT_KEY|!CODE/KEY_ACTION_NEXT",
|
assertParserError("ACTION NEXT AS MORE KEY", "!TEXT/LABEL_NEXT_KEY|!CODE/KEY_ACTION_NEXT",
|
||||||
"Next", null, ICON_UNDEFINED, mCodeActionNext);
|
"Next", null, ICON_UNDEFINED, mCodeActionNext);
|
||||||
|
|
||||||
assertParser("Popular domain",
|
assertParser("Popular domain",
|
||||||
|
|
Loading…
Reference in a new issue