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"); you may not
      5  * use this file except in compliance with the License. You may obtain a copy of
      6  * 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, WITHOUT
     12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
     13  * License for the specific language governing permissions and limitations under
     14  * the License.
     15  */
     16 
     17 package com.android.inputmethod.keyboard;
     18 
     19 import android.graphics.drawable.Drawable;
     20 import android.text.TextUtils;
     21 
     22 import com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
     23 import com.android.inputmethod.keyboard.internal.KeyboardParams;
     24 import com.android.inputmethod.keyboard.internal.KeyboardShiftState;
     25 
     26 import java.util.Collections;
     27 import java.util.List;
     28 import java.util.Map;
     29 import java.util.Set;
     30 
     31 /**
     32  * Loads an XML description of a keyboard and stores the attributes of the keys. A keyboard
     33  * consists of rows of keys.
     34  * <p>The layout file for a keyboard contains XML that looks like the following snippet:</p>
     35  * <pre>
     36  * &lt;Keyboard
     37  *         latin:keyWidth="%10p"
     38  *         latin:keyHeight="50px"
     39  *         latin:horizontalGap="2px"
     40  *         latin:verticalGap="2px" &gt;
     41  *     &lt;Row latin:keyWidth="32px" &gt;
     42  *         &lt;Key latin:keyLabel="A" /&gt;
     43  *         ...
     44  *     &lt;/Row&gt;
     45  *     ...
     46  * &lt;/Keyboard&gt;
     47  * </pre>
     48  */
     49 public class Keyboard {
     50     /** Some common keys code.  These should be aligned with values/keycodes.xml */
     51     public static final int CODE_ENTER = '\n';
     52     public static final int CODE_TAB = '\t';
     53     public static final int CODE_SPACE = ' ';
     54     public static final int CODE_PERIOD = '.';
     55     public static final int CODE_DASH = '-';
     56     public static final int CODE_SINGLE_QUOTE = '\'';
     57     public static final int CODE_DOUBLE_QUOTE = '"';
     58     // TODO: Check how this should work for right-to-left languages. It seems to stand
     59     // that for rtl languages, a closing parenthesis is a left parenthesis. Is this
     60     // managed by the font? Or is it a different char?
     61     public static final int CODE_CLOSING_PARENTHESIS = ')';
     62     public static final int CODE_CLOSING_SQUARE_BRACKET = ']';
     63     public static final int CODE_CLOSING_CURLY_BRACKET = '}';
     64     public static final int CODE_CLOSING_ANGLE_BRACKET = '>';
     65     public static final int CODE_DIGIT0 = '0';
     66     public static final int CODE_PLUS = '+';
     67 
     68 
     69     /** Special keys code.  These should be aligned with values/keycodes.xml */
     70     public static final int CODE_DUMMY = 0;
     71     public static final int CODE_SHIFT = -1;
     72     public static final int CODE_SWITCH_ALPHA_SYMBOL = -2;
     73     public static final int CODE_CAPSLOCK = -3;
     74     public static final int CODE_CANCEL = -4;
     75     public static final int CODE_DELETE = -5;
     76     public static final int CODE_SETTINGS = -6;
     77     public static final int CODE_SHORTCUT = -7;
     78     public static final int CODE_HAPTIC_AND_AUDIO_FEEDBACK_ONLY = -98;
     79     // Code value representing the code is not specified.
     80     public static final int CODE_UNSPECIFIED = -99;
     81 
     82     public final KeyboardId mId;
     83     public final int mThemeId;
     84 
     85     /** Total height of the keyboard, including the padding and keys */
     86     public final int mOccupiedHeight;
     87     /** Total width of the keyboard, including the padding and keys */
     88     public final int mOccupiedWidth;
     89 
     90     /** The padding above the keyboard */
     91     public final int mTopPadding;
     92     /** Default gap between rows */
     93     public final int mVerticalGap;
     94 
     95     public final int mMostCommonKeyHeight;
     96     public final int mMostCommonKeyWidth;
     97 
     98     /** More keys keyboard template */
     99     public final int mMoreKeysTemplate;
    100 
    101     /** Maximum column for mini keyboard */
    102     public final int mMaxMiniKeyboardColumn;
    103 
    104     /** True if Right-To-Left keyboard */
    105     public final boolean mIsRtlKeyboard;
    106 
    107     /** List of keys and icons in this keyboard */
    108     public final List<Key> mKeys;
    109     public final List<Key> mShiftKeys;
    110     public final Set<Key> mShiftLockKeys;
    111     public final Map<Key, Drawable> mShiftedIcons;
    112     public final Map<Key, Drawable> mUnshiftedIcons;
    113     public final KeyboardIconsSet mIconsSet;
    114 
    115     private final KeyboardShiftState mShiftState = new KeyboardShiftState();
    116 
    117     private final ProximityInfo mProximityInfo;
    118 
    119     public Keyboard(KeyboardParams params) {
    120         mId = params.mId;
    121         mThemeId = params.mThemeId;
    122         mOccupiedHeight = params.mOccupiedHeight;
    123         mOccupiedWidth = params.mOccupiedWidth;
    124         mMostCommonKeyHeight = params.mMostCommonKeyHeight;
    125         mMostCommonKeyWidth = params.mMostCommonKeyWidth;
    126         mIsRtlKeyboard = params.mIsRtlKeyboard;
    127         mMoreKeysTemplate = params.mMoreKeysTemplate;
    128         mMaxMiniKeyboardColumn = params.mMaxMiniKeyboardColumn;
    129 
    130         mTopPadding = params.mTopPadding;
    131         mVerticalGap = params.mVerticalGap;
    132 
    133         mKeys = Collections.unmodifiableList(params.mKeys);
    134         mShiftKeys = Collections.unmodifiableList(params.mShiftKeys);
    135         mShiftLockKeys = Collections.unmodifiableSet(params.mShiftLockKeys);
    136         mShiftedIcons = Collections.unmodifiableMap(params.mShiftedIcons);
    137         mUnshiftedIcons = Collections.unmodifiableMap(params.mUnshiftedIcons);
    138         mIconsSet = params.mIconsSet;
    139 
    140         mProximityInfo = new ProximityInfo(
    141                 params.GRID_WIDTH, params.GRID_HEIGHT, mOccupiedWidth, mOccupiedHeight,
    142                 mMostCommonKeyWidth, mMostCommonKeyHeight, mKeys, params.mTouchPositionCorrection);
    143     }
    144 
    145     public ProximityInfo getProximityInfo() {
    146         return mProximityInfo;
    147     }
    148 
    149     public boolean hasShiftLockKey() {
    150         return !mShiftLockKeys.isEmpty();
    151     }
    152 
    153     public boolean setShiftLocked(boolean newShiftLockState) {
    154         for (final Key key : mShiftLockKeys) {
    155             // To represent "shift locked" state. The highlight is handled by background image that
    156             // might be a StateListDrawable.
    157             key.setHighlightOn(newShiftLockState);
    158             // To represent "shifted" state. The key might have a shifted icon.
    159             if (newShiftLockState && mShiftedIcons.containsKey(key)) {
    160                 key.setIcon(mShiftedIcons.get(key));
    161             } else {
    162                 key.setIcon(mUnshiftedIcons.get(key));
    163             }
    164         }
    165         mShiftState.setShiftLocked(newShiftLockState);
    166         return true;
    167     }
    168 
    169     public boolean isShiftLocked() {
    170         return mShiftState.isShiftLocked();
    171     }
    172 
    173     public boolean isShiftLockShifted() {
    174         return mShiftState.isShiftLockShifted();
    175     }
    176 
    177     public boolean setShifted(boolean newShiftState) {
    178         for (final Key key : mShiftKeys) {
    179             if (!newShiftState && !mShiftState.isShiftLocked()) {
    180                 key.setIcon(mUnshiftedIcons.get(key));
    181             } else if (newShiftState && !mShiftState.isShiftedOrShiftLocked()) {
    182                 key.setIcon(mShiftedIcons.get(key));
    183             }
    184         }
    185         return mShiftState.setShifted(newShiftState);
    186     }
    187 
    188     public boolean isShiftedOrShiftLocked() {
    189         return mShiftState.isShiftedOrShiftLocked();
    190     }
    191 
    192     public void setAutomaticTemporaryUpperCase() {
    193         setShifted(true);
    194         mShiftState.setAutomaticTemporaryUpperCase();
    195     }
    196 
    197     public boolean isAutomaticTemporaryUpperCase() {
    198         return isAlphaKeyboard() && mShiftState.isAutomaticTemporaryUpperCase();
    199     }
    200 
    201     public boolean isManualTemporaryUpperCase() {
    202         return isAlphaKeyboard() && mShiftState.isManualTemporaryUpperCase();
    203     }
    204 
    205     public boolean isManualTemporaryUpperCaseFromAuto() {
    206         return isAlphaKeyboard() && mShiftState.isManualTemporaryUpperCaseFromAuto();
    207     }
    208 
    209     public KeyboardShiftState getKeyboardShiftState() {
    210         return mShiftState;
    211     }
    212 
    213     public boolean isAlphaKeyboard() {
    214         return mId.isAlphabetKeyboard();
    215     }
    216 
    217     public boolean isPhoneKeyboard() {
    218         return mId.isPhoneKeyboard();
    219     }
    220 
    221     public boolean isNumberKeyboard() {
    222         return mId.isNumberKeyboard();
    223     }
    224 
    225     public CharSequence adjustLabelCase(CharSequence label) {
    226         if (isShiftedOrShiftLocked() && !TextUtils.isEmpty(label) && label.length() < 3
    227                 && Character.isLowerCase(label.charAt(0))) {
    228             return label.toString().toUpperCase(mId.mLocale);
    229         }
    230         return label;
    231     }
    232 
    233     /**
    234      * Returns the indices of the keys that are closest to the given point.
    235      * @param x the x-coordinate of the point
    236      * @param y the y-coordinate of the point
    237      * @return the array of integer indices for the nearest keys to the given point. If the given
    238      * point is out of range, then an array of size zero is returned.
    239      */
    240     public int[] getNearestKeys(int x, int y) {
    241         return mProximityInfo.getNearestKeys(x, y);
    242     }
    243 
    244     public static String themeName(int themeId) {
    245         // This should be aligned with theme-*.xml resource files' themeId attribute.
    246         switch (themeId) {
    247         case 0: return "Basic";
    248         case 1: return "BasicHighContrast";
    249         case 5: return "IceCreamSandwich";
    250         case 6: return "Stone";
    251         case 7: return "StoneBold";
    252         case 8: return "GingerBread";
    253         default: return null;
    254         }
    255     }
    256 }
    257