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 
KeyboardParams()105     public KeyboardParams() {
106         this(UniqueKeysCache.NO_CACHE);
107     }
108 
KeyboardParams(@onnull final UniqueKeysCache keysCache)109     public KeyboardParams(@Nonnull final UniqueKeysCache keysCache) {
110         mUniqueKeysCache = keysCache;
111     }
112 
clearKeys()113     protected void clearKeys() {
114         mSortedKeys.clear();
115         mShiftKeys.clear();
116         clearHistogram();
117     }
118 
onAddKey(@onnull final Key newKey)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 
removeRedundantMoreKeys()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 
clearHistogram()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 
updateHistogramCounter(final SparseIntArray histogram, final int key)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 
updateHistogram(final Key key)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