1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.inputmethod.keyboard.internal; 18 19 import android.util.SparseIntArray; 20 21 import com.android.inputmethod.keyboard.Key; 22 import com.android.inputmethod.keyboard.KeyboardId; 23 import com.android.inputmethod.latin.common.Constants; 24 25 import java.util.ArrayList; 26 import java.util.Comparator; 27 import java.util.SortedSet; 28 import java.util.TreeSet; 29 30 import javax.annotation.Nonnull; 31 import javax.annotation.Nullable; 32 33 public class KeyboardParams { 34 public KeyboardId mId; 35 public int mThemeId; 36 37 /** Total height and width of the keyboard, including the paddings and keys */ 38 public int mOccupiedHeight; 39 public int mOccupiedWidth; 40 41 /** Base height and width of the keyboard used to calculate rows' or keys' heights and 42 * widths 43 */ 44 public int mBaseHeight; 45 public int mBaseWidth; 46 47 public int mTopPadding; 48 public int mBottomPadding; 49 public int mLeftPadding; 50 public int mRightPadding; 51 52 @Nullable 53 public KeyVisualAttributes mKeyVisualAttributes; 54 55 public int mDefaultRowHeight; 56 public int mDefaultKeyWidth; 57 public int mHorizontalGap; 58 public int mVerticalGap; 59 60 public int mMoreKeysTemplate; 61 public int mMaxMoreKeysKeyboardColumn; 62 63 public int GRID_WIDTH; 64 public int GRID_HEIGHT; 65 66 // Keys are sorted from top-left to bottom-right order. 67 @Nonnull 68 public final SortedSet<Key> mSortedKeys = new TreeSet<>(ROW_COLUMN_COMPARATOR); 69 @Nonnull 70 public final ArrayList<Key> mShiftKeys = new ArrayList<>(); 71 @Nonnull 72 public final ArrayList<Key> mAltCodeKeysWhileTyping = new ArrayList<>(); 73 @Nonnull 74 public final KeyboardIconsSet mIconsSet = new KeyboardIconsSet(); 75 @Nonnull 76 public final KeyboardTextsSet mTextsSet = new KeyboardTextsSet(); 77 @Nonnull 78 public final KeyStylesSet mKeyStyles = new KeyStylesSet(mTextsSet); 79 80 @Nonnull 81 private final UniqueKeysCache mUniqueKeysCache; 82 public boolean mAllowRedundantMoreKeys; 83 84 public int mMostCommonKeyHeight = 0; 85 public int mMostCommonKeyWidth = 0; 86 87 public boolean mProximityCharsCorrectionEnabled; 88 89 @Nonnull 90 public final TouchPositionCorrection mTouchPositionCorrection = 91 new TouchPositionCorrection(); 92 93 // Comparator to sort {@link Key}s from top-left to bottom-right order. 94 private static final Comparator<Key> ROW_COLUMN_COMPARATOR = new Comparator<Key>() { 95 @Override 96 public int compare(final Key lhs, final Key rhs) { 97 if (lhs.getY() < rhs.getY()) return -1; 98 if (lhs.getY() > rhs.getY()) return 1; 99 if (lhs.getX() < rhs.getX()) return -1; 100 if (lhs.getX() > rhs.getX()) return 1; 101 return 0; 102 } 103 }; 104 105 public KeyboardParams() { 106 this(UniqueKeysCache.NO_CACHE); 107 } 108 109 public KeyboardParams(@Nonnull final UniqueKeysCache keysCache) { 110 mUniqueKeysCache = keysCache; 111 } 112 113 protected void clearKeys() { 114 mSortedKeys.clear(); 115 mShiftKeys.clear(); 116 clearHistogram(); 117 } 118 119 public void onAddKey(@Nonnull final Key newKey) { 120 final Key key = mUniqueKeysCache.getUniqueKey(newKey); 121 final boolean isSpacer = key.isSpacer(); 122 if (isSpacer && key.getWidth() == 0) { 123 // Ignore zero width {@link Spacer}. 124 return; 125 } 126 mSortedKeys.add(key); 127 if (isSpacer) { 128 return; 129 } 130 updateHistogram(key); 131 if (key.getCode() == Constants.CODE_SHIFT) { 132 mShiftKeys.add(key); 133 } 134 if (key.altCodeWhileTyping()) { 135 mAltCodeKeysWhileTyping.add(key); 136 } 137 } 138 139 public void removeRedundantMoreKeys() { 140 if (mAllowRedundantMoreKeys) { 141 return; 142 } 143 final MoreKeySpec.LettersOnBaseLayout lettersOnBaseLayout = 144 new MoreKeySpec.LettersOnBaseLayout(); 145 for (final Key key : mSortedKeys) { 146 lettersOnBaseLayout.addLetter(key); 147 } 148 final ArrayList<Key> allKeys = new ArrayList<>(mSortedKeys); 149 mSortedKeys.clear(); 150 for (final Key key : allKeys) { 151 final Key filteredKey = Key.removeRedundantMoreKeys(key, lettersOnBaseLayout); 152 mSortedKeys.add(mUniqueKeysCache.getUniqueKey(filteredKey)); 153 } 154 } 155 156 private int mMaxHeightCount = 0; 157 private int mMaxWidthCount = 0; 158 private final SparseIntArray mHeightHistogram = new SparseIntArray(); 159 private final SparseIntArray mWidthHistogram = new SparseIntArray(); 160 161 private void clearHistogram() { 162 mMostCommonKeyHeight = 0; 163 mMaxHeightCount = 0; 164 mHeightHistogram.clear(); 165 166 mMaxWidthCount = 0; 167 mMostCommonKeyWidth = 0; 168 mWidthHistogram.clear(); 169 } 170 171 private static int updateHistogramCounter(final SparseIntArray histogram, final int key) { 172 final int index = histogram.indexOfKey(key); 173 final int count = (index >= 0 ? histogram.get(key) : 0) + 1; 174 histogram.put(key, count); 175 return count; 176 } 177 178 private void updateHistogram(final Key key) { 179 final int height = key.getHeight() + mVerticalGap; 180 final int heightCount = updateHistogramCounter(mHeightHistogram, height); 181 if (heightCount > mMaxHeightCount) { 182 mMaxHeightCount = heightCount; 183 mMostCommonKeyHeight = height; 184 } 185 186 final int width = key.getWidth() + mHorizontalGap; 187 final int widthCount = updateHistogramCounter(mWidthHistogram, width); 188 if (widthCount > mMaxWidthCount) { 189 mMaxWidthCount = widthCount; 190 mMostCommonKeyWidth = width; 191 } 192 } 193 } 194