15a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka/* 28632bff2d5a8e1160989008dea6eff4b94b065ddTadashi G. Takaoka * Copyright (C) 2010 The Android Open Source Project 35a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka * 48aa9963a895f9dd5bb1bc92ab2e4f461e058f87aTadashi G. Takaoka * Licensed under the Apache License, Version 2.0 (the "License"); 58aa9963a895f9dd5bb1bc92ab2e4f461e058f87aTadashi G. Takaoka * you may not use this file except in compliance with the License. 68aa9963a895f9dd5bb1bc92ab2e4f461e058f87aTadashi G. Takaoka * You may obtain a copy of the License at 75a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka * 88aa9963a895f9dd5bb1bc92ab2e4f461e058f87aTadashi 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 118aa9963a895f9dd5bb1bc92ab2e4f461e058f87aTadashi G. Takaoka * distributed under the License is distributed on an "AS IS" BASIS, 128aa9963a895f9dd5bb1bc92ab2e4f461e058f87aTadashi G. Takaoka * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 138aa9963a895f9dd5bb1bc92ab2e4f461e058f87aTadashi G. Takaoka * See the License for the specific language governing permissions and 148aa9963a895f9dd5bb1bc92ab2e4f461e058f87aTadashi G. Takaoka * limitations under the License. 155a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka */ 165a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka 175a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaokapackage com.android.inputmethod.keyboard; 185a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka 1956853c1e48deb71367104060b49b7b1f0344a476Tadashi G. Takaokaimport android.util.SparseArray; 205a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka 21dc34da218a22489d92d1015e9e5dac8d951b89f4Tadashi G. Takaokaimport com.android.inputmethod.keyboard.internal.KeyVisualAttributes; 22c2a21786e526cc32e48a577a55b1b7e72ae1a6ddTadashi G. Takaokaimport com.android.inputmethod.keyboard.internal.KeyboardIconsSet; 2335ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaokaimport com.android.inputmethod.keyboard.internal.KeyboardParams; 24240871ecafde7834ebb4270cd7758fc904a5f3a7Tadashi G. Takaokaimport com.android.inputmethod.latin.Constants; 251d6e647ac31eab38f30b8ed468551d1e3a07c705Jean Chalardimport com.android.inputmethod.latin.utils.CoordinateUtils; 26b7758d6f912093747d4b18fbc8d1dcd77c7d1f9bTadashi G. Takaoka 27a91561aa58db1c43092c1caecc051a11fa5391c7Tadashi G. Takaokaimport java.util.ArrayList; 28064af5c0fc07b3afae3021d42fcac2185158c951Tadashi G. Takaokaimport java.util.Collections; 29064af5c0fc07b3afae3021d42fcac2185158c951Tadashi G. Takaokaimport java.util.List; 30064af5c0fc07b3afae3021d42fcac2185158c951Tadashi G. Takaoka 315a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka/** 325a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka * Loads an XML description of a keyboard and stores the attributes of the keys. A keyboard 335a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka * consists of rows of keys. 345a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka * <p>The layout file for a keyboard contains XML that looks like the following snippet:</p> 355a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka * <pre> 365a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka * <Keyboard 375ee2d79e41872610946b5a5c1caf14f3e5696c26Tadashi G. Takaoka * latin:keyWidth="10%p" 385ee2d79e41872610946b5a5c1caf14f3e5696c26Tadashi G. Takaoka * latin:rowHeight="50px" 395ee2d79e41872610946b5a5c1caf14f3e5696c26Tadashi G. Takaoka * latin:horizontalGap="2%p" 405ee2d79e41872610946b5a5c1caf14f3e5696c26Tadashi G. Takaoka * latin:verticalGap="2%p" > 415ee2d79e41872610946b5a5c1caf14f3e5696c26Tadashi G. Takaoka * <Row latin:keyWidth="10%p" > 425a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka * <Key latin:keyLabel="A" /> 435a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka * ... 445a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka * </Row> 455a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka * ... 465a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka * </Keyboard> 475a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka * </pre> 485a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka */ 495a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaokapublic class Keyboard { 50167e77f17084da5c223a3a790d3dd3d749e68ae3Tadashi G. Takaoka public final KeyboardId mId; 5163584323cab56c76debf6bb000621f2c605329a9Tadashi G. Takaoka public final int mThemeId; 52167e77f17084da5c223a3a790d3dd3d749e68ae3Tadashi G. Takaoka 53167e77f17084da5c223a3a790d3dd3d749e68ae3Tadashi G. Takaoka /** Total height of the keyboard, including the padding and keys */ 548da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka public final int mOccupiedHeight; 558da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka /** Total width of the keyboard, including the padding and keys */ 568da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka public final int mOccupiedWidth; 57167e77f17084da5c223a3a790d3dd3d749e68ae3Tadashi G. Takaoka 582f5a933c04252257bc2ec747948017da40d4a484Tadashi G. Takaoka /** Base height of the keyboard, used to calculate rows' height */ 592f5a933c04252257bc2ec747948017da40d4a484Tadashi G. Takaoka public final int mBaseHeight; 602f5a933c04252257bc2ec747948017da40d4a484Tadashi G. Takaoka /** Base width of the keyboard, used to calculate keys' width */ 612f5a933c04252257bc2ec747948017da40d4a484Tadashi G. Takaoka public final int mBaseWidth; 622f5a933c04252257bc2ec747948017da40d4a484Tadashi G. Takaoka 638fbfac4ffb7079e8e71fd4e3ddc04e362239ebb3Tadashi G. Takaoka /** The padding above the keyboard */ 648fbfac4ffb7079e8e71fd4e3ddc04e362239ebb3Tadashi G. Takaoka public final int mTopPadding; 655a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka /** Default gap between rows */ 668da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka public final int mVerticalGap; 678da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka 68d20652c878aae2e0e46a33310672a2786ee55b0cTadashi G. Takaoka /** Per keyboard key visual parameters */ 69dc34da218a22489d92d1015e9e5dac8d951b89f4Tadashi G. Takaoka public final KeyVisualAttributes mKeyVisualAttributes; 70d20652c878aae2e0e46a33310672a2786ee55b0cTadashi G. Takaoka 718fbfac4ffb7079e8e71fd4e3ddc04e362239ebb3Tadashi G. Takaoka public final int mMostCommonKeyHeight; 728da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka public final int mMostCommonKeyWidth; 735a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka 749d5601e9013c5ec9a7ac75db16f4a0a8218b02bfTadashi G. Takaoka /** More keys keyboard template */ 759d5601e9013c5ec9a7ac75db16f4a0a8218b02bfTadashi G. Takaoka public final int mMoreKeysTemplate; 769b6d1d52d91f8f18952ae3841f4bb0d7309bfc0eTadashi G. Takaoka 772affaf91a04d63e0994102299816014a8bbe11e1Tadashi G. Takaoka /** Maximum column for more keys keyboard */ 782affaf91a04d63e0994102299816014a8bbe11e1Tadashi G. Takaoka public final int mMaxMoreKeysKeyboardColumn; 799b6d1d52d91f8f18952ae3841f4bb0d7309bfc0eTadashi G. Takaoka 805326dcfb7dbdc1a3fc9cfb94046805f18bf3d3d7Tadashi G. Takaoka /** List of keys in this keyboard */ 81c13c1adfa72227b0006add5f13f555fbb9c9eb4eTadashi G. Takaoka private final List<Key> mSortedKeys; 82064af5c0fc07b3afae3021d42fcac2185158c951Tadashi G. Takaoka public final List<Key> mShiftKeys; 83064af5c0fc07b3afae3021d42fcac2185158c951Tadashi G. Takaoka public final List<Key> mAltCodeKeysWhileTyping; 848da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka public final KeyboardIconsSet mIconsSet; 856fb97bf71cee2a0775410a05478ed6a667aa847fTadashi G. Takaoka 86a91561aa58db1c43092c1caecc051a11fa5391c7Tadashi G. Takaoka private final SparseArray<Key> mKeyCache = new SparseArray<>(); 87c2a21786e526cc32e48a577a55b1b7e72ae1a6ddTadashi G. Takaoka 888fbd55229243cb66c03d5ea1f79dfb39f596590dsatok private final ProximityInfo mProximityInfo; 898dcad2ed4776b849ddacb623a94b4301afcf055aTadashi G. Takaoka private final boolean mProximityCharsCorrectionEnabled; 908fbd55229243cb66c03d5ea1f79dfb39f596590dsatok 9135ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka public Keyboard(final KeyboardParams params) { 928da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka mId = params.mId; 9363584323cab56c76debf6bb000621f2c605329a9Tadashi G. Takaoka mThemeId = params.mThemeId; 948da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka mOccupiedHeight = params.mOccupiedHeight; 958da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka mOccupiedWidth = params.mOccupiedWidth; 962f5a933c04252257bc2ec747948017da40d4a484Tadashi G. Takaoka mBaseHeight = params.mBaseHeight; 972f5a933c04252257bc2ec747948017da40d4a484Tadashi G. Takaoka mBaseWidth = params.mBaseWidth; 988fbfac4ffb7079e8e71fd4e3ddc04e362239ebb3Tadashi G. Takaoka mMostCommonKeyHeight = params.mMostCommonKeyHeight; 998da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka mMostCommonKeyWidth = params.mMostCommonKeyWidth; 1009d5601e9013c5ec9a7ac75db16f4a0a8218b02bfTadashi G. Takaoka mMoreKeysTemplate = params.mMoreKeysTemplate; 1012affaf91a04d63e0994102299816014a8bbe11e1Tadashi G. Takaoka mMaxMoreKeysKeyboardColumn = params.mMaxMoreKeysKeyboardColumn; 102dc34da218a22489d92d1015e9e5dac8d951b89f4Tadashi G. Takaoka mKeyVisualAttributes = params.mKeyVisualAttributes; 1038fbfac4ffb7079e8e71fd4e3ddc04e362239ebb3Tadashi G. Takaoka mTopPadding = params.mTopPadding; 1048da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka mVerticalGap = params.mVerticalGap; 1058da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka 106a91561aa58db1c43092c1caecc051a11fa5391c7Tadashi G. Takaoka mSortedKeys = Collections.unmodifiableList(new ArrayList<>(params.mSortedKeys)); 107064af5c0fc07b3afae3021d42fcac2185158c951Tadashi G. Takaoka mShiftKeys = Collections.unmodifiableList(params.mShiftKeys); 108064af5c0fc07b3afae3021d42fcac2185158c951Tadashi G. Takaoka mAltCodeKeysWhileTyping = Collections.unmodifiableList(params.mAltCodeKeysWhileTyping); 1098da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka mIconsSet = params.mIconsSet; 1105a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka 1117ef1dabd92a9dae042965cd10d08a2cd47455dccsatok mProximityInfo = new ProximityInfo(params.mId.mLocale.toString(), 1128da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka params.GRID_WIDTH, params.GRID_HEIGHT, mOccupiedWidth, mOccupiedHeight, 113c13c1adfa72227b0006add5f13f555fbb9c9eb4eTadashi G. Takaoka mMostCommonKeyWidth, mMostCommonKeyHeight, mSortedKeys, 114c13c1adfa72227b0006add5f13f555fbb9c9eb4eTadashi G. Takaoka params.mTouchPositionCorrection); 1158dcad2ed4776b849ddacb623a94b4301afcf055aTadashi G. Takaoka mProximityCharsCorrectionEnabled = params.mProximityCharsCorrectionEnabled; 1168dcad2ed4776b849ddacb623a94b4301afcf055aTadashi G. Takaoka } 1178dcad2ed4776b849ddacb623a94b4301afcf055aTadashi G. Takaoka 1180b3d5e12e38291e7f06a1a5cdf157af61217465fTadashi G. Takaoka protected Keyboard(final Keyboard keyboard) { 1190b3d5e12e38291e7f06a1a5cdf157af61217465fTadashi G. Takaoka mId = keyboard.mId; 1200b3d5e12e38291e7f06a1a5cdf157af61217465fTadashi G. Takaoka mThemeId = keyboard.mThemeId; 1210b3d5e12e38291e7f06a1a5cdf157af61217465fTadashi G. Takaoka mOccupiedHeight = keyboard.mOccupiedHeight; 1220b3d5e12e38291e7f06a1a5cdf157af61217465fTadashi G. Takaoka mOccupiedWidth = keyboard.mOccupiedWidth; 1232f5a933c04252257bc2ec747948017da40d4a484Tadashi G. Takaoka mBaseHeight = keyboard.mBaseHeight; 1242f5a933c04252257bc2ec747948017da40d4a484Tadashi G. Takaoka mBaseWidth = keyboard.mBaseWidth; 1250b3d5e12e38291e7f06a1a5cdf157af61217465fTadashi G. Takaoka mMostCommonKeyHeight = keyboard.mMostCommonKeyHeight; 1260b3d5e12e38291e7f06a1a5cdf157af61217465fTadashi G. Takaoka mMostCommonKeyWidth = keyboard.mMostCommonKeyWidth; 1270b3d5e12e38291e7f06a1a5cdf157af61217465fTadashi G. Takaoka mMoreKeysTemplate = keyboard.mMoreKeysTemplate; 1280b3d5e12e38291e7f06a1a5cdf157af61217465fTadashi G. Takaoka mMaxMoreKeysKeyboardColumn = keyboard.mMaxMoreKeysKeyboardColumn; 1290b3d5e12e38291e7f06a1a5cdf157af61217465fTadashi G. Takaoka mKeyVisualAttributes = keyboard.mKeyVisualAttributes; 1300b3d5e12e38291e7f06a1a5cdf157af61217465fTadashi G. Takaoka mTopPadding = keyboard.mTopPadding; 1310b3d5e12e38291e7f06a1a5cdf157af61217465fTadashi G. Takaoka mVerticalGap = keyboard.mVerticalGap; 1320b3d5e12e38291e7f06a1a5cdf157af61217465fTadashi G. Takaoka 133c13c1adfa72227b0006add5f13f555fbb9c9eb4eTadashi G. Takaoka mSortedKeys = keyboard.mSortedKeys; 1340b3d5e12e38291e7f06a1a5cdf157af61217465fTadashi G. Takaoka mShiftKeys = keyboard.mShiftKeys; 1350b3d5e12e38291e7f06a1a5cdf157af61217465fTadashi G. Takaoka mAltCodeKeysWhileTyping = keyboard.mAltCodeKeysWhileTyping; 1360b3d5e12e38291e7f06a1a5cdf157af61217465fTadashi G. Takaoka mIconsSet = keyboard.mIconsSet; 1370b3d5e12e38291e7f06a1a5cdf157af61217465fTadashi G. Takaoka 1380b3d5e12e38291e7f06a1a5cdf157af61217465fTadashi G. Takaoka mProximityInfo = keyboard.mProximityInfo; 1390b3d5e12e38291e7f06a1a5cdf157af61217465fTadashi G. Takaoka mProximityCharsCorrectionEnabled = keyboard.mProximityCharsCorrectionEnabled; 1400b3d5e12e38291e7f06a1a5cdf157af61217465fTadashi G. Takaoka } 1410b3d5e12e38291e7f06a1a5cdf157af61217465fTadashi G. Takaoka 14235ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka public boolean hasProximityCharsCorrection(final int code) { 1438dcad2ed4776b849ddacb623a94b4301afcf055aTadashi G. Takaoka if (!mProximityCharsCorrectionEnabled) { 1448dcad2ed4776b849ddacb623a94b4301afcf055aTadashi G. Takaoka return false; 1458dcad2ed4776b849ddacb623a94b4301afcf055aTadashi G. Takaoka } 1468dcad2ed4776b849ddacb623a94b4301afcf055aTadashi G. Takaoka // Note: The native code has the main keyboard layout only at this moment. 1478dcad2ed4776b849ddacb623a94b4301afcf055aTadashi G. Takaoka // TODO: Figure out how to handle proximity characters information of all layouts. 1488dcad2ed4776b849ddacb623a94b4301afcf055aTadashi G. Takaoka final boolean canAssumeNativeHasProximityCharsInfoOfAllKeys = ( 1498dcad2ed4776b849ddacb623a94b4301afcf055aTadashi G. Takaoka mId.mElementId == KeyboardId.ELEMENT_ALPHABET 1508dcad2ed4776b849ddacb623a94b4301afcf055aTadashi G. Takaoka || mId.mElementId == KeyboardId.ELEMENT_ALPHABET_AUTOMATIC_SHIFTED); 1518dcad2ed4776b849ddacb623a94b4301afcf055aTadashi G. Takaoka return canAssumeNativeHasProximityCharsInfoOfAllKeys || Character.isLetter(code); 1528fbd55229243cb66c03d5ea1f79dfb39f596590dsatok } 1538fbd55229243cb66c03d5ea1f79dfb39f596590dsatok 154043f7841985916717f4fa821fe3e423daf3ff2f5Jean Chalard public ProximityInfo getProximityInfo() { 155043f7841985916717f4fa821fe3e423daf3ff2f5Jean Chalard return mProximityInfo; 1565a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka } 1575a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka 158c13c1adfa72227b0006add5f13f555fbb9c9eb4eTadashi G. Takaoka /** 159c13c1adfa72227b0006add5f13f555fbb9c9eb4eTadashi G. Takaoka * Return the sorted list of keys of this keyboard. 160c13c1adfa72227b0006add5f13f555fbb9c9eb4eTadashi G. Takaoka * The keys are sorted from top-left to bottom-right order. 161a91561aa58db1c43092c1caecc051a11fa5391c7Tadashi G. Takaoka * The list may contain {@link Key.Spacer} object as well. 162c13c1adfa72227b0006add5f13f555fbb9c9eb4eTadashi G. Takaoka * @return the sorted unmodifiable list of {@link Key}s of this keyboard. 163c13c1adfa72227b0006add5f13f555fbb9c9eb4eTadashi G. Takaoka */ 164c13c1adfa72227b0006add5f13f555fbb9c9eb4eTadashi G. Takaoka public List<Key> getSortedKeys() { 165c13c1adfa72227b0006add5f13f555fbb9c9eb4eTadashi G. Takaoka return mSortedKeys; 1660b3d5e12e38291e7f06a1a5cdf157af61217465fTadashi G. Takaoka } 1670b3d5e12e38291e7f06a1a5cdf157af61217465fTadashi G. Takaoka 16835ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka public Key getKey(final int code) { 169240871ecafde7834ebb4270cd7758fc904a5f3a7Tadashi G. Takaoka if (code == Constants.CODE_UNSPECIFIED) { 170623d0155b6a316fdc9335370cdd4005bbb474ef3Tadashi G. Takaoka return null; 171623d0155b6a316fdc9335370cdd4005bbb474ef3Tadashi G. Takaoka } 1728f6c603b3bc9b1f81a0ab2299429d725b463b92fTadashi G. Takaoka synchronized (mKeyCache) { 1738f6c603b3bc9b1f81a0ab2299429d725b463b92fTadashi G. Takaoka final int index = mKeyCache.indexOfKey(code); 1748f6c603b3bc9b1f81a0ab2299429d725b463b92fTadashi G. Takaoka if (index >= 0) { 1758f6c603b3bc9b1f81a0ab2299429d725b463b92fTadashi G. Takaoka return mKeyCache.valueAt(index); 1768f6c603b3bc9b1f81a0ab2299429d725b463b92fTadashi G. Takaoka } 1772013bab89ca2f82589f99d98d9cf3b41ea5aac65Tadashi G. Takaoka 178c13c1adfa72227b0006add5f13f555fbb9c9eb4eTadashi G. Takaoka for (final Key key : getSortedKeys()) { 1797dc60f9db729e93cb591492574a436418c553ebfTadashi G. Takaoka if (key.getCode() == code) { 1808f6c603b3bc9b1f81a0ab2299429d725b463b92fTadashi G. Takaoka mKeyCache.put(code, key); 1818f6c603b3bc9b1f81a0ab2299429d725b463b92fTadashi G. Takaoka return key; 1828f6c603b3bc9b1f81a0ab2299429d725b463b92fTadashi G. Takaoka } 1832013bab89ca2f82589f99d98d9cf3b41ea5aac65Tadashi G. Takaoka } 1848f6c603b3bc9b1f81a0ab2299429d725b463b92fTadashi G. Takaoka mKeyCache.put(code, null); 1858f6c603b3bc9b1f81a0ab2299429d725b463b92fTadashi G. Takaoka return null; 1862013bab89ca2f82589f99d98d9cf3b41ea5aac65Tadashi G. Takaoka } 1872013bab89ca2f82589f99d98d9cf3b41ea5aac65Tadashi G. Takaoka } 1882013bab89ca2f82589f99d98d9cf3b41ea5aac65Tadashi G. Takaoka 18935ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka public boolean hasKey(final Key aKey) { 19056853c1e48deb71367104060b49b7b1f0344a476Tadashi G. Takaoka if (mKeyCache.indexOfValue(aKey) >= 0) { 191b7a5a6820038824568dc5251ae5080b34a4933b8Tadashi G. Takaoka return true; 192b7a5a6820038824568dc5251ae5080b34a4933b8Tadashi G. Takaoka } 193b7a5a6820038824568dc5251ae5080b34a4933b8Tadashi G. Takaoka 194c13c1adfa72227b0006add5f13f555fbb9c9eb4eTadashi G. Takaoka for (final Key key : getSortedKeys()) { 195b7a5a6820038824568dc5251ae5080b34a4933b8Tadashi G. Takaoka if (key == aKey) { 1967dc60f9db729e93cb591492574a436418c553ebfTadashi G. Takaoka mKeyCache.put(key.getCode(), key); 197b7a5a6820038824568dc5251ae5080b34a4933b8Tadashi G. Takaoka return true; 198b7a5a6820038824568dc5251ae5080b34a4933b8Tadashi G. Takaoka } 199b7a5a6820038824568dc5251ae5080b34a4933b8Tadashi G. Takaoka } 200b7a5a6820038824568dc5251ae5080b34a4933b8Tadashi G. Takaoka return false; 201b7a5a6820038824568dc5251ae5080b34a4933b8Tadashi G. Takaoka } 202b7a5a6820038824568dc5251ae5080b34a4933b8Tadashi G. Takaoka 20335336cf83a434514c60d79389ceb818cba642506Tadashi G. Takaoka @Override 20435336cf83a434514c60d79389ceb818cba642506Tadashi G. Takaoka public String toString() { 20535336cf83a434514c60d79389ceb818cba642506Tadashi G. Takaoka return mId.toString(); 20635336cf83a434514c60d79389ceb818cba642506Tadashi G. Takaoka } 20735336cf83a434514c60d79389ceb818cba642506Tadashi G. Takaoka 2085a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka /** 2090c0ca874febee38fb5cb2c85c11ddd46cdf2b859Tadashi G. Takaoka * Returns the array of the keys that are closest to the given point. 2105a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka * @param x the x-coordinate of the point 2115a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka * @param y the y-coordinate of the point 21258d4e610ac705fbfb49d8ec8d893a35ac416668eTadashi G. Takaoka * @return the list of the nearest keys to the given point. If the given 2135a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka * point is out of range, then an array of size zero is returned. 2145a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka */ 21558d4e610ac705fbfb49d8ec8d893a35ac416668eTadashi G. Takaoka public List<Key> getNearestKeys(final int x, final int y) { 2164f7d278af62a89ef3f45cc9ebbfb076a5a352c76Ken Wakasa // Avoid dead pixels at edges of the keyboard 2174f7d278af62a89ef3f45cc9ebbfb076a5a352c76Ken Wakasa final int adjustedX = Math.max(0, Math.min(x, mOccupiedWidth - 1)); 2184f7d278af62a89ef3f45cc9ebbfb076a5a352c76Ken Wakasa final int adjustedY = Math.max(0, Math.min(y, mOccupiedHeight - 1)); 2194f7d278af62a89ef3f45cc9ebbfb076a5a352c76Ken Wakasa return mProximityInfo.getNearestKeys(adjustedX, adjustedY); 2205a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka } 2211d6e647ac31eab38f30b8ed468551d1e3a07c705Jean Chalard 2221d6e647ac31eab38f30b8ed468551d1e3a07c705Jean Chalard public int[] getCoordinates(final int[] codePoints) { 2231d6e647ac31eab38f30b8ed468551d1e3a07c705Jean Chalard final int length = codePoints.length; 2241d6e647ac31eab38f30b8ed468551d1e3a07c705Jean Chalard final int[] coordinates = CoordinateUtils.newCoordinateArray(length); 2251d6e647ac31eab38f30b8ed468551d1e3a07c705Jean Chalard for (int i = 0; i < length; ++i) { 2261d6e647ac31eab38f30b8ed468551d1e3a07c705Jean Chalard final Key key = getKey(codePoints[i]); 2271d6e647ac31eab38f30b8ed468551d1e3a07c705Jean Chalard if (null != key) { 2281d6e647ac31eab38f30b8ed468551d1e3a07c705Jean Chalard CoordinateUtils.setXYInArray(coordinates, i, 2291d6e647ac31eab38f30b8ed468551d1e3a07c705Jean Chalard key.getX() + key.getWidth() / 2, key.getY() + key.getHeight() / 2); 2301d6e647ac31eab38f30b8ed468551d1e3a07c705Jean Chalard } else { 2311d6e647ac31eab38f30b8ed468551d1e3a07c705Jean Chalard CoordinateUtils.setXYInArray(coordinates, i, 2321d6e647ac31eab38f30b8ed468551d1e3a07c705Jean Chalard Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE); 2331d6e647ac31eab38f30b8ed468551d1e3a07c705Jean Chalard } 2341d6e647ac31eab38f30b8ed468551d1e3a07c705Jean Chalard } 2351d6e647ac31eab38f30b8ed468551d1e3a07c705Jean Chalard return coordinates; 2361d6e647ac31eab38f30b8ed468551d1e3a07c705Jean Chalard } 2375a309f57155fb95667c2ccdda730eaf175de8876Tadashi G. Takaoka} 238