Keyboard.java revision 623d0155b6a316fdc9335370cdd4005bbb474ef3
15a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka/*
28632bff2d5a8e1160989008dea6eff4b94b065ddTadashi G. Takaoka * Copyright (C) 2010 The Android Open Source Project
35a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka *
45a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka * Licensed under the Apache License, Version 2.0 (the "License"); you may not
55a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka * use this file except in compliance with the License. You may obtain a copy of
65a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka * the License at
75a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka *
85a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka * http://www.apache.org/licenses/LICENSE-2.0
95a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka *
105a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka * Unless required by applicable law or agreed to in writing, software
115a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
125a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
135a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka * License for the specific language governing permissions and limitations under
145a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka * the License.
155a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka */
165a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka
175a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaokapackage com.android.inputmethod.keyboard;
185a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka
195a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaokaimport android.graphics.drawable.Drawable;
20d773bf38a3c8f49ea56de67d3b828f8126f46ed2Tadashi G. Takaokaimport android.text.TextUtils;
217dfd5a3e833e14d5bf90d728d5a50b40c8a927d2Tadashi G. Takaokaimport android.util.Log;
225a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka
23c2a21786e526cc32e48a577a55b1b7e72ae1a6ddTadashi G. Takaokaimport com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
248da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaokaimport com.android.inputmethod.keyboard.internal.KeyboardParams;
25e466583ddc68278ad708094f8ac521be504bf342Tadashi G. Takaokaimport com.android.inputmethod.keyboard.internal.KeyboardShiftState;
26b7758d6f912093747d4b18fbc8d1dcd77c7d1f9bTadashi G. Takaoka
278da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaokaimport java.util.Collections;
282013bab89ca2f82589f99d98d9cf3b41ea5aac65Tadashi G. Takaokaimport java.util.HashMap;
295a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaokaimport java.util.List;
30167e77f17084da5c223a3a790d3dd3d749e68ae3Tadashi G. Takaokaimport java.util.Map;
31167e77f17084da5c223a3a790d3dd3d749e68ae3Tadashi G. Takaokaimport java.util.Set;
325a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka
335a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka/**
345a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka * Loads an XML description of a keyboard and stores the attributes of the keys. A keyboard
355a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka * consists of rows of keys.
365a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka * <p>The layout file for a keyboard contains XML that looks like the following snippet:</p>
375a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka * <pre>
385a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka * &lt;Keyboard
395a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka *         latin:keyWidth="%10p"
405a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka *         latin:keyHeight="50px"
415a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka *         latin:horizontalGap="2px"
425a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka *         latin:verticalGap="2px" &gt;
435a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka *     &lt;Row latin:keyWidth="32px" &gt;
445a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka *         &lt;Key latin:keyLabel="A" /&gt;
455a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka *         ...
465a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka *     &lt;/Row&gt;
475a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka *     ...
485a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka * &lt;/Keyboard&gt;
495a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka * </pre>
505a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka */
515a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaokapublic class Keyboard {
527dfd5a3e833e14d5bf90d728d5a50b40c8a927d2Tadashi G. Takaoka    private static final String TAG = Keyboard.class.getSimpleName();
537dfd5a3e833e14d5bf90d728d5a50b40c8a927d2Tadashi G. Takaoka
54e18bd3e323e7d7448677bb66e8149eea0169c771Tadashi G. Takaoka    /** Some common keys code.  These should be aligned with values/keycodes.xml */
55571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka    public static final int CODE_ENTER = '\n';
56571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka    public static final int CODE_TAB = '\t';
57571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka    public static final int CODE_SPACE = ' ';
58571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka    public static final int CODE_PERIOD = '.';
590730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard    public static final int CODE_DASH = '-';
600730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard    public static final int CODE_SINGLE_QUOTE = '\'';
610730bbfbf5e37bbcb5c287aeff71b304c833a36eJean Chalard    public static final int CODE_DOUBLE_QUOTE = '"';
622b4eabed2bfe982b91a994c145401d98894e6ef5Jean Chalard    // TODO: Check how this should work for right-to-left languages. It seems to stand
632b4eabed2bfe982b91a994c145401d98894e6ef5Jean Chalard    // that for rtl languages, a closing parenthesis is a left parenthesis. Is this
642b4eabed2bfe982b91a994c145401d98894e6ef5Jean Chalard    // managed by the font? Or is it a different char?
652b4eabed2bfe982b91a994c145401d98894e6ef5Jean Chalard    public static final int CODE_CLOSING_PARENTHESIS = ')';
662b4eabed2bfe982b91a994c145401d98894e6ef5Jean Chalard    public static final int CODE_CLOSING_SQUARE_BRACKET = ']';
672b4eabed2bfe982b91a994c145401d98894e6ef5Jean Chalard    public static final int CODE_CLOSING_CURLY_BRACKET = '}';
682b4eabed2bfe982b91a994c145401d98894e6ef5Jean Chalard    public static final int CODE_CLOSING_ANGLE_BRACKET = '>';
69851c3267d4ab21f892b4164783bb4959c88b44ffTadashi G. Takaoka    public static final int CODE_DIGIT0 = '0';
70851c3267d4ab21f892b4164783bb4959c88b44ffTadashi G. Takaoka    public static final int CODE_PLUS = '+';
712b4eabed2bfe982b91a994c145401d98894e6ef5Jean Chalard
72e18bd3e323e7d7448677bb66e8149eea0169c771Tadashi G. Takaoka    /** Special keys code.  These should be aligned with values/keycodes.xml */
73c4f71668d7b8203dc66f0f04c089a363189eb4ceTadashi G. Takaoka    public static final int CODE_DUMMY = 0;
74571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka    public static final int CODE_SHIFT = -1;
75e18bd3e323e7d7448677bb66e8149eea0169c771Tadashi G. Takaoka    public static final int CODE_SWITCH_ALPHA_SYMBOL = -2;
76d2c5fdda862f6dd2a1e020cf674c35fbbc63fc92Tadashi G. Takaoka    public static final int CODE_CAPSLOCK = -3;
77571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka    public static final int CODE_DELETE = -5;
78d2c5fdda862f6dd2a1e020cf674c35fbbc63fc92Tadashi G. Takaoka    public static final int CODE_SETTINGS = -6;
79cadb2128f54b49be31bb4dc06374afe81ed028b7Ken Wakasa    public static final int CODE_SHORTCUT = -7;
80c4f71668d7b8203dc66f0f04c089a363189eb4ceTadashi G. Takaoka    // Code value representing the code is not specified.
81c4f71668d7b8203dc66f0f04c089a363189eb4ceTadashi G. Takaoka    public static final int CODE_UNSPECIFIED = -99;
825a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka
83167e77f17084da5c223a3a790d3dd3d749e68ae3Tadashi G. Takaoka    public final KeyboardId mId;
8463584323cab56c76debf6bb000621f2c605329a9Tadashi G. Takaoka    public final int mThemeId;
85167e77f17084da5c223a3a790d3dd3d749e68ae3Tadashi G. Takaoka
86167e77f17084da5c223a3a790d3dd3d749e68ae3Tadashi G. Takaoka    /** Total height of the keyboard, including the padding and keys */
878da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka    public final int mOccupiedHeight;
888da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka    /** Total width of the keyboard, including the padding and keys */
898da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka    public final int mOccupiedWidth;
90167e77f17084da5c223a3a790d3dd3d749e68ae3Tadashi G. Takaoka
918fbfac4ffb7079e8e71fd4e3ddc04e362239ebb3Tadashi G. Takaoka    /** The padding above the keyboard */
928fbfac4ffb7079e8e71fd4e3ddc04e362239ebb3Tadashi G. Takaoka    public final int mTopPadding;
935a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka    /** Default gap between rows */
948da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka    public final int mVerticalGap;
958da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka
968fbfac4ffb7079e8e71fd4e3ddc04e362239ebb3Tadashi G. Takaoka    public final int mMostCommonKeyHeight;
978da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka    public final int mMostCommonKeyWidth;
985a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka
999d5601e9013c5ec9a7ac75db16f4a0a8218b02bfTadashi G. Takaoka    /** More keys keyboard template */
1009d5601e9013c5ec9a7ac75db16f4a0a8218b02bfTadashi G. Takaoka    public final int mMoreKeysTemplate;
1019b6d1d52d91f8f18952ae3841f4bb0d7309bfc0eTadashi G. Takaoka
1029237a72634be821c22911633ef0848130e162d58Tadashi G. Takaoka    /** Maximum column for mini keyboard */
1039237a72634be821c22911633ef0848130e162d58Tadashi G. Takaoka    public final int mMaxMiniKeyboardColumn;
1049b6d1d52d91f8f18952ae3841f4bb0d7309bfc0eTadashi G. Takaoka
1057139335dcd84209285c028f5d83cb72bfbf1a966Tadashi G. Takaoka    /** True if Right-To-Left keyboard */
1068da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka    public final boolean mIsRtlKeyboard;
1075a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka
1088da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka    /** List of keys and icons in this keyboard */
1098da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka    public final List<Key> mKeys;
1108da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka    public final List<Key> mShiftKeys;
1118da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka    public final Set<Key> mShiftLockKeys;
1128da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka    public final Map<Key, Drawable> mShiftedIcons;
1138da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka    public final Map<Key, Drawable> mUnshiftedIcons;
1148da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka    public final KeyboardIconsSet mIconsSet;
1156fb97bf71cee2a0775410a05478ed6a667aa847fTadashi G. Takaoka
1162013bab89ca2f82589f99d98d9cf3b41ea5aac65Tadashi G. Takaoka    private final Map<Integer, Key> mKeyCache = new HashMap<Integer, Key>();
117c2a21786e526cc32e48a577a55b1b7e72ae1a6ddTadashi G. Takaoka
1188fbd55229243cb66c03d5ea1f79dfb39f596590dsatok    private final ProximityInfo mProximityInfo;
1198fbd55229243cb66c03d5ea1f79dfb39f596590dsatok
120e466583ddc68278ad708094f8ac521be504bf342Tadashi G. Takaoka    // TODO: Remove this variable.
121e466583ddc68278ad708094f8ac521be504bf342Tadashi G. Takaoka    private final KeyboardShiftState mShiftState = new KeyboardShiftState();
122c1859b8fd22b2c4cc2a700566f57f3e3d04e1580Tadashi G. Takaoka
1238da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka    public Keyboard(KeyboardParams params) {
1248da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka        mId = params.mId;
12563584323cab56c76debf6bb000621f2c605329a9Tadashi G. Takaoka        mThemeId = params.mThemeId;
1268da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka        mOccupiedHeight = params.mOccupiedHeight;
1278da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka        mOccupiedWidth = params.mOccupiedWidth;
1288fbfac4ffb7079e8e71fd4e3ddc04e362239ebb3Tadashi G. Takaoka        mMostCommonKeyHeight = params.mMostCommonKeyHeight;
1298da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka        mMostCommonKeyWidth = params.mMostCommonKeyWidth;
1308da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka        mIsRtlKeyboard = params.mIsRtlKeyboard;
1319d5601e9013c5ec9a7ac75db16f4a0a8218b02bfTadashi G. Takaoka        mMoreKeysTemplate = params.mMoreKeysTemplate;
1329237a72634be821c22911633ef0848130e162d58Tadashi G. Takaoka        mMaxMiniKeyboardColumn = params.mMaxMiniKeyboardColumn;
1338da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka
1348fbfac4ffb7079e8e71fd4e3ddc04e362239ebb3Tadashi G. Takaoka        mTopPadding = params.mTopPadding;
1358da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka        mVerticalGap = params.mVerticalGap;
1368da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka
1378da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka        mKeys = Collections.unmodifiableList(params.mKeys);
1388da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka        mShiftKeys = Collections.unmodifiableList(params.mShiftKeys);
1398da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka        mShiftLockKeys = Collections.unmodifiableSet(params.mShiftLockKeys);
1408da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka        mShiftedIcons = Collections.unmodifiableMap(params.mShiftedIcons);
1418da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka        mUnshiftedIcons = Collections.unmodifiableMap(params.mUnshiftedIcons);
1428da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka        mIconsSet = params.mIconsSet;
1435a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka
1440d5494c66ac3e5947040e8148091163a1c8716f7satok        mProximityInfo = new ProximityInfo(
1458da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka                params.GRID_WIDTH, params.GRID_HEIGHT, mOccupiedWidth, mOccupiedHeight,
146294e1b4a5abb86e58deefc8eee40e6b661524b28Yusuke Nojima                mMostCommonKeyWidth, mMostCommonKeyHeight, mKeys, params.mTouchPositionCorrection);
1478fbd55229243cb66c03d5ea1f79dfb39f596590dsatok    }
1488fbd55229243cb66c03d5ea1f79dfb39f596590dsatok
149043f7841985916717f4fa821fe3e423daf3ff2f5Jean Chalard    public ProximityInfo getProximityInfo() {
150043f7841985916717f4fa821fe3e423daf3ff2f5Jean Chalard        return mProximityInfo;
1515a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka    }
1525a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka
1532013bab89ca2f82589f99d98d9cf3b41ea5aac65Tadashi G. Takaoka    public Key getKey(int code) {
154623d0155b6a316fdc9335370cdd4005bbb474ef3Tadashi G. Takaoka        if (code == CODE_DUMMY) {
155623d0155b6a316fdc9335370cdd4005bbb474ef3Tadashi G. Takaoka            return null;
156623d0155b6a316fdc9335370cdd4005bbb474ef3Tadashi G. Takaoka        }
1572013bab89ca2f82589f99d98d9cf3b41ea5aac65Tadashi G. Takaoka        final Integer keyCode = code;
1582013bab89ca2f82589f99d98d9cf3b41ea5aac65Tadashi G. Takaoka        if (mKeyCache.containsKey(keyCode)) {
1592013bab89ca2f82589f99d98d9cf3b41ea5aac65Tadashi G. Takaoka            return mKeyCache.get(keyCode);
1602013bab89ca2f82589f99d98d9cf3b41ea5aac65Tadashi G. Takaoka        }
1612013bab89ca2f82589f99d98d9cf3b41ea5aac65Tadashi G. Takaoka
1622013bab89ca2f82589f99d98d9cf3b41ea5aac65Tadashi G. Takaoka        for (final Key key : mKeys) {
1632013bab89ca2f82589f99d98d9cf3b41ea5aac65Tadashi G. Takaoka            if (key.mCode == code) {
1642013bab89ca2f82589f99d98d9cf3b41ea5aac65Tadashi G. Takaoka                mKeyCache.put(keyCode, key);
1652013bab89ca2f82589f99d98d9cf3b41ea5aac65Tadashi G. Takaoka                return key;
1662013bab89ca2f82589f99d98d9cf3b41ea5aac65Tadashi G. Takaoka            }
1672013bab89ca2f82589f99d98d9cf3b41ea5aac65Tadashi G. Takaoka        }
1682013bab89ca2f82589f99d98d9cf3b41ea5aac65Tadashi G. Takaoka        mKeyCache.put(keyCode, null);
1692013bab89ca2f82589f99d98d9cf3b41ea5aac65Tadashi G. Takaoka        return null;
1702013bab89ca2f82589f99d98d9cf3b41ea5aac65Tadashi G. Takaoka    }
1712013bab89ca2f82589f99d98d9cf3b41ea5aac65Tadashi G. Takaoka
172c1859b8fd22b2c4cc2a700566f57f3e3d04e1580Tadashi G. Takaoka    // TODO: Remove this method.
1736d9bcd5e1317722207116ab6a3ddfcb152005701Tadashi G. Takaoka    public boolean hasShiftLockKey() {
1746d9bcd5e1317722207116ab6a3ddfcb152005701Tadashi G. Takaoka        return !mShiftLockKeys.isEmpty();
175571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka    }
176571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka
177c1859b8fd22b2c4cc2a700566f57f3e3d04e1580Tadashi G. Takaoka    // TODO: Remove this method.
1784f7f61730cbd45871c1e9044da84b494831f97c3Tadashi G. Takaoka    public void setShiftLocked(boolean newShiftLockState) {
1796d9bcd5e1317722207116ab6a3ddfcb152005701Tadashi G. Takaoka        for (final Key key : mShiftLockKeys) {
1806d9bcd5e1317722207116ab6a3ddfcb152005701Tadashi G. Takaoka            // To represent "shift locked" state. The highlight is handled by background image that
1816d9bcd5e1317722207116ab6a3ddfcb152005701Tadashi G. Takaoka            // might be a StateListDrawable.
182e7759091ddb5ec18268945d70d9212195bf6497bTadashi G. Takaoka            key.setHighlightOn(newShiftLockState);
1834f7f61730cbd45871c1e9044da84b494831f97c3Tadashi G. Takaoka            key.setIcon(newShiftLockState ? mShiftedIcons.get(key) : mUnshiftedIcons.get(key));
184571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka        }
185e466583ddc68278ad708094f8ac521be504bf342Tadashi G. Takaoka        mShiftState.setShiftLocked(newShiftLockState);
186571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka    }
187571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka
188c1859b8fd22b2c4cc2a700566f57f3e3d04e1580Tadashi G. Takaoka    // TODO: Move this method to KeyboardId.
189571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka    public boolean isShiftLocked() {
190e466583ddc68278ad708094f8ac521be504bf342Tadashi G. Takaoka        return mShiftState.isShiftLocked();
191571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka    }
192571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka
193c1859b8fd22b2c4cc2a700566f57f3e3d04e1580Tadashi G. Takaoka    // TODO: Remove this method.
194c1859b8fd22b2c4cc2a700566f57f3e3d04e1580Tadashi G. Takaoka    public void setShifted(boolean newShiftState) {
195e466583ddc68278ad708094f8ac521be504bf342Tadashi G. Takaoka        if (!mShiftState.isShiftLocked()) {
1964f7f61730cbd45871c1e9044da84b494831f97c3Tadashi G. Takaoka            for (final Key key : mShiftKeys) {
1974f7f61730cbd45871c1e9044da84b494831f97c3Tadashi G. Takaoka                key.setIcon(newShiftState ? mShiftedIcons.get(key) : mUnshiftedIcons.get(key));
198571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka            }
1995a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka        }
200e466583ddc68278ad708094f8ac521be504bf342Tadashi G. Takaoka        mShiftState.setShifted(newShiftState);
2015a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka    }
2025a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka
203c1859b8fd22b2c4cc2a700566f57f3e3d04e1580Tadashi G. Takaoka    // TODO: Move this method to KeyboardId.
2045a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka    public boolean isShiftedOrShiftLocked() {
205e466583ddc68278ad708094f8ac521be504bf342Tadashi G. Takaoka        return mShiftState.isShiftedOrShiftLocked();
2065a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka    }
2075a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka
208c1859b8fd22b2c4cc2a700566f57f3e3d04e1580Tadashi G. Takaoka    // TODO: Remove this method
209571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka    public void setAutomaticTemporaryUpperCase() {
210e466583ddc68278ad708094f8ac521be504bf342Tadashi G. Takaoka        mShiftState.setAutomaticTemporaryUpperCase();
211571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka    }
212571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka
213c1859b8fd22b2c4cc2a700566f57f3e3d04e1580Tadashi G. Takaoka    // TODO: Move this method to KeyboardId.
214571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka    public boolean isManualTemporaryUpperCase() {
215e466583ddc68278ad708094f8ac521be504bf342Tadashi G. Takaoka        return mShiftState.isManualTemporaryUpperCase();
216571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka    }
217571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka
218c1859b8fd22b2c4cc2a700566f57f3e3d04e1580Tadashi G. Takaoka    // TODO: Remove this method.
219d773bf38a3c8f49ea56de67d3b828f8126f46ed2Tadashi G. Takaoka    public CharSequence adjustLabelCase(CharSequence label) {
220d773bf38a3c8f49ea56de67d3b828f8126f46ed2Tadashi G. Takaoka        if (isShiftedOrShiftLocked() && !TextUtils.isEmpty(label) && label.length() < 3
221d773bf38a3c8f49ea56de67d3b828f8126f46ed2Tadashi G. Takaoka                && Character.isLowerCase(label.charAt(0))) {
222d773bf38a3c8f49ea56de67d3b828f8126f46ed2Tadashi G. Takaoka            return label.toString().toUpperCase(mId.mLocale);
223d773bf38a3c8f49ea56de67d3b828f8126f46ed2Tadashi G. Takaoka        }
224d773bf38a3c8f49ea56de67d3b828f8126f46ed2Tadashi G. Takaoka        return label;
225571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka    }
226571bdb401f670b92bd7710a12a990cb65a99b7d3Tadashi G. Takaoka
2275a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka    /**
2285a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka     * Returns the indices of the keys that are closest to the given point.
2295a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka     * @param x the x-coordinate of the point
2305a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka     * @param y the y-coordinate of the point
2315a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka     * @return the array of integer indices for the nearest keys to the given point. If the given
2325a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka     * point is out of range, then an array of size zero is returned.
2335a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka     */
2345a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka    public int[] getNearestKeys(int x, int y) {
2350d5494c66ac3e5947040e8148091163a1c8716f7satok        return mProximityInfo.getNearestKeys(x, y);
2365a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka    }
23763584323cab56c76debf6bb000621f2c605329a9Tadashi G. Takaoka
23863584323cab56c76debf6bb000621f2c605329a9Tadashi G. Takaoka    public static String themeName(int themeId) {
23963584323cab56c76debf6bb000621f2c605329a9Tadashi G. Takaoka        // This should be aligned with theme-*.xml resource files' themeId attribute.
24063584323cab56c76debf6bb000621f2c605329a9Tadashi G. Takaoka        switch (themeId) {
24163584323cab56c76debf6bb000621f2c605329a9Tadashi G. Takaoka        case 0: return "Basic";
24263584323cab56c76debf6bb000621f2c605329a9Tadashi G. Takaoka        case 1: return "BasicHighContrast";
24363584323cab56c76debf6bb000621f2c605329a9Tadashi G. Takaoka        case 5: return "IceCreamSandwich";
24463584323cab56c76debf6bb000621f2c605329a9Tadashi G. Takaoka        case 6: return "Stone";
24563584323cab56c76debf6bb000621f2c605329a9Tadashi G. Takaoka        case 7: return "StoneBold";
24663584323cab56c76debf6bb000621f2c605329a9Tadashi G. Takaoka        case 8: return "GingerBread";
24763584323cab56c76debf6bb000621f2c605329a9Tadashi G. Takaoka        default: return null;
24863584323cab56c76debf6bb000621f2c605329a9Tadashi G. Takaoka        }
24963584323cab56c76debf6bb000621f2c605329a9Tadashi G. Takaoka    }
2507dfd5a3e833e14d5bf90d728d5a50b40c8a927d2Tadashi G. Takaoka
2517dfd5a3e833e14d5bf90d728d5a50b40c8a927d2Tadashi G. Takaoka    public static String printableCode(int code) {
2527dfd5a3e833e14d5bf90d728d5a50b40c8a927d2Tadashi G. Takaoka        switch (code) {
2537dfd5a3e833e14d5bf90d728d5a50b40c8a927d2Tadashi G. Takaoka        case CODE_SHIFT: return "shift";
2547dfd5a3e833e14d5bf90d728d5a50b40c8a927d2Tadashi G. Takaoka        case CODE_SWITCH_ALPHA_SYMBOL: return "symbol";
2557dfd5a3e833e14d5bf90d728d5a50b40c8a927d2Tadashi G. Takaoka        case CODE_CAPSLOCK: return "capslock";
2567dfd5a3e833e14d5bf90d728d5a50b40c8a927d2Tadashi G. Takaoka        case CODE_DELETE: return "delete";
2577dfd5a3e833e14d5bf90d728d5a50b40c8a927d2Tadashi G. Takaoka        case CODE_SHORTCUT: return "shortcut";
2587dfd5a3e833e14d5bf90d728d5a50b40c8a927d2Tadashi G. Takaoka        case CODE_DUMMY: return "dummy";
2597dfd5a3e833e14d5bf90d728d5a50b40c8a927d2Tadashi G. Takaoka        case CODE_UNSPECIFIED: return "unspec";
2607dfd5a3e833e14d5bf90d728d5a50b40c8a927d2Tadashi G. Takaoka        default:
2617dfd5a3e833e14d5bf90d728d5a50b40c8a927d2Tadashi G. Takaoka            if (code < 0) Log.w(TAG, "Unknow negative key code=" + code);
2627dfd5a3e833e14d5bf90d728d5a50b40c8a927d2Tadashi G. Takaoka            if (code < 0x100) return String.format("\\u%02x", code);
2637dfd5a3e833e14d5bf90d728d5a50b40c8a927d2Tadashi G. Takaoka            return String.format("\\u04x", code);
2647dfd5a3e833e14d5bf90d728d5a50b40c8a927d2Tadashi G. Takaoka        }
2657dfd5a3e833e14d5bf90d728d5a50b40c8a927d2Tadashi G. Takaoka    }
2665a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka}
267