diff options
author | 2014-09-24 15:52:11 +0900 | |
---|---|---|
committer | 2014-09-25 15:12:06 +0900 | |
commit | 0be4e6e5853daca7813fc7ca853a5492a064d696 (patch) | |
tree | 02a9db8116a8ab5976b2458edd75e19c8abba232 /java/src | |
parent | 145f05d6371fac2a3f6f7cf840add38280c432fe (diff) | |
download | latinime-0be4e6e5853daca7813fc7ca853a5492a064d696.tar.gz latinime-0be4e6e5853daca7813fc7ca853a5492a064d696.tar.xz latinime-0be4e6e5853daca7813fc7ca853a5492a064d696.zip |
Add allowRedundantMoreKeys attribute
This CL also adds a couple of custom layout tests of Nordic languages.
Bug: 10787354
Change-Id: I5e875d3f30863395511afa82f0a02deb093d3a6f
Diffstat (limited to 'java/src')
7 files changed, 138 insertions, 1 deletions
diff --git a/java/src/com/android/inputmethod/compat/CharacterCompat.java b/java/src/com/android/inputmethod/compat/CharacterCompat.java new file mode 100644 index 000000000..609fe1638 --- /dev/null +++ b/java/src/com/android/inputmethod/compat/CharacterCompat.java @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2014 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.compat; + +import java.lang.reflect.Method; + +public final class CharacterCompat { + // Note that Character.isAlphabetic(int), has been introduced in API level 19 + // (Build.VERSION_CODE.KITKAT). + private static final Method METHOD_isAlphabetic = CompatUtils.getMethod( + Character.class, "isAlphabetic", int.class); + + private CharacterCompat() { + // This utility class is not publicly instantiable. + } + + public static boolean isAlphabetic(final int code) { + if (METHOD_isAlphabetic != null) { + return (Boolean)CompatUtils.invoke(null, false, METHOD_isAlphabetic, code); + } + switch (Character.getType(code)) { + case Character.UPPERCASE_LETTER: + case Character.LOWERCASE_LETTER: + case Character.TITLECASE_LETTER: + case Character.MODIFIER_LETTER: + case Character.OTHER_LETTER: + case Character.LETTER_NUMBER: + return true; + default: + return false; + } + } +} diff --git a/java/src/com/android/inputmethod/keyboard/Key.java b/java/src/com/android/inputmethod/keyboard/Key.java index 863a8b7ad..bf29b5ffe 100644 --- a/java/src/com/android/inputmethod/keyboard/Key.java +++ b/java/src/com/android/inputmethod/keyboard/Key.java @@ -395,6 +395,10 @@ public class Key implements Comparable<Key> { * @param key the original key. */ protected Key(final Key key) { + this(key, key.mMoreKeys); + } + + private Key(final Key key, final MoreKeySpec[] moreKeys) { // Final attributes. mCode = key.mCode; mLabel = key.mLabel; @@ -408,7 +412,7 @@ public class Key implements Comparable<Key> { mX = key.mX; mY = key.mY; mHitBox.set(key.mHitBox); - mMoreKeys = key.mMoreKeys; + mMoreKeys = moreKeys; mMoreKeysColumnAndFlags = key.mMoreKeysColumnAndFlags; mBackgroundType = key.mBackgroundType; mActionFlags = key.mActionFlags; @@ -420,6 +424,14 @@ public class Key implements Comparable<Key> { mEnabled = key.mEnabled; } + public static Key removeRedundantMoreKeys(final Key key, + final MoreKeySpec.LettersOnBaseLayout lettersOnBaseLayout) { + final MoreKeySpec[] moreKeys = key.getMoreKeys(); + final MoreKeySpec[] filteredMoreKeys = MoreKeySpec.removeRedundantMoreKeys( + moreKeys, lettersOnBaseLayout); + return (filteredMoreKeys == moreKeys) ? key : new Key(key, filteredMoreKeys); + } + private static boolean needsToUpperCase(final int labelFlags, final int keyboardElementId) { if ((labelFlags & LABEL_FLAGS_PRESERVE_CASE) != 0) return false; switch (keyboardElementId) { diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java b/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java index 47fb7b320..52b9284be 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java @@ -97,6 +97,7 @@ public final class KeyboardLayoutSet { int mKeyboardXmlId; boolean mProximityCharsCorrectionEnabled; boolean mSupportsSplitLayout; + boolean mAllowRedundantMoreKeys; public ElementParams() {} } @@ -202,6 +203,7 @@ public final class KeyboardLayoutSet { if (id.isAlphabetKeyboard()) { builder.setAutoGenerate(sKeysCache); } + builder.setAllowRedundantMoreKes(elementParams.mAllowRedundantMoreKeys); final int keyboardXmlId = elementParams.mKeyboardXmlId; builder.load(keyboardXmlId, id); if (mParams.mDisableTouchPositionCorrectionDataForTest) { @@ -395,6 +397,8 @@ public final class KeyboardLayoutSet { false); elementParams.mSupportsSplitLayout = a.getBoolean( R.styleable.KeyboardLayoutSet_Element_supportsSplitLayout, false); + elementParams.mAllowRedundantMoreKeys = a.getBoolean( + R.styleable.KeyboardLayoutSet_Element_allowRedundantMoreKeys, true); mParams.mKeyboardLayoutSetElementIdToParamsMap.put(elementName, elementParams); } finally { a.recycle(); diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java index 2056a0b9d..50385555c 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java @@ -162,6 +162,10 @@ public class KeyboardBuilder<KP extends KeyboardParams> { mParams.mKeysCache = keysCache; } + public void setAllowRedundantMoreKes(final boolean enabled) { + mParams.mAllowRedundantMoreKeys = enabled; + } + public KeyboardBuilder<KP> load(final int xmlId, final KeyboardId id) { mParams.mId = id; final XmlResourceParser parser = mResources.getXml(xmlId); @@ -851,6 +855,7 @@ public class KeyboardBuilder<KP extends KeyboardParams> { } private void endKeyboard() { + mParams.removeRedundantMoreKeys(); // {@link #parseGridRows(XmlPullParser,boolean)} may populate keyboard rows higher than // previously expected. final int actualHeight = mCurrentY - mParams.mVerticalGap + mParams.mBottomPadding; diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardParams.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardParams.java index 5df9d3ece..1e1188bd0 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardParams.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardParams.java @@ -68,6 +68,7 @@ public class KeyboardParams { public final KeyStylesSet mKeyStyles = new KeyStylesSet(mTextsSet); public KeysCache mKeysCache; + public boolean mAllowRedundantMoreKeys; public int mMostCommonKeyHeight = 0; public int mMostCommonKeyWidth = 0; @@ -115,6 +116,23 @@ public class KeyboardParams { } } + public void removeRedundantMoreKeys() { + if (mAllowRedundantMoreKeys) { + return; + } + final MoreKeySpec.LettersOnBaseLayout lettersOnBaseLayout = + new MoreKeySpec.LettersOnBaseLayout(); + for (final Key key : mSortedKeys) { + lettersOnBaseLayout.addLetter(key); + } + final ArrayList<Key> allKeys = new ArrayList<>(mSortedKeys); + mSortedKeys.clear(); + for (final Key key : allKeys) { + final Key filteredKey = Key.removeRedundantMoreKeys(key, lettersOnBaseLayout); + mSortedKeys.add(mKeysCache.replace(key, filteredKey)); + } + } + private int mMaxHeightCount = 0; private int mMaxWidthCount = 0; private final SparseIntArray mHeightHistogram = new SparseIntArray(); diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeysCache.java b/java/src/com/android/inputmethod/keyboard/internal/KeysCache.java index 7743d4744..e8678637b 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeysCache.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeysCache.java @@ -36,4 +36,12 @@ public final class KeysCache { mMap.put(key, key); return key; } + + public Key replace(final Key oldKey, final Key newKey) { + if (oldKey.equals(newKey)) { + return oldKey; + } + mMap.remove(oldKey); + return get(newKey); + } } diff --git a/java/src/com/android/inputmethod/keyboard/internal/MoreKeySpec.java b/java/src/com/android/inputmethod/keyboard/internal/MoreKeySpec.java index 625a0c283..764159c3d 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/MoreKeySpec.java +++ b/java/src/com/android/inputmethod/keyboard/internal/MoreKeySpec.java @@ -17,7 +17,9 @@ package com.android.inputmethod.keyboard.internal; import android.text.TextUtils; +import android.util.SparseIntArray; +import com.android.inputmethod.compat.CharacterCompat; import com.android.inputmethod.keyboard.Key; import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.define.DebugFlags; @@ -26,6 +28,7 @@ import com.android.inputmethod.latin.utils.StringUtils; import java.util.ArrayList; import java.util.Arrays; +import java.util.HashSet; import java.util.Locale; /** @@ -110,6 +113,46 @@ public final class MoreKeySpec { } } + public static class LettersOnBaseLayout { + private final SparseIntArray mCodes = new SparseIntArray(); + private final HashSet<String> mTexts = new HashSet<>(); + + public void addLetter(final Key key) { + final int code = key.getCode(); + if (CharacterCompat.isAlphabetic(code)) { + mCodes.put(code, 0); + } else if (code == Constants.CODE_OUTPUT_TEXT) { + mTexts.add(key.getOutputText()); + } + } + + public boolean contains(final MoreKeySpec moreKey) { + final int code = moreKey.mCode; + if (CharacterCompat.isAlphabetic(code) && mCodes.indexOfKey(code) >= 0) { + return true; + } else if (code == Constants.CODE_OUTPUT_TEXT && mTexts.contains(moreKey.mOutputText)) { + return true; + } + return false; + } + } + + public static MoreKeySpec[] removeRedundantMoreKeys(final MoreKeySpec[] moreKeys, + final LettersOnBaseLayout lettersOnBaseLayout) { + if (moreKeys == null) { + return null; + } + final ArrayList<MoreKeySpec> filteredMoreKeys = new ArrayList<>(); + for (final MoreKeySpec moreKey : moreKeys) { + if (!lettersOnBaseLayout.contains(moreKey)) { + filteredMoreKeys.add(moreKey); + } + } + final int size = filteredMoreKeys.size(); + return (moreKeys.length == size) ? moreKeys + : filteredMoreKeys.toArray(new MoreKeySpec[size]); + } + private static final boolean DEBUG = DebugFlags.DEBUG_ENABLED; // Constants for parsing. private static final char COMMA = Constants.CODE_COMMA; |