| /* |
| * Copyright (C) 2010 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); you may not |
| * use this file except in compliance with the License. You may obtain a copy of |
| * the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| * License for the specific language governing permissions and limitations under |
| * the License. |
| */ |
| |
| package com.android.inputmethod.keyboard; |
| |
| import android.graphics.drawable.Drawable; |
| import android.text.TextUtils; |
| |
| import com.android.inputmethod.keyboard.internal.KeyboardIconsSet; |
| import com.android.inputmethod.keyboard.internal.KeyboardParams; |
| import com.android.inputmethod.keyboard.internal.KeyboardShiftState; |
| |
| import java.util.Collections; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| |
| /** |
| * Loads an XML description of a keyboard and stores the attributes of the keys. A keyboard |
| * consists of rows of keys. |
| * <p>The layout file for a keyboard contains XML that looks like the following snippet:</p> |
| * <pre> |
| * <Keyboard |
| * latin:keyWidth="%10p" |
| * latin:keyHeight="50px" |
| * latin:horizontalGap="2px" |
| * latin:verticalGap="2px" > |
| * <Row latin:keyWidth="32px" > |
| * <Key latin:keyLabel="A" /> |
| * ... |
| * </Row> |
| * ... |
| * </Keyboard> |
| * </pre> |
| */ |
| public class Keyboard { |
| /** Some common keys code. These should be aligned with values/keycodes.xml */ |
| public static final int CODE_ENTER = '\n'; |
| public static final int CODE_TAB = '\t'; |
| public static final int CODE_SPACE = ' '; |
| public static final int CODE_PERIOD = '.'; |
| public static final int CODE_DASH = '-'; |
| public static final int CODE_SINGLE_QUOTE = '\''; |
| public static final int CODE_DOUBLE_QUOTE = '"'; |
| // TODO: Check how this should work for right-to-left languages. It seems to stand |
| // that for rtl languages, a closing parenthesis is a left parenthesis. Is this |
| // managed by the font? Or is it a different char? |
| public static final int CODE_CLOSING_PARENTHESIS = ')'; |
| public static final int CODE_CLOSING_SQUARE_BRACKET = ']'; |
| public static final int CODE_CLOSING_CURLY_BRACKET = '}'; |
| public static final int CODE_CLOSING_ANGLE_BRACKET = '>'; |
| public static final int CODE_DIGIT0 = '0'; |
| public static final int CODE_PLUS = '+'; |
| |
| |
| /** Special keys code. These should be aligned with values/keycodes.xml */ |
| public static final int CODE_DUMMY = 0; |
| public static final int CODE_SHIFT = -1; |
| public static final int CODE_SWITCH_ALPHA_SYMBOL = -2; |
| public static final int CODE_CAPSLOCK = -3; |
| public static final int CODE_CANCEL = -4; |
| public static final int CODE_DELETE = -5; |
| public static final int CODE_SETTINGS = -6; |
| public static final int CODE_SHORTCUT = -7; |
| // Code value representing the code is not specified. |
| public static final int CODE_UNSPECIFIED = -99; |
| |
| public final KeyboardId mId; |
| public final int mThemeId; |
| |
| /** Total height of the keyboard, including the padding and keys */ |
| public final int mOccupiedHeight; |
| /** Total width of the keyboard, including the padding and keys */ |
| public final int mOccupiedWidth; |
| |
| /** The padding above the keyboard */ |
| public final int mTopPadding; |
| /** Default gap between rows */ |
| public final int mVerticalGap; |
| |
| public final int mMostCommonKeyHeight; |
| public final int mMostCommonKeyWidth; |
| |
| /** More keys keyboard template */ |
| public final int mMoreKeysTemplate; |
| |
| /** Maximum column for mini keyboard */ |
| public final int mMaxMiniKeyboardColumn; |
| |
| /** True if Right-To-Left keyboard */ |
| public final boolean mIsRtlKeyboard; |
| |
| /** List of keys and icons in this keyboard */ |
| public final List<Key> mKeys; |
| public final List<Key> mShiftKeys; |
| public final Set<Key> mShiftLockKeys; |
| public final Map<Key, Drawable> mShiftedIcons; |
| public final Map<Key, Drawable> mUnshiftedIcons; |
| public final KeyboardIconsSet mIconsSet; |
| |
| private final KeyboardShiftState mShiftState = new KeyboardShiftState(); |
| |
| private final ProximityInfo mProximityInfo; |
| |
| public Keyboard(KeyboardParams params) { |
| mId = params.mId; |
| mThemeId = params.mThemeId; |
| mOccupiedHeight = params.mOccupiedHeight; |
| mOccupiedWidth = params.mOccupiedWidth; |
| mMostCommonKeyHeight = params.mMostCommonKeyHeight; |
| mMostCommonKeyWidth = params.mMostCommonKeyWidth; |
| mIsRtlKeyboard = params.mIsRtlKeyboard; |
| mMoreKeysTemplate = params.mMoreKeysTemplate; |
| mMaxMiniKeyboardColumn = params.mMaxMiniKeyboardColumn; |
| |
| mTopPadding = params.mTopPadding; |
| mVerticalGap = params.mVerticalGap; |
| |
| mKeys = Collections.unmodifiableList(params.mKeys); |
| mShiftKeys = Collections.unmodifiableList(params.mShiftKeys); |
| mShiftLockKeys = Collections.unmodifiableSet(params.mShiftLockKeys); |
| mShiftedIcons = Collections.unmodifiableMap(params.mShiftedIcons); |
| mUnshiftedIcons = Collections.unmodifiableMap(params.mUnshiftedIcons); |
| mIconsSet = params.mIconsSet; |
| |
| mProximityInfo = new ProximityInfo( |
| params.GRID_WIDTH, params.GRID_HEIGHT, mOccupiedWidth, mOccupiedHeight, |
| mMostCommonKeyWidth, mMostCommonKeyHeight, mKeys, params.mTouchPositionCorrectionXs, |
| params.mTouchPositionCorrectionYs, params.mTouchPositionCorrectionRadii); |
| } |
| |
| public ProximityInfo getProximityInfo() { |
| return mProximityInfo; |
| } |
| |
| public boolean hasShiftLockKey() { |
| return !mShiftLockKeys.isEmpty(); |
| } |
| |
| public boolean setShiftLocked(boolean newShiftLockState) { |
| for (final Key key : mShiftLockKeys) { |
| // To represent "shift locked" state. The highlight is handled by background image that |
| // might be a StateListDrawable. |
| key.setHighlightOn(newShiftLockState); |
| // To represent "shifted" state. The key might have a shifted icon. |
| if (newShiftLockState && mShiftedIcons.containsKey(key)) { |
| key.setIcon(mShiftedIcons.get(key)); |
| } else { |
| key.setIcon(mUnshiftedIcons.get(key)); |
| } |
| } |
| mShiftState.setShiftLocked(newShiftLockState); |
| return true; |
| } |
| |
| public boolean isShiftLocked() { |
| return mShiftState.isShiftLocked(); |
| } |
| |
| public boolean setShifted(boolean newShiftState) { |
| for (final Key key : mShiftKeys) { |
| if (!newShiftState && !mShiftState.isShiftLocked()) { |
| key.setIcon(mUnshiftedIcons.get(key)); |
| } else if (newShiftState && !mShiftState.isShiftedOrShiftLocked()) { |
| key.setIcon(mShiftedIcons.get(key)); |
| } |
| } |
| return mShiftState.setShifted(newShiftState); |
| } |
| |
| public boolean isShiftedOrShiftLocked() { |
| return mShiftState.isShiftedOrShiftLocked(); |
| } |
| |
| public void setAutomaticTemporaryUpperCase() { |
| setShifted(true); |
| mShiftState.setAutomaticTemporaryUpperCase(); |
| } |
| |
| public boolean isAutomaticTemporaryUpperCase() { |
| return isAlphaKeyboard() && mShiftState.isAutomaticTemporaryUpperCase(); |
| } |
| |
| public boolean isManualTemporaryUpperCase() { |
| return isAlphaKeyboard() && mShiftState.isManualTemporaryUpperCase(); |
| } |
| |
| public boolean isManualTemporaryUpperCaseFromAuto() { |
| return isAlphaKeyboard() && mShiftState.isManualTemporaryUpperCaseFromAuto(); |
| } |
| |
| public KeyboardShiftState getKeyboardShiftState() { |
| return mShiftState; |
| } |
| |
| public boolean isAlphaKeyboard() { |
| return mId.isAlphabetKeyboard(); |
| } |
| |
| public boolean isPhoneKeyboard() { |
| return mId.isPhoneKeyboard(); |
| } |
| |
| public boolean isNumberKeyboard() { |
| return mId.isNumberKeyboard(); |
| } |
| |
| public CharSequence adjustLabelCase(CharSequence label) { |
| if (isShiftedOrShiftLocked() && !TextUtils.isEmpty(label) && label.length() < 3 |
| && Character.isLowerCase(label.charAt(0))) { |
| return label.toString().toUpperCase(mId.mLocale); |
| } |
| return label; |
| } |
| |
| /** |
| * Returns the indices of the keys that are closest to the given point. |
| * @param x the x-coordinate of the point |
| * @param y the y-coordinate of the point |
| * @return the array of integer indices for the nearest keys to the given point. If the given |
| * point is out of range, then an array of size zero is returned. |
| */ |
| public int[] getNearestKeys(int x, int y) { |
| return mProximityInfo.getNearestKeys(x, y); |
| } |
| |
| public static String themeName(int themeId) { |
| // This should be aligned with theme-*.xml resource files' themeId attribute. |
| switch (themeId) { |
| case 0: return "Basic"; |
| case 1: return "BasicHighContrast"; |
| case 5: return "IceCreamSandwich"; |
| case 6: return "Stone"; |
| case 7: return "StoneBold"; |
| case 8: return "GingerBread"; |
| default: return null; |
| } |
| } |
| } |