Keyboard.java revision 63584323cab56c76debf6bb000621f2c605329a9
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 17package com.android.inputmethod.keyboard; 18 19import android.graphics.drawable.Drawable; 20import android.text.TextUtils; 21 22import com.android.inputmethod.keyboard.internal.KeyboardIconsSet; 23import com.android.inputmethod.keyboard.internal.KeyboardParams; 24import com.android.inputmethod.keyboard.internal.KeyboardShiftState; 25 26import java.util.Collections; 27import java.util.List; 28import java.util.Map; 29import 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 * <Keyboard 37 * latin:keyWidth="%10p" 38 * latin:keyHeight="50px" 39 * latin:horizontalGap="2px" 40 * latin:verticalGap="2px" > 41 * <Row latin:keyWidth="32px" > 42 * <Key latin:keyLabel="A" /> 43 * ... 44 * </Row> 45 * ... 46 * </Keyboard> 47 * </pre> 48 */ 49public class Keyboard { 50 public static final int EDGE_LEFT = 0x01; 51 public static final int EDGE_RIGHT = 0x02; 52 public static final int EDGE_TOP = 0x04; 53 public static final int EDGE_BOTTOM = 0x08; 54 55 /** Some common keys code. These should be aligned with values/keycodes.xml */ 56 public static final int CODE_ENTER = '\n'; 57 public static final int CODE_TAB = '\t'; 58 public static final int CODE_SPACE = ' '; 59 public static final int CODE_PERIOD = '.'; 60 public static final int CODE_DASH = '-'; 61 public static final int CODE_SINGLE_QUOTE = '\''; 62 public static final int CODE_DOUBLE_QUOTE = '"'; 63 // TODO: Check how this should work for right-to-left languages. It seems to stand 64 // that for rtl languages, a closing parenthesis is a left parenthesis. Is this 65 // managed by the font? Or is it a different char? 66 public static final int CODE_CLOSING_PARENTHESIS = ')'; 67 public static final int CODE_CLOSING_SQUARE_BRACKET = ']'; 68 public static final int CODE_CLOSING_CURLY_BRACKET = '}'; 69 public static final int CODE_CLOSING_ANGLE_BRACKET = '>'; 70 public static final int CODE_DIGIT0 = '0'; 71 public static final int CODE_PLUS = '+'; 72 73 74 /** Special keys code. These should be aligned with values/keycodes.xml */ 75 public static final int CODE_DUMMY = 0; 76 public static final int CODE_SHIFT = -1; 77 public static final int CODE_SWITCH_ALPHA_SYMBOL = -2; 78 public static final int CODE_CAPSLOCK = -3; 79 public static final int CODE_CANCEL = -4; 80 public static final int CODE_DELETE = -5; 81 public static final int CODE_SETTINGS = -6; 82 public static final int CODE_SHORTCUT = -7; 83 // Code value representing the code is not specified. 84 public static final int CODE_UNSPECIFIED = -99; 85 86 public final KeyboardId mId; 87 public final int mThemeId; 88 89 /** Total height of the keyboard, including the padding and keys */ 90 public final int mOccupiedHeight; 91 /** Total width of the keyboard, including the padding and keys */ 92 public final int mOccupiedWidth; 93 94 /** The padding above the keyboard */ 95 public final int mTopPadding; 96 /** Default gap between rows */ 97 public final int mVerticalGap; 98 99 public final int mMostCommonKeyHeight; 100 public final int mMostCommonKeyWidth; 101 102 /** More keys keyboard template */ 103 public final int mMoreKeysTemplate; 104 105 /** Maximum column for mini keyboard */ 106 public final int mMaxMiniKeyboardColumn; 107 108 /** True if Right-To-Left keyboard */ 109 public final boolean mIsRtlKeyboard; 110 111 /** List of keys and icons in this keyboard */ 112 public final List<Key> mKeys; 113 public final List<Key> mShiftKeys; 114 public final Set<Key> mShiftLockKeys; 115 public final Map<Key, Drawable> mShiftedIcons; 116 public final Map<Key, Drawable> mUnshiftedIcons; 117 public final KeyboardIconsSet mIconsSet; 118 119 private final KeyboardShiftState mShiftState = new KeyboardShiftState(); 120 121 private final ProximityInfo mProximityInfo; 122 123 public Keyboard(KeyboardParams params) { 124 mId = params.mId; 125 mThemeId = params.mThemeId; 126 mOccupiedHeight = params.mOccupiedHeight; 127 mOccupiedWidth = params.mOccupiedWidth; 128 mMostCommonKeyHeight = params.mMostCommonKeyHeight; 129 mMostCommonKeyWidth = params.mMostCommonKeyWidth; 130 mIsRtlKeyboard = params.mIsRtlKeyboard; 131 mMoreKeysTemplate = params.mMoreKeysTemplate; 132 mMaxMiniKeyboardColumn = params.mMaxMiniKeyboardColumn; 133 134 mTopPadding = params.mTopPadding; 135 mVerticalGap = params.mVerticalGap; 136 137 mKeys = Collections.unmodifiableList(params.mKeys); 138 mShiftKeys = Collections.unmodifiableList(params.mShiftKeys); 139 mShiftLockKeys = Collections.unmodifiableSet(params.mShiftLockKeys); 140 mShiftedIcons = Collections.unmodifiableMap(params.mShiftedIcons); 141 mUnshiftedIcons = Collections.unmodifiableMap(params.mUnshiftedIcons); 142 mIconsSet = params.mIconsSet; 143 144 mProximityInfo = new ProximityInfo( 145 params.GRID_WIDTH, params.GRID_HEIGHT, mOccupiedWidth, mOccupiedHeight, 146 mMostCommonKeyWidth, mKeys); 147 } 148 149 public ProximityInfo getProximityInfo() { 150 return mProximityInfo; 151 } 152 153 public boolean hasShiftLockKey() { 154 return !mShiftLockKeys.isEmpty(); 155 } 156 157 public boolean setShiftLocked(boolean newShiftLockState) { 158 for (final Key key : mShiftLockKeys) { 159 // To represent "shift locked" state. The highlight is handled by background image that 160 // might be a StateListDrawable. 161 key.setHighlightOn(newShiftLockState); 162 // To represent "shifted" state. The key might have a shifted icon. 163 if (newShiftLockState && mShiftedIcons.containsKey(key)) { 164 key.setIcon(mShiftedIcons.get(key)); 165 } else { 166 key.setIcon(mUnshiftedIcons.get(key)); 167 } 168 } 169 mShiftState.setShiftLocked(newShiftLockState); 170 return true; 171 } 172 173 public boolean isShiftLocked() { 174 return mShiftState.isShiftLocked(); 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