19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2008-2009 Google Inc. 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); you may not 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * use this file except in compliance with the License. You may obtain a copy of 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * License for the specific language governing permissions and limitations under 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.inputmethodservice; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.xmlpull.v1.XmlPullParserException; 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 217b9c912f536925ac6ec43935d6e97506851b33d6Tor Norbyeimport android.annotation.XmlRes; 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context; 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.Resources; 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.TypedArray; 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.XmlResourceParser; 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.drawable.Drawable; 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.TextUtils; 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log; 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.TypedValue; 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Xml; 3158feea74b42bbaaa0552d76af23873bdd0b5dca2Mitsuru Oshimaimport android.util.DisplayMetrics; 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException; 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList; 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.List; 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.StringTokenizer; 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Loads an XML description of a keyboard and stores the attributes of the keys. A keyboard 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * consists of rows of keys. 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>The layout file for a keyboard contains XML that looks like the following snippet:</p> 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <pre> 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <Keyboard 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * android:keyWidth="%10p" 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * android:keyHeight="50px" 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * android:horizontalGap="2px" 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * android:verticalGap="2px" > 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <Row android:keyWidth="32px" > 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <Key android:keyLabel="A" /> 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * ... 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </Row> 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * ... 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </Keyboard> 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </pre> 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#Keyboard_keyWidth 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#Keyboard_keyHeight 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#Keyboard_horizontalGap 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#Keyboard_verticalGap 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class Keyboard { 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static final String TAG = "Keyboard"; 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Keyboard XML Tags 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String TAG_KEYBOARD = "Keyboard"; 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String TAG_ROW = "Row"; 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String TAG_KEY = "Key"; 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int EDGE_LEFT = 0x01; 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int EDGE_RIGHT = 0x02; 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int EDGE_TOP = 0x04; 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int EDGE_BOTTOM = 0x08; 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int KEYCODE_SHIFT = -1; 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int KEYCODE_MODE_CHANGE = -2; 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int KEYCODE_CANCEL = -3; 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int KEYCODE_DONE = -4; 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int KEYCODE_DELETE = -5; 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int KEYCODE_ALT = -6; 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Keyboard label **/ 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private CharSequence mLabel; 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Horizontal gap default for all rows */ 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mDefaultHorizontalGap; 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Default key width */ 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mDefaultWidth; 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Default key height */ 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mDefaultHeight; 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Default gap between rows */ 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mDefaultVerticalGap; 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Is the keyboard in the shifted state */ 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mShifted; 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Key instance for the shift key, if present */ 1016465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller private Key[] mShiftKeys = { null, null }; 1026465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Key index for the shift key, if present */ 1046465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller private int[] mShiftKeyIndices = {-1, -1}; 1056465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Current key width, while loading the keyboard */ 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mKeyWidth; 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Current key height, while loading the keyboard */ 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mKeyHeight; 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Total height of the keyboard, including the padding and keys */ 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mTotalHeight; 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Total width of the keyboard, including left side gaps and keys, but not any gaps on the 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * right side. 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mTotalWidth; 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** List of keys in this keyboard */ 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private List<Key> mKeys; 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** List of modifier keys such as Shift & Alt, if any */ 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private List<Key> mModifierKeys; 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Width of the screen available to fit the keyboard */ 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mDisplayWidth; 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Height of the screen */ 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mDisplayHeight; 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Keyboard mode, or zero, if none. */ 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mKeyboardMode; 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Variables for pre-computing nearest keys. 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int GRID_WIDTH = 10; 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int GRID_HEIGHT = 5; 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int GRID_SIZE = GRID_WIDTH * GRID_HEIGHT; 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mCellWidth; 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mCellHeight; 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int[][] mGridNeighbors; 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mProximityThreshold; 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Number of key widths from current touch point to search for nearest keys. */ 146ae09878698ba6ad56ea43843f5a0895c94c32d90Amith Yamasani private static float SEARCH_DISTANCE = 1.8f; 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 148a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase private ArrayList<Row> rows = new ArrayList<Row>(); 149a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Container for keys in the keyboard. All keys in a row are at the same Y-coordinate. 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Some of the key size defaults can be overridden per row from what the {@link Keyboard} 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * defines. 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#Keyboard_keyWidth 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#Keyboard_keyHeight 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#Keyboard_horizontalGap 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#Keyboard_verticalGap 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#Keyboard_Row_rowEdgeFlags 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#Keyboard_Row_keyboardMode 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static class Row { 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Default width of a key in this row. */ 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int defaultWidth; 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Default height of a key in this row. */ 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int defaultHeight; 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Default horizontal gap between keys in this row. */ 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int defaultHorizontalGap; 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Vertical gap following this row. */ 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int verticalGap; 170a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase 171a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase ArrayList<Key> mKeys = new ArrayList<Key>(); 172a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Edge flags for this row of keys. Possible values that can be assigned are 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link Keyboard#EDGE_TOP EDGE_TOP} and {@link Keyboard#EDGE_BOTTOM EDGE_BOTTOM} 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int rowEdgeFlags; 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** The keyboard mode for this row */ 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int mode; 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Keyboard parent; 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Row(Keyboard parent) { 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this.parent = parent; 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Row(Resources res, Keyboard parent, XmlResourceParser parser) { 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this.parent = parent; 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TypedArray a = res.obtainAttributes(Xml.asAttributeSet(parser), 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project com.android.internal.R.styleable.Keyboard); 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project defaultWidth = getDimensionOrFraction(a, 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project com.android.internal.R.styleable.Keyboard_keyWidth, 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project parent.mDisplayWidth, parent.mDefaultWidth); 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project defaultHeight = getDimensionOrFraction(a, 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project com.android.internal.R.styleable.Keyboard_keyHeight, 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project parent.mDisplayHeight, parent.mDefaultHeight); 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project defaultHorizontalGap = getDimensionOrFraction(a, 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project com.android.internal.R.styleable.Keyboard_horizontalGap, 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project parent.mDisplayWidth, parent.mDefaultHorizontalGap); 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project verticalGap = getDimensionOrFraction(a, 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project com.android.internal.R.styleable.Keyboard_verticalGap, 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project parent.mDisplayHeight, parent.mDefaultVerticalGap); 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project a.recycle(); 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project a = res.obtainAttributes(Xml.asAttributeSet(parser), 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project com.android.internal.R.styleable.Keyboard_Row); 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project rowEdgeFlags = a.getInt(com.android.internal.R.styleable.Keyboard_Row_rowEdgeFlags, 0); 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mode = a.getResourceId(com.android.internal.R.styleable.Keyboard_Row_keyboardMode, 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 0); 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Class for describing the position and characteristics of a single key in the keyboard. 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#Keyboard_keyWidth 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#Keyboard_keyHeight 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#Keyboard_horizontalGap 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#Keyboard_Key_codes 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#Keyboard_Key_keyIcon 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#Keyboard_Key_keyLabel 2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#Keyboard_Key_iconPreview 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#Keyboard_Key_isSticky 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#Keyboard_Key_isRepeatable 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#Keyboard_Key_isModifier 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#Keyboard_Key_popupKeyboard 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#Keyboard_Key_popupCharacters 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#Keyboard_Key_keyOutputText 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#Keyboard_Key_keyEdgeFlags 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static class Key { 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * All the key codes (unicode or custom code) that this key could generate, zero'th 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * being the most important. 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int[] codes; 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Label to display */ 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public CharSequence label; 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Icon to display instead of a label. Icon takes precedence over a label */ 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Drawable icon; 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Preview version of the icon, for the preview popup */ 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Drawable iconPreview; 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Width of the key, not including the gap */ 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int width; 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Height of the key, not including the gap */ 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int height; 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** The horizontal gap before this key */ 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int gap; 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Whether this key is sticky, i.e., a toggle key */ 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean sticky; 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** X coordinate of the key in the keyboard layout */ 2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int x; 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Y coordinate of the key in the keyboard layout */ 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int y; 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** The current pressed state of this key */ 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean pressed; 2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** If this is a sticky key, is it on? */ 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean on; 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Text to output when pressed. This can be multiple characters, like ".com" */ 2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public CharSequence text; 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Popup characters */ 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public CharSequence popupCharacters; 265a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase 2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Flags that specify the anchoring to edges of the keyboard for detecting touch events 2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * that are just out of the boundary of the key. This is a bit mask of 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link Keyboard#EDGE_LEFT}, {@link Keyboard#EDGE_RIGHT}, {@link Keyboard#EDGE_TOP} and 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link Keyboard#EDGE_BOTTOM}. 2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int edgeFlags; 2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Whether this is a modifier key, such as Shift or Alt */ 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean modifier; 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** The keyboard that this key belongs to */ 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Keyboard keyboard; 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * If this key pops up a mini keyboard, this is the resource id for the XML layout for that 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * keyboard. 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int popupResId; 2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Whether this key repeats itself when held down */ 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean repeatable; 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final static int[] KEY_STATE_NORMAL_ON = { 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project android.R.attr.state_checkable, 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project android.R.attr.state_checked 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final static int[] KEY_STATE_PRESSED_ON = { 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project android.R.attr.state_pressed, 2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project android.R.attr.state_checkable, 2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project android.R.attr.state_checked 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final static int[] KEY_STATE_NORMAL_OFF = { 2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project android.R.attr.state_checkable 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final static int[] KEY_STATE_PRESSED_OFF = { 3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project android.R.attr.state_pressed, 3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project android.R.attr.state_checkable 3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final static int[] KEY_STATE_NORMAL = { 3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final static int[] KEY_STATE_PRESSED = { 3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project android.R.attr.state_pressed 3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Create an empty key with no attributes. */ 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Key(Row parent) { 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project keyboard = parent.parent; 316b65b7cb5808a3cea59cbfa72ecd46bdda90351faTadashi G. Takaoka height = parent.defaultHeight; 317b65b7cb5808a3cea59cbfa72ecd46bdda90351faTadashi G. Takaoka width = parent.defaultWidth; 318b65b7cb5808a3cea59cbfa72ecd46bdda90351faTadashi G. Takaoka gap = parent.defaultHorizontalGap; 319b65b7cb5808a3cea59cbfa72ecd46bdda90351faTadashi G. Takaoka edgeFlags = parent.rowEdgeFlags; 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Create a key with the given top-left coordinate and extract its attributes from 3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the XML parser. 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param res resources associated with the caller's context 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param parent the row that this key belongs to. The row must already be attached to 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * a {@link Keyboard}. 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param x the x coordinate of the top-left 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param y the y coordinate of the top-left 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param parser the XML parser containing the attributes for this key 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Key(Resources res, Row parent, int x, int y, XmlResourceParser parser) { 3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this(parent); 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this.x = x; 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this.y = y; 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TypedArray a = res.obtainAttributes(Xml.asAttributeSet(parser), 3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project com.android.internal.R.styleable.Keyboard); 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project width = getDimensionOrFraction(a, 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project com.android.internal.R.styleable.Keyboard_keyWidth, 3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project keyboard.mDisplayWidth, parent.defaultWidth); 3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project height = getDimensionOrFraction(a, 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project com.android.internal.R.styleable.Keyboard_keyHeight, 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project keyboard.mDisplayHeight, parent.defaultHeight); 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project gap = getDimensionOrFraction(a, 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project com.android.internal.R.styleable.Keyboard_horizontalGap, 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project keyboard.mDisplayWidth, parent.defaultHorizontalGap); 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project a.recycle(); 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project a = res.obtainAttributes(Xml.asAttributeSet(parser), 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project com.android.internal.R.styleable.Keyboard_Key); 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this.x += gap; 3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TypedValue codesValue = new TypedValue(); 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project a.getValue(com.android.internal.R.styleable.Keyboard_Key_codes, 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project codesValue); 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (codesValue.type == TypedValue.TYPE_INT_DEC 3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project || codesValue.type == TypedValue.TYPE_INT_HEX) { 3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project codes = new int[] { codesValue.data }; 3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (codesValue.type == TypedValue.TYPE_STRING) { 3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project codes = parseCSV(codesValue.string.toString()); 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project iconPreview = a.getDrawable(com.android.internal.R.styleable.Keyboard_Key_iconPreview); 3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (iconPreview != null) { 3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project iconPreview.setBounds(0, 0, iconPreview.getIntrinsicWidth(), 3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project iconPreview.getIntrinsicHeight()); 3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project popupCharacters = a.getText( 3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project com.android.internal.R.styleable.Keyboard_Key_popupCharacters); 3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project popupResId = a.getResourceId( 3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project com.android.internal.R.styleable.Keyboard_Key_popupKeyboard, 0); 3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project repeatable = a.getBoolean( 3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project com.android.internal.R.styleable.Keyboard_Key_isRepeatable, false); 3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project modifier = a.getBoolean( 3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project com.android.internal.R.styleable.Keyboard_Key_isModifier, false); 3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sticky = a.getBoolean( 3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project com.android.internal.R.styleable.Keyboard_Key_isSticky, false); 3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project edgeFlags = a.getInt(com.android.internal.R.styleable.Keyboard_Key_keyEdgeFlags, 0); 3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project edgeFlags |= parent.rowEdgeFlags; 3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project icon = a.getDrawable( 3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project com.android.internal.R.styleable.Keyboard_Key_keyIcon); 3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (icon != null) { 3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project icon.setBounds(0, 0, icon.getIntrinsicWidth(), icon.getIntrinsicHeight()); 3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project label = a.getText(com.android.internal.R.styleable.Keyboard_Key_keyLabel); 3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project text = a.getText(com.android.internal.R.styleable.Keyboard_Key_keyOutputText); 3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (codes == null && !TextUtils.isEmpty(label)) { 3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project codes = new int[] { label.charAt(0) }; 3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project a.recycle(); 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Informs the key that it has been pressed, in case it needs to change its appearance or 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * state. 3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see #onReleased(boolean) 3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onPressed() { 4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pressed = !pressed; 4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4035c31de33ccc99404f54452de1974bb2960b31343Yohei Yukawa 4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4055c31de33ccc99404f54452de1974bb2960b31343Yohei Yukawa * Changes the pressed state of the key. 4065c31de33ccc99404f54452de1974bb2960b31343Yohei Yukawa * 4075c31de33ccc99404f54452de1974bb2960b31343Yohei Yukawa * <p>Toggled state of the key will be flipped when all the following conditions are 4085c31de33ccc99404f54452de1974bb2960b31343Yohei Yukawa * fulfilled:</p> 4095c31de33ccc99404f54452de1974bb2960b31343Yohei Yukawa * 4105c31de33ccc99404f54452de1974bb2960b31343Yohei Yukawa * <ul> 4115c31de33ccc99404f54452de1974bb2960b31343Yohei Yukawa * <li>This is a sticky key, that is, {@link #sticky} is {@code true}. 4125c31de33ccc99404f54452de1974bb2960b31343Yohei Yukawa * <li>The parameter {@code inside} is {@code true}. 4135b2a0987fa0d889db1b4827c79ad3b4ce6409cecYohei Yukawa * <li>{@link android.os.Build.VERSION#SDK_INT} is greater than 4145b2a0987fa0d889db1b4827c79ad3b4ce6409cecYohei Yukawa * {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1}. 4155c31de33ccc99404f54452de1974bb2960b31343Yohei Yukawa * </ul> 4165c31de33ccc99404f54452de1974bb2960b31343Yohei Yukawa * 4175c31de33ccc99404f54452de1974bb2960b31343Yohei Yukawa * @param inside whether the finger was released inside the key. Works only on Android M and 4185c31de33ccc99404f54452de1974bb2960b31343Yohei Yukawa * later. See the method document for details. 4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see #onPressed() 4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onReleased(boolean inside) { 4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pressed = !pressed; 4235c31de33ccc99404f54452de1974bb2960b31343Yohei Yukawa if (sticky && inside) { 4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project on = !on; 4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int[] parseCSV(String value) { 4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count = 0; 4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int lastIndex = 0; 4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (value.length() > 0) { 4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project count++; 4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while ((lastIndex = value.indexOf(",", lastIndex + 1)) > 0) { 4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project count++; 4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int[] values = new int[count]; 4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project count = 0; 4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project StringTokenizer st = new StringTokenizer(value, ","); 4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (st.hasMoreTokens()) { 4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project values[count++] = Integer.parseInt(st.nextToken()); 4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (NumberFormatException nfe) { 4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(TAG, "Error parsing keycodes " + value); 4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return values; 4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Detects if a point falls inside this key. 4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param x the x-coordinate of the point 4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param y the y-coordinate of the point 4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return whether or not the point falls inside the key. If the key is attached to an edge, 4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * it will assume that all points between the key and the edge are considered to be inside 4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the key. 4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean isInside(int x, int y) { 4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean leftEdge = (edgeFlags & EDGE_LEFT) > 0; 4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean rightEdge = (edgeFlags & EDGE_RIGHT) > 0; 4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean topEdge = (edgeFlags & EDGE_TOP) > 0; 4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean bottomEdge = (edgeFlags & EDGE_BOTTOM) > 0; 4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((x >= this.x || (leftEdge && x <= this.x + this.width)) 4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project && (x < this.x + this.width || (rightEdge && x >= this.x)) 4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project && (y >= this.y || (topEdge && y <= this.y + this.height)) 4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project && (y < this.y + this.height || (bottomEdge && y >= this.y))) { 4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the square of the distance between the center of the key and the given point. 4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param x the x-coordinate of the point 4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param y the y-coordinate of the point 4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return the square of the distance of the point from the center of the key 4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int squaredDistanceFrom(int x, int y) { 4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int xDist = this.x + width / 2 - x; 4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int yDist = this.y + height / 2 - y; 4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return xDist * xDist + yDist * yDist; 4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the drawable state for the key, based on the current state and type of the key. 4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return the drawable state of the key. 4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see android.graphics.drawable.StateListDrawable#setState(int[]) 4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int[] getCurrentDrawableState() { 4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int[] states = KEY_STATE_NORMAL; 4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (on) { 4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (pressed) { 4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project states = KEY_STATE_PRESSED_ON; 4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project states = KEY_STATE_NORMAL_ON; 4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (sticky) { 5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (pressed) { 5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project states = KEY_STATE_PRESSED_OFF; 5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project states = KEY_STATE_NORMAL_OFF; 5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (pressed) { 5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project states = KEY_STATE_PRESSED; 5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return states; 5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Creates a keyboard from the given xml key layout file. 5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param context the application or service context 5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param xmlLayoutResId the resource file that contains the keyboard layout and keys. 5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Keyboard(Context context, int xmlLayoutResId) { 5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this(context, xmlLayoutResId, 0); 5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5248171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung 5258171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung /** 5268171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung * Creates a keyboard from the given xml key layout file. Weeds out rows 5278171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung * that have a keyboard mode defined but don't match the specified mode. 5288171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung * @param context the application or service context 5298171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung * @param xmlLayoutResId the resource file that contains the keyboard layout and keys. 5308171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung * @param modeId keyboard mode identifier 5318171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung * @param width sets width of keyboard 5328171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung * @param height sets height of keyboard 5338171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung */ 5347b9c912f536925ac6ec43935d6e97506851b33d6Tor Norbye public Keyboard(Context context, @XmlRes int xmlLayoutResId, int modeId, int width, 5357b9c912f536925ac6ec43935d6e97506851b33d6Tor Norbye int height) { 5368171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung mDisplayWidth = width; 5378171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung mDisplayHeight = height; 5388171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung 5398171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung mDefaultHorizontalGap = 0; 5408171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung mDefaultWidth = mDisplayWidth / 10; 5418171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung mDefaultVerticalGap = 0; 5428171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung mDefaultHeight = mDefaultWidth; 5438171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung mKeys = new ArrayList<Key>(); 5448171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung mModifierKeys = new ArrayList<Key>(); 5458171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung mKeyboardMode = modeId; 5468171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung loadKeyboard(context, context.getResources().getXml(xmlLayoutResId)); 5478171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung } 5488171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung 5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Creates a keyboard from the given xml key layout file. Weeds out rows 5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * that have a keyboard mode defined but don't match the specified mode. 5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param context the application or service context 5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param xmlLayoutResId the resource file that contains the keyboard layout and keys. 5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param modeId keyboard mode identifier 5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5567b9c912f536925ac6ec43935d6e97506851b33d6Tor Norbye public Keyboard(Context context, @XmlRes int xmlLayoutResId, int modeId) { 55758feea74b42bbaaa0552d76af23873bdd0b5dca2Mitsuru Oshima DisplayMetrics dm = context.getResources().getDisplayMetrics(); 55858feea74b42bbaaa0552d76af23873bdd0b5dca2Mitsuru Oshima mDisplayWidth = dm.widthPixels; 55958feea74b42bbaaa0552d76af23873bdd0b5dca2Mitsuru Oshima mDisplayHeight = dm.heightPixels; 56058feea74b42bbaaa0552d76af23873bdd0b5dca2Mitsuru Oshima //Log.v(TAG, "keyboard's display metrics:" + dm); 56158feea74b42bbaaa0552d76af23873bdd0b5dca2Mitsuru Oshima 5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDefaultHorizontalGap = 0; 5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDefaultWidth = mDisplayWidth / 10; 5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDefaultVerticalGap = 0; 5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDefaultHeight = mDefaultWidth; 5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mKeys = new ArrayList<Key>(); 5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mModifierKeys = new ArrayList<Key>(); 5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mKeyboardMode = modeId; 5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project loadKeyboard(context, context.getResources().getXml(xmlLayoutResId)); 5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>Creates a blank keyboard from the given resource file and populates it with the specified 5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * characters in left-to-right, top-to-bottom fashion, using the specified number of columns. 5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </p> 5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>If the specified number of columns is -1, then the keyboard will fit as many keys as 5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * possible in each row.</p> 5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param context the application or service context 5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param layoutTemplateResId the layout template file, containing no keys. 5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param characters the list of characters to display on the keyboard. One key will be created 5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * for each character. 5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param columns the number of columns of keys to display. If this number is greater than the 5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * number of keys that can fit in a row, it will be ignored. If this number is -1, the 5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * keyboard will fit as many keys as possible in each row. 5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Keyboard(Context context, int layoutTemplateResId, 5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CharSequence characters, int columns, int horizontalPadding) { 5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this(context, layoutTemplateResId); 5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int x = 0; 5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int y = 0; 5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int column = 0; 5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mTotalWidth = 0; 5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Row row = new Row(this); 5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project row.defaultHeight = mDefaultHeight; 5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project row.defaultWidth = mDefaultWidth; 5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project row.defaultHorizontalGap = mDefaultHorizontalGap; 5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project row.verticalGap = mDefaultVerticalGap; 5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project row.rowEdgeFlags = EDGE_TOP | EDGE_BOTTOM; 6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int maxColumns = columns == -1 ? Integer.MAX_VALUE : columns; 6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < characters.length(); i++) { 6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char c = characters.charAt(i); 6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (column >= maxColumns 6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project || x + mDefaultWidth + horizontalPadding > mDisplayWidth) { 6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project x = 0; 6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project y += mDefaultVerticalGap + mDefaultHeight; 6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project column = 0; 6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Key key = new Key(row); 6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project key.x = x; 6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project key.y = y; 6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project key.label = String.valueOf(c); 6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project key.codes = new int[] { c }; 6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project column++; 6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project x += key.width + key.gap; 6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mKeys.add(key); 617a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase row.mKeys.add(key); 6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (x > mTotalWidth) { 6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mTotalWidth = x; 6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 622a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase mTotalHeight = y + mDefaultHeight; 623a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase rows.add(row); 624a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase } 625a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase 626a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase final void resize(int newWidth, int newHeight) { 627a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase int numRows = rows.size(); 628a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase for (int rowIndex = 0; rowIndex < numRows; ++rowIndex) { 629a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase Row row = rows.get(rowIndex); 630a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase int numKeys = row.mKeys.size(); 631a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase int totalGap = 0; 632a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase int totalWidth = 0; 633a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase for (int keyIndex = 0; keyIndex < numKeys; ++keyIndex) { 634a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase Key key = row.mKeys.get(keyIndex); 635a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase if (keyIndex > 0) { 636a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase totalGap += key.gap; 637a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase } 638a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase totalWidth += key.width; 639a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase } 640a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase if (totalGap + totalWidth > newWidth) { 641a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase int x = 0; 642a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase float scaleFactor = (float)(newWidth - totalGap) / totalWidth; 643a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase for (int keyIndex = 0; keyIndex < numKeys; ++keyIndex) { 644a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase Key key = row.mKeys.get(keyIndex); 645a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase key.width *= scaleFactor; 646a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase key.x = x; 647a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase x += key.width + key.gap; 648a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase } 649a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase } 650a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase } 651a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase mTotalWidth = newWidth; 652a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase // TODO: This does not adjust the vertical placement according to the new size. 653a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase // The main problem in the previous code was horizontal placement/size, but we should 654a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase // also recalculate the vertical sizes/positions when we get this resize call. 6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public List<Key> getKeys() { 6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mKeys; 6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public List<Key> getModifierKeys() { 6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mModifierKeys; 6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected int getHorizontalGap() { 6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mDefaultHorizontalGap; 6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void setHorizontalGap(int gap) { 6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDefaultHorizontalGap = gap; 6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected int getVerticalGap() { 6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mDefaultVerticalGap; 6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void setVerticalGap(int gap) { 6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDefaultVerticalGap = gap; 6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected int getKeyHeight() { 6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mDefaultHeight; 6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void setKeyHeight(int height) { 6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDefaultHeight = height; 6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected int getKeyWidth() { 6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mDefaultWidth; 6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void setKeyWidth(int width) { 6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDefaultWidth = width; 6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the total height of the keyboard 6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return the total height of the keyboard 7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getHeight() { 7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mTotalHeight; 7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getMinWidth() { 7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mTotalWidth; 7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean setShifted(boolean shiftState) { 7106465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller for (Key shiftKey : mShiftKeys) { 7116465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller if (shiftKey != null) { 7126465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller shiftKey.on = shiftState; 7136465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller } 7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mShifted != shiftState) { 7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mShifted = shiftState; 7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean isShifted() { 7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mShifted; 7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7266465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller /** 7276465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller * @hide 7286465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller */ 7296465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller public int[] getShiftKeyIndices() { 7306465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller return mShiftKeyIndices; 7316465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller } 7326465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller 7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getShiftKeyIndex() { 7346465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller return mShiftKeyIndices[0]; 7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void computeNearestNeighbors() { 7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Round-up so we don't have any pixels outside the grid 7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCellWidth = (getMinWidth() + GRID_WIDTH - 1) / GRID_WIDTH; 7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCellHeight = (getHeight() + GRID_HEIGHT - 1) / GRID_HEIGHT; 7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGridNeighbors = new int[GRID_SIZE][]; 7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int[] indices = new int[mKeys.size()]; 7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int gridWidth = GRID_WIDTH * mCellWidth; 7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int gridHeight = GRID_HEIGHT * mCellHeight; 7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int x = 0; x < gridWidth; x += mCellWidth) { 7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int y = 0; y < gridHeight; y += mCellHeight) { 7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count = 0; 7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < mKeys.size(); i++) { 7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Key key = mKeys.get(i); 7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (key.squaredDistanceFrom(x, y) < mProximityThreshold || 7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project key.squaredDistanceFrom(x + mCellWidth - 1, y) < mProximityThreshold || 7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project key.squaredDistanceFrom(x + mCellWidth - 1, y + mCellHeight - 1) 7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project < mProximityThreshold || 7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project key.squaredDistanceFrom(x, y + mCellHeight - 1) < mProximityThreshold) { 7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project indices[count++] = i; 7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int [] cell = new int[count]; 7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.arraycopy(indices, 0, cell, 0, count); 7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGridNeighbors[(y / mCellHeight) * GRID_WIDTH + (x / mCellWidth)] = cell; 7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the indices of the keys that are closest to the given point. 7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param x the x-coordinate of the point 7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param y the y-coordinate of the point 7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return the array of integer indices for the nearest keys to the given point. If the given 7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * point is out of range, then an array of size zero is returned. 7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int[] getNearestKeys(int x, int y) { 7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mGridNeighbors == null) computeNearestNeighbors(); 7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (x >= 0 && x < getMinWidth() && y >= 0 && y < getHeight()) { 7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int index = (y / mCellHeight) * GRID_WIDTH + (x / mCellWidth); 7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (index < GRID_SIZE) { 7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mGridNeighbors[index]; 7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return new int[0]; 7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected Row createRowFromXml(Resources res, XmlResourceParser parser) { 7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return new Row(res, this, parser); 7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected Key createKeyFromXml(Resources res, Row parent, int x, int y, 7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project XmlResourceParser parser) { 7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return new Key(res, parent, x, y, parser); 7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void loadKeyboard(Context context, XmlResourceParser parser) { 7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean inKey = false; 7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean inRow = false; 7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean leftMostKey = false; 7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int row = 0; 7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int x = 0; 7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int y = 0; 7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Key key = null; 8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Row currentRow = null; 8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Resources res = context.getResources(); 8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean skipRow = false; 803a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase 8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int event; 8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while ((event = parser.next()) != XmlResourceParser.END_DOCUMENT) { 8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (event == XmlResourceParser.START_TAG) { 8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String tag = parser.getName(); 8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (TAG_ROW.equals(tag)) { 8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project inRow = true; 8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project x = 0; 8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project currentRow = createRowFromXml(res, parser); 813a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase rows.add(currentRow); 8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project skipRow = currentRow.mode != 0 && currentRow.mode != mKeyboardMode; 8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (skipRow) { 8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project skipToEndOfRow(parser); 8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project inRow = false; 8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (TAG_KEY.equals(tag)) { 8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project inKey = true; 8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project key = createKeyFromXml(res, currentRow, x, y, parser); 8229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mKeys.add(key); 8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (key.codes[0] == KEYCODE_SHIFT) { 8246465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller // Find available shift key slot and put this shift key in it 8256465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller for (int i = 0; i < mShiftKeys.length; i++) { 8266465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller if (mShiftKeys[i] == null) { 8276465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller mShiftKeys[i] = key; 8286465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller mShiftKeyIndices[i] = mKeys.size()-1; 8296465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller break; 8306465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller } 8316465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller } 8329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mModifierKeys.add(key); 8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (key.codes[0] == KEYCODE_ALT) { 8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mModifierKeys.add(key); 8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 836a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase currentRow.mKeys.add(key); 8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (TAG_KEYBOARD.equals(tag)) { 8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project parseKeyboardAttributes(res, parser); 8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (event == XmlResourceParser.END_TAG) { 8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (inKey) { 8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project inKey = false; 8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project x += key.gap + key.width; 8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (x > mTotalWidth) { 8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mTotalWidth = x; 8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (inRow) { 8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project inRow = false; 8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project y += currentRow.verticalGap; 8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project y += currentRow.defaultHeight; 8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project row++; 8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // TODO: error or extend? 8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (Exception e) { 8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(TAG, "Parse error:" + e); 8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project e.printStackTrace(); 8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mTotalHeight = y - mDefaultVerticalGap; 8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void skipToEndOfRow(XmlResourceParser parser) 8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throws XmlPullParserException, IOException { 8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int event; 8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while ((event = parser.next()) != XmlResourceParser.END_DOCUMENT) { 8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (event == XmlResourceParser.END_TAG 8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project && parser.getName().equals(TAG_ROW)) { 8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void parseKeyboardAttributes(Resources res, XmlResourceParser parser) { 8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TypedArray a = res.obtainAttributes(Xml.asAttributeSet(parser), 8779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project com.android.internal.R.styleable.Keyboard); 8789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDefaultWidth = getDimensionOrFraction(a, 8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project com.android.internal.R.styleable.Keyboard_keyWidth, 8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDisplayWidth, mDisplayWidth / 10); 8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDefaultHeight = getDimensionOrFraction(a, 8839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project com.android.internal.R.styleable.Keyboard_keyHeight, 8849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDisplayHeight, 50); 8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDefaultHorizontalGap = getDimensionOrFraction(a, 8869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project com.android.internal.R.styleable.Keyboard_horizontalGap, 8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDisplayWidth, 0); 8889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDefaultVerticalGap = getDimensionOrFraction(a, 8899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project com.android.internal.R.styleable.Keyboard_verticalGap, 8909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDisplayHeight, 0); 8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mProximityThreshold = (int) (mDefaultWidth * SEARCH_DISTANCE); 8929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mProximityThreshold = mProximityThreshold * mProximityThreshold; // Square it for comparison 8939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project a.recycle(); 8949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static int getDimensionOrFraction(TypedArray a, int index, int base, int defValue) { 8979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TypedValue value = a.peekValue(index); 8989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (value == null) return defValue; 8999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (value.type == TypedValue.TYPE_DIMENSION) { 9009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return a.getDimensionPixelOffset(index, defValue); 9019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (value.type == TypedValue.TYPE_FRACTION) { 9029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Round it to avoid values like 47.9999 from getting truncated 9039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return Math.round(a.getFraction(index, base, base, defValue)); 9049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return defValue; 9069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 908