Home | History | Annotate | Download | only in keyboard
      1 /*
      2  * Copyright (C) 2010 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;
     18 
     19 import android.util.SparseArray;
     20 
     21 import com.android.inputmethod.keyboard.internal.KeyVisualAttributes;
     22 import com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
     23 import com.android.inputmethod.keyboard.internal.KeyboardParams;
     24 import com.android.inputmethod.latin.Constants;
     25 import com.android.inputmethod.latin.utils.CollectionUtils;
     26 
     27 /**
     28  * Loads an XML description of a keyboard and stores the attributes of the keys. A keyboard
     29  * consists of rows of keys.
     30  * <p>The layout file for a keyboard contains XML that looks like the following snippet:</p>
     31  * <pre>
     32  * &lt;Keyboard
     33  *         latin:keyWidth="10%p"
     34  *         latin:rowHeight="50px"
     35  *         latin:horizontalGap="2%p"
     36  *         latin:verticalGap="2%p" &gt;
     37  *     &lt;Row latin:keyWidth="10%p" &gt;
     38  *         &lt;Key latin:keyLabel="A" /&gt;
     39  *         ...
     40  *     &lt;/Row&gt;
     41  *     ...
     42  * &lt;/Keyboard&gt;
     43  * </pre>
     44  */
     45 public class Keyboard {
     46     public final KeyboardId mId;
     47     public final int mThemeId;
     48 
     49     /** Total height of the keyboard, including the padding and keys */
     50     public final int mOccupiedHeight;
     51     /** Total width of the keyboard, including the padding and keys */
     52     public final int mOccupiedWidth;
     53 
     54     /** Base height of the keyboard, used to calculate rows' height */
     55     public final int mBaseHeight;
     56     /** Base width of the keyboard, used to calculate keys' width */
     57     public final int mBaseWidth;
     58 
     59     /** The padding above the keyboard */
     60     public final int mTopPadding;
     61     /** Default gap between rows */
     62     public final int mVerticalGap;
     63 
     64     /** Per keyboard key visual parameters */
     65     public final KeyVisualAttributes mKeyVisualAttributes;
     66 
     67     public final int mMostCommonKeyHeight;
     68     public final int mMostCommonKeyWidth;
     69 
     70     /** More keys keyboard template */
     71     public final int mMoreKeysTemplate;
     72 
     73     /** Maximum column for more keys keyboard */
     74     public final int mMaxMoreKeysKeyboardColumn;
     75 
     76     /** Array of keys and icons in this keyboard */
     77     private final Key[] mKeys;
     78     public final Key[] mShiftKeys;
     79     public final Key[] mAltCodeKeysWhileTyping;
     80     public final KeyboardIconsSet mIconsSet;
     81 
     82     private final SparseArray<Key> mKeyCache = CollectionUtils.newSparseArray();
     83 
     84     private final ProximityInfo mProximityInfo;
     85     private final boolean mProximityCharsCorrectionEnabled;
     86 
     87     public Keyboard(final KeyboardParams params) {
     88         mId = params.mId;
     89         mThemeId = params.mThemeId;
     90         mOccupiedHeight = params.mOccupiedHeight;
     91         mOccupiedWidth = params.mOccupiedWidth;
     92         mBaseHeight = params.mBaseHeight;
     93         mBaseWidth = params.mBaseWidth;
     94         mMostCommonKeyHeight = params.mMostCommonKeyHeight;
     95         mMostCommonKeyWidth = params.mMostCommonKeyWidth;
     96         mMoreKeysTemplate = params.mMoreKeysTemplate;
     97         mMaxMoreKeysKeyboardColumn = params.mMaxMoreKeysKeyboardColumn;
     98         mKeyVisualAttributes = params.mKeyVisualAttributes;
     99         mTopPadding = params.mTopPadding;
    100         mVerticalGap = params.mVerticalGap;
    101 
    102         mKeys = params.mKeys.toArray(new Key[params.mKeys.size()]);
    103         mShiftKeys = params.mShiftKeys.toArray(new Key[params.mShiftKeys.size()]);
    104         mAltCodeKeysWhileTyping = params.mAltCodeKeysWhileTyping.toArray(
    105                 new Key[params.mAltCodeKeysWhileTyping.size()]);
    106         mIconsSet = params.mIconsSet;
    107 
    108         mProximityInfo = new ProximityInfo(params.mId.mLocale.toString(),
    109                 params.GRID_WIDTH, params.GRID_HEIGHT, mOccupiedWidth, mOccupiedHeight,
    110                 mMostCommonKeyWidth, mMostCommonKeyHeight, mKeys, params.mTouchPositionCorrection);
    111         mProximityCharsCorrectionEnabled = params.mProximityCharsCorrectionEnabled;
    112     }
    113 
    114     protected Keyboard(final Keyboard keyboard) {
    115         mId = keyboard.mId;
    116         mThemeId = keyboard.mThemeId;
    117         mOccupiedHeight = keyboard.mOccupiedHeight;
    118         mOccupiedWidth = keyboard.mOccupiedWidth;
    119         mBaseHeight = keyboard.mBaseHeight;
    120         mBaseWidth = keyboard.mBaseWidth;
    121         mMostCommonKeyHeight = keyboard.mMostCommonKeyHeight;
    122         mMostCommonKeyWidth = keyboard.mMostCommonKeyWidth;
    123         mMoreKeysTemplate = keyboard.mMoreKeysTemplate;
    124         mMaxMoreKeysKeyboardColumn = keyboard.mMaxMoreKeysKeyboardColumn;
    125         mKeyVisualAttributes = keyboard.mKeyVisualAttributes;
    126         mTopPadding = keyboard.mTopPadding;
    127         mVerticalGap = keyboard.mVerticalGap;
    128 
    129         mKeys = keyboard.mKeys;
    130         mShiftKeys = keyboard.mShiftKeys;
    131         mAltCodeKeysWhileTyping = keyboard.mAltCodeKeysWhileTyping;
    132         mIconsSet = keyboard.mIconsSet;
    133 
    134         mProximityInfo = keyboard.mProximityInfo;
    135         mProximityCharsCorrectionEnabled = keyboard.mProximityCharsCorrectionEnabled;
    136     }
    137 
    138     public boolean hasProximityCharsCorrection(final int code) {
    139         if (!mProximityCharsCorrectionEnabled) {
    140             return false;
    141         }
    142         // Note: The native code has the main keyboard layout only at this moment.
    143         // TODO: Figure out how to handle proximity characters information of all layouts.
    144         final boolean canAssumeNativeHasProximityCharsInfoOfAllKeys = (
    145                 mId.mElementId == KeyboardId.ELEMENT_ALPHABET
    146                 || mId.mElementId == KeyboardId.ELEMENT_ALPHABET_AUTOMATIC_SHIFTED);
    147         return canAssumeNativeHasProximityCharsInfoOfAllKeys || Character.isLetter(code);
    148     }
    149 
    150     public ProximityInfo getProximityInfo() {
    151         return mProximityInfo;
    152     }
    153 
    154     public Key[] getKeys() {
    155         return mKeys;
    156     }
    157 
    158     public Key getKeyFromOutputText(final String outputText) {
    159         for (final Key key : getKeys()) {
    160             if (outputText.equals(key.getOutputText())) {
    161                 return key;
    162             }
    163         }
    164         return null;
    165     }
    166 
    167     public Key getKey(final int code) {
    168         if (code == Constants.CODE_UNSPECIFIED) {
    169             return null;
    170         }
    171         synchronized (mKeyCache) {
    172             final int index = mKeyCache.indexOfKey(code);
    173             if (index >= 0) {
    174                 return mKeyCache.valueAt(index);
    175             }
    176 
    177             for (final Key key : getKeys()) {
    178                 if (key.getCode() == code) {
    179                     mKeyCache.put(code, key);
    180                     return key;
    181                 }
    182             }
    183             mKeyCache.put(code, null);
    184             return null;
    185         }
    186     }
    187 
    188     public boolean hasKey(final Key aKey) {
    189         if (mKeyCache.indexOfValue(aKey) >= 0) {
    190             return true;
    191         }
    192 
    193         for (final Key key : getKeys()) {
    194             if (key == aKey) {
    195                 mKeyCache.put(key.getCode(), key);
    196                 return true;
    197             }
    198         }
    199         return false;
    200     }
    201 
    202     @Override
    203     public String toString() {
    204         return mId.toString();
    205     }
    206 
    207     /**
    208      * Returns the array of the keys that are closest to the given point.
    209      * @param x the x-coordinate of the point
    210      * @param y the y-coordinate of the point
    211      * @return the array of the nearest keys to the given point. If the given
    212      * point is out of range, then an array of size zero is returned.
    213      */
    214     public Key[] getNearestKeys(final int x, final int y) {
    215         // Avoid dead pixels at edges of the keyboard
    216         final int adjustedX = Math.max(0, Math.min(x, mOccupiedWidth - 1));
    217         final int adjustedY = Math.max(0, Math.min(y, mOccupiedHeight - 1));
    218         return mProximityInfo.getNearestKeys(adjustedX, adjustedY);
    219     }
    220 }
    221