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.CollectionUtils;
     25 import com.android.inputmethod.latin.Constants;
     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     /** The padding above the keyboard */
     55     public final int mTopPadding;
     56     /** Default gap between rows */
     57     public final int mVerticalGap;
     58 
     59     /** Per keyboard key visual parameters */
     60     public final KeyVisualAttributes mKeyVisualAttributes;
     61 
     62     public final int mMostCommonKeyHeight;
     63     public final int mMostCommonKeyWidth;
     64 
     65     /** More keys keyboard template */
     66     public final int mMoreKeysTemplate;
     67 
     68     /** Maximum column for more keys keyboard */
     69     public final int mMaxMoreKeysKeyboardColumn;
     70 
     71     /** Array of keys and icons in this keyboard */
     72     public final Key[] mKeys;
     73     public final Key[] mShiftKeys;
     74     public final Key[] mAltCodeKeysWhileTyping;
     75     public final KeyboardIconsSet mIconsSet;
     76 
     77     private final SparseArray<Key> mKeyCache = CollectionUtils.newSparseArray();
     78 
     79     private final ProximityInfo mProximityInfo;
     80     private final boolean mProximityCharsCorrectionEnabled;
     81 
     82     public Keyboard(final KeyboardParams params) {
     83         mId = params.mId;
     84         mThemeId = params.mThemeId;
     85         mOccupiedHeight = params.mOccupiedHeight;
     86         mOccupiedWidth = params.mOccupiedWidth;
     87         mMostCommonKeyHeight = params.mMostCommonKeyHeight;
     88         mMostCommonKeyWidth = params.mMostCommonKeyWidth;
     89         mMoreKeysTemplate = params.mMoreKeysTemplate;
     90         mMaxMoreKeysKeyboardColumn = params.mMaxMoreKeysKeyboardColumn;
     91         mKeyVisualAttributes = params.mKeyVisualAttributes;
     92         mTopPadding = params.mTopPadding;
     93         mVerticalGap = params.mVerticalGap;
     94 
     95         mKeys = params.mKeys.toArray(new Key[params.mKeys.size()]);
     96         mShiftKeys = params.mShiftKeys.toArray(new Key[params.mShiftKeys.size()]);
     97         mAltCodeKeysWhileTyping = params.mAltCodeKeysWhileTyping.toArray(
     98                 new Key[params.mAltCodeKeysWhileTyping.size()]);
     99         mIconsSet = params.mIconsSet;
    100 
    101         mProximityInfo = new ProximityInfo(params.mId.mLocale.toString(),
    102                 params.GRID_WIDTH, params.GRID_HEIGHT, mOccupiedWidth, mOccupiedHeight,
    103                 mMostCommonKeyWidth, mMostCommonKeyHeight, mKeys, params.mTouchPositionCorrection);
    104         mProximityCharsCorrectionEnabled = params.mProximityCharsCorrectionEnabled;
    105     }
    106 
    107     public boolean hasProximityCharsCorrection(final int code) {
    108         if (!mProximityCharsCorrectionEnabled) {
    109             return false;
    110         }
    111         // Note: The native code has the main keyboard layout only at this moment.
    112         // TODO: Figure out how to handle proximity characters information of all layouts.
    113         final boolean canAssumeNativeHasProximityCharsInfoOfAllKeys = (
    114                 mId.mElementId == KeyboardId.ELEMENT_ALPHABET
    115                 || mId.mElementId == KeyboardId.ELEMENT_ALPHABET_AUTOMATIC_SHIFTED);
    116         return canAssumeNativeHasProximityCharsInfoOfAllKeys || Character.isLetter(code);
    117     }
    118 
    119     public ProximityInfo getProximityInfo() {
    120         return mProximityInfo;
    121     }
    122 
    123     public Key getKey(final int code) {
    124         if (code == Constants.CODE_UNSPECIFIED) {
    125             return null;
    126         }
    127         synchronized (mKeyCache) {
    128             final int index = mKeyCache.indexOfKey(code);
    129             if (index >= 0) {
    130                 return mKeyCache.valueAt(index);
    131             }
    132 
    133             for (final Key key : mKeys) {
    134                 if (key.mCode == code) {
    135                     mKeyCache.put(code, key);
    136                     return key;
    137                 }
    138             }
    139             mKeyCache.put(code, null);
    140             return null;
    141         }
    142     }
    143 
    144     public boolean hasKey(final Key aKey) {
    145         if (mKeyCache.indexOfValue(aKey) >= 0) {
    146             return true;
    147         }
    148 
    149         for (final Key key : mKeys) {
    150             if (key == aKey) {
    151                 mKeyCache.put(key.mCode, key);
    152                 return true;
    153             }
    154         }
    155         return false;
    156     }
    157 
    158     @Override
    159     public String toString() {
    160         return mId.toString();
    161     }
    162 
    163     /**
    164      * Returns the array of the keys that are closest to the given point.
    165      * @param x the x-coordinate of the point
    166      * @param y the y-coordinate of the point
    167      * @return the array of the nearest keys to the given point. If the given
    168      * point is out of range, then an array of size zero is returned.
    169      */
    170     public Key[] getNearestKeys(final int x, final int y) {
    171         // Avoid dead pixels at edges of the keyboard
    172         final int adjustedX = Math.max(0, Math.min(x, mOccupiedWidth - 1));
    173         final int adjustedY = Math.max(0, Math.min(y, mOccupiedHeight - 1));
    174         return mProximityInfo.getNearestKeys(adjustedX, adjustedY);
    175     }
    176 }
    177