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 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context; 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.Resources; 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.TypedArray; 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.XmlResourceParser; 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.drawable.Drawable; 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.TextUtils; 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log; 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.TypedValue; 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Xml; 3058feea74b42bbaaa0552d76af23873bdd0b5dca2Mitsuru Oshimaimport android.util.DisplayMetrics; 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException; 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList; 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.List; 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.StringTokenizer; 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Loads an XML description of a keyboard and stores the attributes of the keys. A keyboard 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * consists of rows of keys. 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>The layout file for a keyboard contains XML that looks like the following snippet:</p> 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <pre> 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <Keyboard 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * android:keyWidth="%10p" 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * android:keyHeight="50px" 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * android:horizontalGap="2px" 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * android:verticalGap="2px" > 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <Row android:keyWidth="32px" > 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <Key android:keyLabel="A" /> 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * ... 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </Row> 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * ... 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </Keyboard> 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </pre> 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#Keyboard_keyWidth 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#Keyboard_keyHeight 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#Keyboard_horizontalGap 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#Keyboard_verticalGap 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class Keyboard { 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static final String TAG = "Keyboard"; 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Keyboard XML Tags 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String TAG_KEYBOARD = "Keyboard"; 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String TAG_ROW = "Row"; 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String TAG_KEY = "Key"; 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int EDGE_LEFT = 0x01; 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int EDGE_RIGHT = 0x02; 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int EDGE_TOP = 0x04; 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int EDGE_BOTTOM = 0x08; 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int KEYCODE_SHIFT = -1; 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int KEYCODE_MODE_CHANGE = -2; 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int KEYCODE_CANCEL = -3; 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int KEYCODE_DONE = -4; 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int KEYCODE_DELETE = -5; 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int KEYCODE_ALT = -6; 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Keyboard label **/ 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private CharSequence mLabel; 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Horizontal gap default for all rows */ 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mDefaultHorizontalGap; 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Default key width */ 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mDefaultWidth; 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Default key height */ 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mDefaultHeight; 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Default gap between rows */ 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mDefaultVerticalGap; 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Is the keyboard in the shifted state */ 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mShifted; 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Key instance for the shift key, if present */ 1006465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller private Key[] mShiftKeys = { null, null }; 1016465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Key index for the shift key, if present */ 1036465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller private int[] mShiftKeyIndices = {-1, -1}; 1046465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Current key width, while loading the keyboard */ 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mKeyWidth; 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Current key height, while loading the keyboard */ 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mKeyHeight; 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Total height of the keyboard, including the padding and keys */ 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mTotalHeight; 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Total width of the keyboard, including left side gaps and keys, but not any gaps on the 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * right side. 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mTotalWidth; 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** List of keys in this keyboard */ 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private List<Key> mKeys; 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** List of modifier keys such as Shift & Alt, if any */ 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private List<Key> mModifierKeys; 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Width of the screen available to fit the keyboard */ 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mDisplayWidth; 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Height of the screen */ 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mDisplayHeight; 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Keyboard mode, or zero, if none. */ 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mKeyboardMode; 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Variables for pre-computing nearest keys. 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int GRID_WIDTH = 10; 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int GRID_HEIGHT = 5; 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int GRID_SIZE = GRID_WIDTH * GRID_HEIGHT; 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mCellWidth; 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mCellHeight; 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int[][] mGridNeighbors; 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mProximityThreshold; 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Number of key widths from current touch point to search for nearest keys. */ 145ae09878698ba6ad56ea43843f5a0895c94c32d90Amith Yamasani private static float SEARCH_DISTANCE = 1.8f; 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 147a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase private ArrayList<Row> rows = new ArrayList<Row>(); 148a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Container for keys in the keyboard. All keys in a row are at the same Y-coordinate. 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Some of the key size defaults can be overridden per row from what the {@link Keyboard} 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * defines. 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#Keyboard_keyWidth 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#Keyboard_keyHeight 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#Keyboard_horizontalGap 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#Keyboard_verticalGap 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#Keyboard_Row_rowEdgeFlags 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#Keyboard_Row_keyboardMode 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static class Row { 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Default width of a key in this row. */ 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int defaultWidth; 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Default height of a key in this row. */ 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int defaultHeight; 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Default horizontal gap between keys in this row. */ 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int defaultHorizontalGap; 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Vertical gap following this row. */ 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int verticalGap; 169a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase 170a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase ArrayList<Key> mKeys = new ArrayList<Key>(); 171a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Edge flags for this row of keys. Possible values that can be assigned are 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link Keyboard#EDGE_TOP EDGE_TOP} and {@link Keyboard#EDGE_BOTTOM EDGE_BOTTOM} 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int rowEdgeFlags; 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** The keyboard mode for this row */ 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int mode; 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Keyboard parent; 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Row(Keyboard parent) { 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this.parent = parent; 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Row(Resources res, Keyboard parent, XmlResourceParser parser) { 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this.parent = parent; 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TypedArray a = res.obtainAttributes(Xml.asAttributeSet(parser), 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project com.android.internal.R.styleable.Keyboard); 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project defaultWidth = getDimensionOrFraction(a, 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project com.android.internal.R.styleable.Keyboard_keyWidth, 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project parent.mDisplayWidth, parent.mDefaultWidth); 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project defaultHeight = getDimensionOrFraction(a, 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project com.android.internal.R.styleable.Keyboard_keyHeight, 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project parent.mDisplayHeight, parent.mDefaultHeight); 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project defaultHorizontalGap = getDimensionOrFraction(a, 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project com.android.internal.R.styleable.Keyboard_horizontalGap, 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project parent.mDisplayWidth, parent.mDefaultHorizontalGap); 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project verticalGap = getDimensionOrFraction(a, 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project com.android.internal.R.styleable.Keyboard_verticalGap, 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project parent.mDisplayHeight, parent.mDefaultVerticalGap); 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project a.recycle(); 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project a = res.obtainAttributes(Xml.asAttributeSet(parser), 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project com.android.internal.R.styleable.Keyboard_Row); 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project rowEdgeFlags = a.getInt(com.android.internal.R.styleable.Keyboard_Row_rowEdgeFlags, 0); 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mode = a.getResourceId(com.android.internal.R.styleable.Keyboard_Row_keyboardMode, 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 0); 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Class for describing the position and characteristics of a single key in the keyboard. 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#Keyboard_keyWidth 2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#Keyboard_keyHeight 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#Keyboard_horizontalGap 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#Keyboard_Key_codes 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#Keyboard_Key_keyIcon 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#Keyboard_Key_keyLabel 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#Keyboard_Key_iconPreview 2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#Keyboard_Key_isSticky 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#Keyboard_Key_isRepeatable 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#Keyboard_Key_isModifier 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#Keyboard_Key_popupKeyboard 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#Keyboard_Key_popupCharacters 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#Keyboard_Key_keyOutputText 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#Keyboard_Key_keyEdgeFlags 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static class Key { 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * All the key codes (unicode or custom code) that this key could generate, zero'th 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * being the most important. 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int[] codes; 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Label to display */ 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public CharSequence label; 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Icon to display instead of a label. Icon takes precedence over a label */ 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Drawable icon; 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Preview version of the icon, for the preview popup */ 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Drawable iconPreview; 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Width of the key, not including the gap */ 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int width; 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Height of the key, not including the gap */ 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int height; 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** The horizontal gap before this key */ 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int gap; 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Whether this key is sticky, i.e., a toggle key */ 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean sticky; 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** X coordinate of the key in the keyboard layout */ 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int x; 2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Y coordinate of the key in the keyboard layout */ 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int y; 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** The current pressed state of this key */ 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean pressed; 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** If this is a sticky key, is it on? */ 2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean on; 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Text to output when pressed. This can be multiple characters, like ".com" */ 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public CharSequence text; 2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Popup characters */ 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public CharSequence popupCharacters; 264a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Flags that specify the anchoring to edges of the keyboard for detecting touch events 2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * that are just out of the boundary of the key. This is a bit mask of 2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link Keyboard#EDGE_LEFT}, {@link Keyboard#EDGE_RIGHT}, {@link Keyboard#EDGE_TOP} and 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link Keyboard#EDGE_BOTTOM}. 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int edgeFlags; 2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Whether this is a modifier key, such as Shift or Alt */ 2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean modifier; 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** The keyboard that this key belongs to */ 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Keyboard keyboard; 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * If this key pops up a mini keyboard, this is the resource id for the XML layout for that 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * keyboard. 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int popupResId; 2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Whether this key repeats itself when held down */ 2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean repeatable; 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final static int[] KEY_STATE_NORMAL_ON = { 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project android.R.attr.state_checkable, 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project android.R.attr.state_checked 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final static int[] KEY_STATE_PRESSED_ON = { 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project android.R.attr.state_pressed, 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project android.R.attr.state_checkable, 2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project android.R.attr.state_checked 2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final static int[] KEY_STATE_NORMAL_OFF = { 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project android.R.attr.state_checkable 2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final static int[] KEY_STATE_PRESSED_OFF = { 3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project android.R.attr.state_pressed, 3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project android.R.attr.state_checkable 3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final static int[] KEY_STATE_NORMAL = { 3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final static int[] KEY_STATE_PRESSED = { 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project android.R.attr.state_pressed 3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Create an empty key with no attributes. */ 3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Key(Row parent) { 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project keyboard = parent.parent; 315b65b7cb5808a3cea59cbfa72ecd46bdda90351faTadashi G. Takaoka height = parent.defaultHeight; 316b65b7cb5808a3cea59cbfa72ecd46bdda90351faTadashi G. Takaoka width = parent.defaultWidth; 317b65b7cb5808a3cea59cbfa72ecd46bdda90351faTadashi G. Takaoka gap = parent.defaultHorizontalGap; 318b65b7cb5808a3cea59cbfa72ecd46bdda90351faTadashi G. Takaoka edgeFlags = parent.rowEdgeFlags; 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Create a key with the given top-left coordinate and extract its attributes from 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the XML parser. 3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param res resources associated with the caller's context 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param parent the row that this key belongs to. The row must already be attached to 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * a {@link Keyboard}. 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param x the x coordinate of the top-left 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param y the y coordinate of the top-left 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param parser the XML parser containing the attributes for this key 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Key(Resources res, Row parent, int x, int y, XmlResourceParser parser) { 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this(parent); 3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this.x = x; 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this.y = y; 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TypedArray a = res.obtainAttributes(Xml.asAttributeSet(parser), 3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project com.android.internal.R.styleable.Keyboard); 3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project width = getDimensionOrFraction(a, 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project com.android.internal.R.styleable.Keyboard_keyWidth, 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project keyboard.mDisplayWidth, parent.defaultWidth); 3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project height = getDimensionOrFraction(a, 3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project com.android.internal.R.styleable.Keyboard_keyHeight, 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project keyboard.mDisplayHeight, parent.defaultHeight); 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project gap = getDimensionOrFraction(a, 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project com.android.internal.R.styleable.Keyboard_horizontalGap, 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project keyboard.mDisplayWidth, parent.defaultHorizontalGap); 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project a.recycle(); 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project a = res.obtainAttributes(Xml.asAttributeSet(parser), 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project com.android.internal.R.styleable.Keyboard_Key); 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this.x += gap; 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TypedValue codesValue = new TypedValue(); 3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project a.getValue(com.android.internal.R.styleable.Keyboard_Key_codes, 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project codesValue); 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (codesValue.type == TypedValue.TYPE_INT_DEC 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project || codesValue.type == TypedValue.TYPE_INT_HEX) { 3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project codes = new int[] { codesValue.data }; 3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (codesValue.type == TypedValue.TYPE_STRING) { 3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project codes = parseCSV(codesValue.string.toString()); 3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project iconPreview = a.getDrawable(com.android.internal.R.styleable.Keyboard_Key_iconPreview); 3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (iconPreview != null) { 3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project iconPreview.setBounds(0, 0, iconPreview.getIntrinsicWidth(), 3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project iconPreview.getIntrinsicHeight()); 3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project popupCharacters = a.getText( 3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project com.android.internal.R.styleable.Keyboard_Key_popupCharacters); 3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project popupResId = a.getResourceId( 3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project com.android.internal.R.styleable.Keyboard_Key_popupKeyboard, 0); 3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project repeatable = a.getBoolean( 3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project com.android.internal.R.styleable.Keyboard_Key_isRepeatable, false); 3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project modifier = a.getBoolean( 3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project com.android.internal.R.styleable.Keyboard_Key_isModifier, false); 3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sticky = a.getBoolean( 3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project com.android.internal.R.styleable.Keyboard_Key_isSticky, false); 3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project edgeFlags = a.getInt(com.android.internal.R.styleable.Keyboard_Key_keyEdgeFlags, 0); 3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project edgeFlags |= parent.rowEdgeFlags; 3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project icon = a.getDrawable( 3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project com.android.internal.R.styleable.Keyboard_Key_keyIcon); 3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (icon != null) { 3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project icon.setBounds(0, 0, icon.getIntrinsicWidth(), icon.getIntrinsicHeight()); 3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project label = a.getText(com.android.internal.R.styleable.Keyboard_Key_keyLabel); 3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project text = a.getText(com.android.internal.R.styleable.Keyboard_Key_keyOutputText); 3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (codes == null && !TextUtils.isEmpty(label)) { 3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project codes = new int[] { label.charAt(0) }; 3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project a.recycle(); 3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Informs the key that it has been pressed, in case it needs to change its appearance or 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * state. 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see #onReleased(boolean) 3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onPressed() { 4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pressed = !pressed; 4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Changes the pressed state of the key. If it is a sticky key, it will also change the 4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * toggled state of the key if the finger was release inside. 4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param inside whether the finger was released inside the key 4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see #onPressed() 4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onReleased(boolean inside) { 4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pressed = !pressed; 4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (sticky) { 4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project on = !on; 4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int[] parseCSV(String value) { 4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count = 0; 4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int lastIndex = 0; 4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (value.length() > 0) { 4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project count++; 4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while ((lastIndex = value.indexOf(",", lastIndex + 1)) > 0) { 4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project count++; 4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int[] values = new int[count]; 4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project count = 0; 4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project StringTokenizer st = new StringTokenizer(value, ","); 4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (st.hasMoreTokens()) { 4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project values[count++] = Integer.parseInt(st.nextToken()); 4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (NumberFormatException nfe) { 4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(TAG, "Error parsing keycodes " + value); 4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return values; 4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Detects if a point falls inside this key. 4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param x the x-coordinate of the point 4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param y the y-coordinate of the point 4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return whether or not the point falls inside the key. If the key is attached to an edge, 4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * it will assume that all points between the key and the edge are considered to be inside 4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the key. 4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean isInside(int x, int y) { 4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean leftEdge = (edgeFlags & EDGE_LEFT) > 0; 4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean rightEdge = (edgeFlags & EDGE_RIGHT) > 0; 4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean topEdge = (edgeFlags & EDGE_TOP) > 0; 4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean bottomEdge = (edgeFlags & EDGE_BOTTOM) > 0; 4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((x >= this.x || (leftEdge && x <= this.x + this.width)) 4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project && (x < this.x + this.width || (rightEdge && x >= this.x)) 4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project && (y >= this.y || (topEdge && y <= this.y + this.height)) 4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project && (y < this.y + this.height || (bottomEdge && y >= this.y))) { 4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the square of the distance between the center of the key and the given point. 4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param x the x-coordinate of the point 4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param y the y-coordinate of the point 4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return the square of the distance of the point from the center of the key 4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int squaredDistanceFrom(int x, int y) { 4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int xDist = this.x + width / 2 - x; 4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int yDist = this.y + height / 2 - y; 4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return xDist * xDist + yDist * yDist; 4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the drawable state for the key, based on the current state and type of the key. 4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return the drawable state of the key. 4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see android.graphics.drawable.StateListDrawable#setState(int[]) 4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int[] getCurrentDrawableState() { 4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int[] states = KEY_STATE_NORMAL; 4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (on) { 4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (pressed) { 4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project states = KEY_STATE_PRESSED_ON; 4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project states = KEY_STATE_NORMAL_ON; 4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (sticky) { 4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (pressed) { 4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project states = KEY_STATE_PRESSED_OFF; 4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project states = KEY_STATE_NORMAL_OFF; 4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (pressed) { 4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project states = KEY_STATE_PRESSED; 4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return states; 5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Creates a keyboard from the given xml key layout file. 5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param context the application or service context 5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param xmlLayoutResId the resource file that contains the keyboard layout and keys. 5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Keyboard(Context context, int xmlLayoutResId) { 5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this(context, xmlLayoutResId, 0); 5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5128171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung 5138171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung /** 5148171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung * Creates a keyboard from the given xml key layout file. Weeds out rows 5158171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung * that have a keyboard mode defined but don't match the specified mode. 5168171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung * @param context the application or service context 5178171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung * @param xmlLayoutResId the resource file that contains the keyboard layout and keys. 5188171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung * @param modeId keyboard mode identifier 5198171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung * @param width sets width of keyboard 5208171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung * @param height sets height of keyboard 5218171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung */ 5228171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung public Keyboard(Context context, int xmlLayoutResId, int modeId, int width, int height) { 5238171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung mDisplayWidth = width; 5248171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung mDisplayHeight = height; 5258171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung 5268171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung mDefaultHorizontalGap = 0; 5278171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung mDefaultWidth = mDisplayWidth / 10; 5288171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung mDefaultVerticalGap = 0; 5298171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung mDefaultHeight = mDefaultWidth; 5308171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung mKeys = new ArrayList<Key>(); 5318171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung mModifierKeys = new ArrayList<Key>(); 5328171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung mKeyboardMode = modeId; 5338171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung loadKeyboard(context, context.getResources().getXml(xmlLayoutResId)); 5348171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung } 5358171b5182f5f07d33c9dfdf2dd8f0f6ae9588039Jae Yong Sung 5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Creates a keyboard from the given xml key layout file. Weeds out rows 5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * that have a keyboard mode defined but don't match the specified mode. 5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param context the application or service context 5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param xmlLayoutResId the resource file that contains the keyboard layout and keys. 5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param modeId keyboard mode identifier 5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Keyboard(Context context, int xmlLayoutResId, int modeId) { 54458feea74b42bbaaa0552d76af23873bdd0b5dca2Mitsuru Oshima DisplayMetrics dm = context.getResources().getDisplayMetrics(); 54558feea74b42bbaaa0552d76af23873bdd0b5dca2Mitsuru Oshima mDisplayWidth = dm.widthPixels; 54658feea74b42bbaaa0552d76af23873bdd0b5dca2Mitsuru Oshima mDisplayHeight = dm.heightPixels; 54758feea74b42bbaaa0552d76af23873bdd0b5dca2Mitsuru Oshima //Log.v(TAG, "keyboard's display metrics:" + dm); 54858feea74b42bbaaa0552d76af23873bdd0b5dca2Mitsuru Oshima 5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDefaultHorizontalGap = 0; 5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDefaultWidth = mDisplayWidth / 10; 5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDefaultVerticalGap = 0; 5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDefaultHeight = mDefaultWidth; 5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mKeys = new ArrayList<Key>(); 5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mModifierKeys = new ArrayList<Key>(); 5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mKeyboardMode = modeId; 5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project loadKeyboard(context, context.getResources().getXml(xmlLayoutResId)); 5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>Creates a blank keyboard from the given resource file and populates it with the specified 5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * characters in left-to-right, top-to-bottom fashion, using the specified number of columns. 5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </p> 5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>If the specified number of columns is -1, then the keyboard will fit as many keys as 5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * possible in each row.</p> 5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param context the application or service context 5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param layoutTemplateResId the layout template file, containing no keys. 5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param characters the list of characters to display on the keyboard. One key will be created 5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * for each character. 5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param columns the number of columns of keys to display. If this number is greater than the 5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * number of keys that can fit in a row, it will be ignored. If this number is -1, the 5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * keyboard will fit as many keys as possible in each row. 5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Keyboard(Context context, int layoutTemplateResId, 5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CharSequence characters, int columns, int horizontalPadding) { 5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this(context, layoutTemplateResId); 5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int x = 0; 5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int y = 0; 5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int column = 0; 5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mTotalWidth = 0; 5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Row row = new Row(this); 5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project row.defaultHeight = mDefaultHeight; 5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project row.defaultWidth = mDefaultWidth; 5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project row.defaultHorizontalGap = mDefaultHorizontalGap; 5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project row.verticalGap = mDefaultVerticalGap; 5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project row.rowEdgeFlags = EDGE_TOP | EDGE_BOTTOM; 5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int maxColumns = columns == -1 ? Integer.MAX_VALUE : columns; 5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < characters.length(); i++) { 5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char c = characters.charAt(i); 5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (column >= maxColumns 5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project || x + mDefaultWidth + horizontalPadding > mDisplayWidth) { 5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project x = 0; 5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project y += mDefaultVerticalGap + mDefaultHeight; 5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project column = 0; 5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Key key = new Key(row); 5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project key.x = x; 5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project key.y = y; 5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project key.label = String.valueOf(c); 6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project key.codes = new int[] { c }; 6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project column++; 6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project x += key.width + key.gap; 6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mKeys.add(key); 604a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase row.mKeys.add(key); 6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (x > mTotalWidth) { 6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mTotalWidth = x; 6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 609a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase mTotalHeight = y + mDefaultHeight; 610a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase rows.add(row); 611a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase } 612a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase 613a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase final void resize(int newWidth, int newHeight) { 614a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase int numRows = rows.size(); 615a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase for (int rowIndex = 0; rowIndex < numRows; ++rowIndex) { 616a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase Row row = rows.get(rowIndex); 617a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase int numKeys = row.mKeys.size(); 618a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase int totalGap = 0; 619a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase int totalWidth = 0; 620a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase for (int keyIndex = 0; keyIndex < numKeys; ++keyIndex) { 621a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase Key key = row.mKeys.get(keyIndex); 622a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase if (keyIndex > 0) { 623a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase totalGap += key.gap; 624a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase } 625a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase totalWidth += key.width; 626a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase } 627a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase if (totalGap + totalWidth > newWidth) { 628a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase int x = 0; 629a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase float scaleFactor = (float)(newWidth - totalGap) / totalWidth; 630a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase for (int keyIndex = 0; keyIndex < numKeys; ++keyIndex) { 631a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase Key key = row.mKeys.get(keyIndex); 632a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase key.width *= scaleFactor; 633a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase key.x = x; 634a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase x += key.width + key.gap; 635a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase } 636a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase } 637a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase } 638a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase mTotalWidth = newWidth; 639a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase // TODO: This does not adjust the vertical placement according to the new size. 640a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase // The main problem in the previous code was horizontal placement/size, but we should 641a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase // also recalculate the vertical sizes/positions when we get this resize call. 6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public List<Key> getKeys() { 6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mKeys; 6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public List<Key> getModifierKeys() { 6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mModifierKeys; 6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected int getHorizontalGap() { 6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mDefaultHorizontalGap; 6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void setHorizontalGap(int gap) { 6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDefaultHorizontalGap = gap; 6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected int getVerticalGap() { 6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mDefaultVerticalGap; 6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void setVerticalGap(int gap) { 6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDefaultVerticalGap = gap; 6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected int getKeyHeight() { 6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mDefaultHeight; 6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void setKeyHeight(int height) { 6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDefaultHeight = height; 6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected int getKeyWidth() { 6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mDefaultWidth; 6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void setKeyWidth(int width) { 6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDefaultWidth = width; 6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the total height of the keyboard 6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return the total height of the keyboard 6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getHeight() { 6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mTotalHeight; 6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getMinWidth() { 6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mTotalWidth; 6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean setShifted(boolean shiftState) { 6976465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller for (Key shiftKey : mShiftKeys) { 6986465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller if (shiftKey != null) { 6996465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller shiftKey.on = shiftState; 7006465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller } 7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mShifted != shiftState) { 7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mShifted = shiftState; 7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean isShifted() { 7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mShifted; 7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7136465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller /** 7146465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller * @hide 7156465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller */ 7166465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller public int[] getShiftKeyIndices() { 7176465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller return mShiftKeyIndices; 7186465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller } 7196465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller 7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getShiftKeyIndex() { 7216465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller return mShiftKeyIndices[0]; 7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void computeNearestNeighbors() { 7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Round-up so we don't have any pixels outside the grid 7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCellWidth = (getMinWidth() + GRID_WIDTH - 1) / GRID_WIDTH; 7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCellHeight = (getHeight() + GRID_HEIGHT - 1) / GRID_HEIGHT; 7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGridNeighbors = new int[GRID_SIZE][]; 7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int[] indices = new int[mKeys.size()]; 7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int gridWidth = GRID_WIDTH * mCellWidth; 7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int gridHeight = GRID_HEIGHT * mCellHeight; 7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int x = 0; x < gridWidth; x += mCellWidth) { 7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int y = 0; y < gridHeight; y += mCellHeight) { 7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count = 0; 7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < mKeys.size(); i++) { 7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Key key = mKeys.get(i); 7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (key.squaredDistanceFrom(x, y) < mProximityThreshold || 7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project key.squaredDistanceFrom(x + mCellWidth - 1, y) < mProximityThreshold || 7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project key.squaredDistanceFrom(x + mCellWidth - 1, y + mCellHeight - 1) 7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project < mProximityThreshold || 7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project key.squaredDistanceFrom(x, y + mCellHeight - 1) < mProximityThreshold) { 7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project indices[count++] = i; 7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int [] cell = new int[count]; 7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.arraycopy(indices, 0, cell, 0, count); 7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGridNeighbors[(y / mCellHeight) * GRID_WIDTH + (x / mCellWidth)] = cell; 7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the indices of the keys that are closest to the given point. 7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param x the x-coordinate of the point 7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param y the y-coordinate of the point 7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return the array of integer indices for the nearest keys to the given point. If the given 7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * point is out of range, then an array of size zero is returned. 7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int[] getNearestKeys(int x, int y) { 7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mGridNeighbors == null) computeNearestNeighbors(); 7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (x >= 0 && x < getMinWidth() && y >= 0 && y < getHeight()) { 7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int index = (y / mCellHeight) * GRID_WIDTH + (x / mCellWidth); 7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (index < GRID_SIZE) { 7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mGridNeighbors[index]; 7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return new int[0]; 7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected Row createRowFromXml(Resources res, XmlResourceParser parser) { 7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return new Row(res, this, parser); 7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected Key createKeyFromXml(Resources res, Row parent, int x, int y, 7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project XmlResourceParser parser) { 7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return new Key(res, parent, x, y, parser); 7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void loadKeyboard(Context context, XmlResourceParser parser) { 7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean inKey = false; 7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean inRow = false; 7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean leftMostKey = false; 7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int row = 0; 7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int x = 0; 7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int y = 0; 7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Key key = null; 7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Row currentRow = null; 7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Resources res = context.getResources(); 7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean skipRow = false; 790a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase 7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int event; 7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while ((event = parser.next()) != XmlResourceParser.END_DOCUMENT) { 7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (event == XmlResourceParser.START_TAG) { 7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String tag = parser.getName(); 7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (TAG_ROW.equals(tag)) { 7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project inRow = true; 7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project x = 0; 7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project currentRow = createRowFromXml(res, parser); 800a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase rows.add(currentRow); 8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project skipRow = currentRow.mode != 0 && currentRow.mode != mKeyboardMode; 8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (skipRow) { 8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project skipToEndOfRow(parser); 8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project inRow = false; 8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (TAG_KEY.equals(tag)) { 8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project inKey = true; 8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project key = createKeyFromXml(res, currentRow, x, y, parser); 8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mKeys.add(key); 8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (key.codes[0] == KEYCODE_SHIFT) { 8116465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller // Find available shift key slot and put this shift key in it 8126465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller for (int i = 0; i < mShiftKeys.length; i++) { 8136465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller if (mShiftKeys[i] == null) { 8146465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller mShiftKeys[i] = key; 8156465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller mShiftKeyIndices[i] = mKeys.size()-1; 8166465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller break; 8176465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller } 8186465f7753783a614948fb3ffbd8c072345b4eea1Jim Miller } 8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mModifierKeys.add(key); 8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (key.codes[0] == KEYCODE_ALT) { 8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mModifierKeys.add(key); 8229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 823a95e1087b2258b118a7ccb2bedb44da359d3abd0Chet Haase currentRow.mKeys.add(key); 8249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (TAG_KEYBOARD.equals(tag)) { 8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project parseKeyboardAttributes(res, parser); 8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (event == XmlResourceParser.END_TAG) { 8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (inKey) { 8299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project inKey = false; 8309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project x += key.gap + key.width; 8319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (x > mTotalWidth) { 8329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mTotalWidth = x; 8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (inRow) { 8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project inRow = false; 8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project y += currentRow.verticalGap; 8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project y += currentRow.defaultHeight; 8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project row++; 8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // TODO: error or extend? 8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (Exception e) { 8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(TAG, "Parse error:" + e); 8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project e.printStackTrace(); 8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mTotalHeight = y - mDefaultVerticalGap; 8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void skipToEndOfRow(XmlResourceParser parser) 8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throws XmlPullParserException, IOException { 8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int event; 8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while ((event = parser.next()) != XmlResourceParser.END_DOCUMENT) { 8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (event == XmlResourceParser.END_TAG 8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project && parser.getName().equals(TAG_ROW)) { 8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void parseKeyboardAttributes(Resources res, XmlResourceParser parser) { 8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TypedArray a = res.obtainAttributes(Xml.asAttributeSet(parser), 8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project com.android.internal.R.styleable.Keyboard); 8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDefaultWidth = getDimensionOrFraction(a, 8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project com.android.internal.R.styleable.Keyboard_keyWidth, 8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDisplayWidth, mDisplayWidth / 10); 8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDefaultHeight = getDimensionOrFraction(a, 8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project com.android.internal.R.styleable.Keyboard_keyHeight, 8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDisplayHeight, 50); 8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDefaultHorizontalGap = getDimensionOrFraction(a, 8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project com.android.internal.R.styleable.Keyboard_horizontalGap, 8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDisplayWidth, 0); 8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDefaultVerticalGap = getDimensionOrFraction(a, 8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project com.android.internal.R.styleable.Keyboard_verticalGap, 8779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDisplayHeight, 0); 8789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mProximityThreshold = (int) (mDefaultWidth * SEARCH_DISTANCE); 8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mProximityThreshold = mProximityThreshold * mProximityThreshold; // Square it for comparison 8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project a.recycle(); 8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static int getDimensionOrFraction(TypedArray a, int index, int base, int defValue) { 8849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TypedValue value = a.peekValue(index); 8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (value == null) return defValue; 8869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (value.type == TypedValue.TYPE_DIMENSION) { 8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return a.getDimensionPixelOffset(index, defValue); 8889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (value.type == TypedValue.TYPE_FRACTION) { 8899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Round it to avoid values like 47.9999 from getting truncated 8909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return Math.round(a.getFraction(index, base, base, defValue)); 8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return defValue; 8939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 895