104c96ab966e8a58e5cd401362b49509751ce75d9Tadashi G. Takaoka/* 28632bff2d5a8e1160989008dea6eff4b94b065ddTadashi G. Takaoka * Copyright (C) 2011 The Android Open Source Project 304c96ab966e8a58e5cd401362b49509751ce75d9Tadashi G. Takaoka * 48aa9963a895f9dd5bb1bc92ab2e4f461e058f87aTadashi G. Takaoka * Licensed under the Apache License, Version 2.0 (the "License"); 58aa9963a895f9dd5bb1bc92ab2e4f461e058f87aTadashi G. Takaoka * you may not use this file except in compliance with the License. 68aa9963a895f9dd5bb1bc92ab2e4f461e058f87aTadashi G. Takaoka * You may obtain a copy of the License at 704c96ab966e8a58e5cd401362b49509751ce75d9Tadashi G. Takaoka * 88aa9963a895f9dd5bb1bc92ab2e4f461e058f87aTadashi G. Takaoka * http://www.apache.org/licenses/LICENSE-2.0 904c96ab966e8a58e5cd401362b49509751ce75d9Tadashi G. Takaoka * 1004c96ab966e8a58e5cd401362b49509751ce75d9Tadashi G. Takaoka * Unless required by applicable law or agreed to in writing, software 118aa9963a895f9dd5bb1bc92ab2e4f461e058f87aTadashi G. Takaoka * distributed under the License is distributed on an "AS IS" BASIS, 128aa9963a895f9dd5bb1bc92ab2e4f461e058f87aTadashi G. Takaoka * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 138aa9963a895f9dd5bb1bc92ab2e4f461e058f87aTadashi G. Takaoka * See the License for the specific language governing permissions and 148aa9963a895f9dd5bb1bc92ab2e4f461e058f87aTadashi G. Takaoka * limitations under the License. 1504c96ab966e8a58e5cd401362b49509751ce75d9Tadashi G. Takaoka */ 1604c96ab966e8a58e5cd401362b49509751ce75d9Tadashi G. Takaoka 1704c96ab966e8a58e5cd401362b49509751ce75d9Tadashi G. Takaokapackage com.android.inputmethod.keyboard; 1804c96ab966e8a58e5cd401362b49509751ce75d9Tadashi G. Takaoka 19a729377395967f7652d93992cbcf50cd2ff522d1Tadashi G. Takaokaimport android.content.Context; 2008ae0d5ca03ed455827e82222df249d1cafb5d71Tadashi G. Takaokaimport android.content.res.Resources; 2132572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaokaimport android.graphics.Paint; 225ef4fccbb90491e1f6c2e87b47ebf9f3659949fbTadashi G. Takaokaimport android.graphics.drawable.Drawable; 2332572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaoka 2415f6d4ae34664ea3d92827a2c3003198c0bac70bTadashi G. Takaokaimport com.android.inputmethod.annotations.UsedForTesting; 250e4f0da449d0fc4f0c4c6b49b4c24961da36a5d1Tadashi G. Takaokaimport com.android.inputmethod.keyboard.internal.KeyPreviewDrawParams; 2635ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaokaimport com.android.inputmethod.keyboard.internal.KeyboardBuilder; 275ef4fccbb90491e1f6c2e87b47ebf9f3659949fbTadashi G. Takaokaimport com.android.inputmethod.keyboard.internal.KeyboardIconsSet; 2835ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaokaimport com.android.inputmethod.keyboard.internal.KeyboardParams; 2935ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaokaimport com.android.inputmethod.keyboard.internal.MoreKeySpec; 3032572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaokaimport com.android.inputmethod.latin.R; 31cc8c8b99bd0463f5977dea82f5e2379ea1dd4e73Tadashi G. Takaokaimport com.android.inputmethod.latin.StringUtils; 3204c96ab966e8a58e5cd401362b49509751ce75d9Tadashi G. Takaoka 33a28a05e971cc242b338331a3b78276fa95188d19Tadashi G. Takaokapublic final class MoreKeysKeyboard extends Keyboard { 348da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka private final int mDefaultKeyCoordX; 3504c96ab966e8a58e5cd401362b49509751ce75d9Tadashi G. Takaoka 3635ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka MoreKeysKeyboard(final MoreKeysKeyboardParams params) { 378da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka super(params); 388da9a13760896cd78235b60d0ea680ea13620532Tadashi G. Takaoka mDefaultKeyCoordX = params.getDefaultKeyCoordX() + params.mDefaultKeyWidth / 2; 3904c96ab966e8a58e5cd401362b49509751ce75d9Tadashi G. Takaoka } 4004c96ab966e8a58e5cd401362b49509751ce75d9Tadashi G. Takaoka 4104c96ab966e8a58e5cd401362b49509751ce75d9Tadashi G. Takaoka public int getDefaultCoordX() { 4204c96ab966e8a58e5cd401362b49509751ce75d9Tadashi G. Takaoka return mDefaultKeyCoordX; 4304c96ab966e8a58e5cd401362b49509751ce75d9Tadashi G. Takaoka } 4432572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaoka 4515f6d4ae34664ea3d92827a2c3003198c0bac70bTadashi G. Takaoka @UsedForTesting 4635ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka static class MoreKeysKeyboardParams extends KeyboardParams { 4735ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka public boolean mIsFixedOrder; 4835ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka /* package */int mTopRowAdjustment; 4935ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka public int mNumRows; 5035ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka public int mNumColumns; 5135ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka public int mTopKeys; 5235ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka public int mLeftKeys; 5335ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka public int mRightKeys; // includes default key. 5435ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka public int mDividerWidth; 5535ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka public int mColumnWidth; 5635ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka 5735ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka public MoreKeysKeyboardParams() { 5835ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka super(); 5935ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka } 60e4c45c6ef920b9cd1754f345446f53c504a64c5fTadashi G. Takaoka 6135ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka /** 6235ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka * Set keyboard parameters of more keys keyboard. 6335ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka * 6435ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka * @param numKeys number of keys in this more keys keyboard. 6535ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka * @param maxColumns number of maximum columns of this more keys keyboard. 6635ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka * @param keyWidth more keys keyboard key width in pixel, including horizontal gap. 6735ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka * @param rowHeight more keys keyboard row height in pixel, including vertical gap. 6835ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka * @param coordXInParent coordinate x of the key preview in parent keyboard. 6935ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka * @param parentKeyboardWidth parent keyboard width in pixel. 7035ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka * @param isFixedColumnOrder if true, more keys should be laid out in fixed order. 7135ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka * @param dividerWidth width of divider, zero for no dividers. 7235ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka */ 7335ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka public void setParameters(final int numKeys, final int maxColumns, final int keyWidth, 7435ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka final int rowHeight, final int coordXInParent, final int parentKeyboardWidth, 7535ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka final boolean isFixedColumnOrder, final int dividerWidth) { 7635ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka mIsFixedOrder = isFixedColumnOrder; 77a4463d7a9a9b97ad0fba764698f75cd3bf036c12Tadashi G. Takaoka if (parentKeyboardWidth / keyWidth < Math.min(numKeys, maxColumns)) { 7835ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka throw new IllegalArgumentException( 7935ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka "Keyboard is too small to hold more keys keyboard: " 80a4463d7a9a9b97ad0fba764698f75cd3bf036c12Tadashi G. Takaoka + parentKeyboardWidth + " " + keyWidth + " " 81a4463d7a9a9b97ad0fba764698f75cd3bf036c12Tadashi G. Takaoka + numKeys + " " + maxColumns); 8232572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaoka } 8335ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka mDefaultKeyWidth = keyWidth; 8435ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka mDefaultRowHeight = rowHeight; 8535ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka 8635ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka final int numRows = (numKeys + maxColumns - 1) / maxColumns; 8735ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka mNumRows = numRows; 8835ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka final int numColumns = mIsFixedOrder ? Math.min(numKeys, maxColumns) 8935ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka : getOptimizedColumns(numKeys, maxColumns); 9035ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka mNumColumns = numColumns; 9135ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka final int topKeys = numKeys % numColumns; 9235ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka mTopKeys = topKeys == 0 ? numColumns : topKeys; 9335ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka 9435ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka final int numLeftKeys = (numColumns - 1) / 2; 9535ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka final int numRightKeys = numColumns - numLeftKeys; // including default key. 9635ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka // Maximum number of keys we can layout both side of the parent key 9735ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka final int maxLeftKeys = coordXInParent / keyWidth; 9835ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka final int maxRightKeys = (parentKeyboardWidth - coordXInParent) / keyWidth; 9935ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka int leftKeys, rightKeys; 10035ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka if (numLeftKeys > maxLeftKeys) { 10135ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka leftKeys = maxLeftKeys; 10235ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka rightKeys = numColumns - leftKeys; 10335ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka } else if (numRightKeys > maxRightKeys + 1) { 10435ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka rightKeys = maxRightKeys + 1; // include default key 10535ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka leftKeys = numColumns - rightKeys; 10635ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka } else { 10735ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka leftKeys = numLeftKeys; 10835ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka rightKeys = numRightKeys; 10932572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaoka } 11035ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka // If the left keys fill the left side of the parent key, entire more keys keyboard 11135ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka // should be shifted to the right unless the parent key is on the left edge. 11235ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka if (maxLeftKeys == leftKeys && leftKeys > 0) { 11335ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka leftKeys--; 11435ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka rightKeys++; 115aeeed758480b0fac848f4556884d978f3004555bTadashi G. Takaoka } 11635ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka // If the right keys fill the right side of the parent key, entire more keys 11735ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka // should be shifted to the left unless the parent key is on the right edge. 11835ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka if (maxRightKeys == rightKeys - 1 && rightKeys > 1) { 11935ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka leftKeys++; 12035ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka rightKeys--; 121aeeed758480b0fac848f4556884d978f3004555bTadashi G. Takaoka } 12235ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka mLeftKeys = leftKeys; 12335ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka mRightKeys = rightKeys; 12435ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka 12535ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka // Adjustment of the top row. 12635ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka mTopRowAdjustment = mIsFixedOrder ? getFixedOrderTopRowAdjustment() 12735ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka : getAutoOrderTopRowAdjustment(); 12835ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka mDividerWidth = dividerWidth; 12935ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka mColumnWidth = mDefaultKeyWidth + mDividerWidth; 13035ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka mBaseWidth = mOccupiedWidth = mNumColumns * mColumnWidth - mDividerWidth; 13135ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka // Need to subtract the bottom row's gutter only. 13235ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka mBaseHeight = mOccupiedHeight = mNumRows * mDefaultRowHeight - mVerticalGap 13335ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka + mTopPadding + mBottomPadding; 13435ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka } 135aeeed758480b0fac848f4556884d978f3004555bTadashi G. Takaoka 13635ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka private int getFixedOrderTopRowAdjustment() { 13735ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka if (mNumRows == 1 || mTopKeys % 2 == 1 || mTopKeys == mNumColumns 13835ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka || mLeftKeys == 0 || mRightKeys == 1) { 13935ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka return 0; 140aeeed758480b0fac848f4556884d978f3004555bTadashi G. Takaoka } 14135ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka return -1; 14235ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka } 143aeeed758480b0fac848f4556884d978f3004555bTadashi G. Takaoka 14435ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka private int getAutoOrderTopRowAdjustment() { 14535ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka if (mNumRows == 1 || mTopKeys == 1 || mNumColumns % 2 == mTopKeys % 2 14635ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka || mLeftKeys == 0 || mRightKeys == 1) { 14735ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka return 0; 148aeeed758480b0fac848f4556884d978f3004555bTadashi G. Takaoka } 14935ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka return -1; 15035ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka } 151aeeed758480b0fac848f4556884d978f3004555bTadashi G. Takaoka 15235ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka // Return key position according to column count (0 is default). 15335ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka /* package */int getColumnPos(final int n) { 15435ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka return mIsFixedOrder ? getFixedOrderColumnPos(n) : getAutomaticColumnPos(n); 15535ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka } 156aeeed758480b0fac848f4556884d978f3004555bTadashi G. Takaoka 15735ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka private int getFixedOrderColumnPos(final int n) { 15835ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka final int col = n % mNumColumns; 15935ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka final int row = n / mNumColumns; 16035ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka if (!isTopRow(row)) { 16135ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka return col - mLeftKeys; 16235ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka } 16335ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka final int rightSideKeys = mTopKeys / 2; 16435ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka final int leftSideKeys = mTopKeys - (rightSideKeys + 1); 16535ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka final int pos = col - leftSideKeys; 16635ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka final int numLeftKeys = mLeftKeys + mTopRowAdjustment; 16735ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka final int numRightKeys = mRightKeys - 1; 16835ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka if (numRightKeys >= rightSideKeys && numLeftKeys >= leftSideKeys) { 16932572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaoka return pos; 17035ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka } else if (numRightKeys < rightSideKeys) { 17135ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka return pos - (rightSideKeys - numRightKeys); 17235ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka } else { // numLeftKeys < leftSideKeys 17335ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka return pos + (leftSideKeys - numLeftKeys); 17432572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaoka } 17535ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka } 17632572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaoka 17735ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka private int getAutomaticColumnPos(final int n) { 17835ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka final int col = n % mNumColumns; 17935ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka final int row = n / mNumColumns; 18035ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka int leftKeys = mLeftKeys; 18135ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka if (isTopRow(row)) { 18235ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka leftKeys += mTopRowAdjustment; 18335ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka } 18435ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka if (col == 0) { 18535ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka // default position. 18635ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka return 0; 18732572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaoka } 18832572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaoka 18935ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka int pos = 0; 19035ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka int right = 1; // include default position key. 19135ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka int left = 0; 19235ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka int i = 0; 19335ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka while (true) { 19435ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka // Assign right key if available. 19535ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka if (right < mRightKeys) { 19635ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka pos = right; 19735ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka right++; 19835ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka i++; 19932572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaoka } 20035ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka if (i >= col) 20135ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka break; 20235ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka // Assign left key if available. 20335ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka if (left < leftKeys) { 20435ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka left++; 20535ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka pos = -left; 20635ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka i++; 20735ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka } 20835ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka if (i >= col) 20935ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka break; 21032572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaoka } 21135ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka return pos; 21235ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka } 21332572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaoka 21435ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka private static int getTopRowEmptySlots(final int numKeys, final int numColumns) { 21535ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka final int remainings = numKeys % numColumns; 21635ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka return remainings == 0 ? 0 : numColumns - remainings; 21735ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka } 21832572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaoka 21935ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka private int getOptimizedColumns(final int numKeys, final int maxColumns) { 22035ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka int numColumns = Math.min(numKeys, maxColumns); 22135ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka while (getTopRowEmptySlots(numKeys, numColumns) >= mNumRows) { 22235ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka numColumns--; 22332572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaoka } 22435ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka return numColumns; 22535ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka } 22632572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaoka 22735ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka public int getDefaultKeyCoordX() { 22835ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka return mLeftKeys * mColumnWidth; 22935ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka } 23032572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaoka 23135ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka public int getX(final int n, final int row) { 23235ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka final int x = getColumnPos(n) * mColumnWidth + getDefaultKeyCoordX(); 23335ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka if (isTopRow(row)) { 23435ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka return x + mTopRowAdjustment * (mColumnWidth / 2); 23532572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaoka } 23635ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka return x; 23735ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka } 23832572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaoka 23935ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka public int getY(final int row) { 24035ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka return (mNumRows - 1 - row) * mDefaultRowHeight + mTopPadding; 24132572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaoka } 24232572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaoka 24335ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka public void markAsEdgeKey(final Key key, final int row) { 24435ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka if (row == 0) 24535ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka key.markAsTopEdge(this); 24635ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka if (isTopRow(row)) 24735ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka key.markAsBottomEdge(this); 24835ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka } 24935ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka 25035ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka private boolean isTopRow(final int rowCount) { 25135ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka return mNumRows > 1 && rowCount == mNumRows - 1; 25235ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka } 25335ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka } 25435ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka 25535ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka public static class Builder extends KeyboardBuilder<MoreKeysKeyboardParams> { 25635ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka private final Key mParentKey; 25735ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka private final Drawable mDivider; 25835ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka 25935ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka private static final float LABEL_PADDING_RATIO = 0.2f; 26035ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka private static final float DIVIDER_RATIO = 0.2f; 26135ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka 2627ecc1081ab9b4e41e4b2aec7877aaaf8df29e611Tadashi G. Takaoka /** 2637ecc1081ab9b4e41e4b2aec7877aaaf8df29e611Tadashi G. Takaoka * The builder of MoreKeysKeyboard. 264a729377395967f7652d93992cbcf50cd2ff522d1Tadashi G. Takaoka * @param context the context of {@link MoreKeysKeyboardView}. 2657ecc1081ab9b4e41e4b2aec7877aaaf8df29e611Tadashi G. Takaoka * @param parentKey the {@link Key} that invokes more keys keyboard. 2667ecc1081ab9b4e41e4b2aec7877aaaf8df29e611Tadashi G. Takaoka * @param parentKeyboardView the {@link KeyboardView} that contains the parentKey. 2670e4f0da449d0fc4f0c4c6b49b4c24961da36a5d1Tadashi G. Takaoka * @param keyPreviewDrawParams the parameter to place key preview. 2687ecc1081ab9b4e41e4b2aec7877aaaf8df29e611Tadashi G. Takaoka */ 269a729377395967f7652d93992cbcf50cd2ff522d1Tadashi G. Takaoka public Builder(final Context context, final Key parentKey, 2700e4f0da449d0fc4f0c4c6b49b4c24961da36a5d1Tadashi G. Takaoka final MainKeyboardView parentKeyboardView, 2710e4f0da449d0fc4f0c4c6b49b4c24961da36a5d1Tadashi G. Takaoka final KeyPreviewDrawParams keyPreviewDrawParams) { 272a729377395967f7652d93992cbcf50cd2ff522d1Tadashi G. Takaoka super(context, new MoreKeysKeyboardParams()); 2737ecc1081ab9b4e41e4b2aec7877aaaf8df29e611Tadashi G. Takaoka final Keyboard parentKeyboard = parentKeyboardView.getKeyboard(); 2747ecc1081ab9b4e41e4b2aec7877aaaf8df29e611Tadashi G. Takaoka load(parentKeyboard.mMoreKeysTemplate, parentKeyboard.mId); 27532572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaoka 2762affaf91a04d63e0994102299816014a8bbe11e1Tadashi G. Takaoka // TODO: More keys keyboard's vertical gap is currently calculated heuristically. 277ea0c567f86bd19015d53fc038c4579df776cfec3Tadashi G. Takaoka // Should revise the algorithm. 278ea0c567f86bd19015d53fc038c4579df776cfec3Tadashi G. Takaoka mParams.mVerticalGap = parentKeyboard.mVerticalGap / 2; 27942fd1d2d72c097b2227d4b22f0f824dbb34a4d0cTadashi G. Takaoka mParentKey = parentKey; 28032572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaoka 281a0e4f40994f779ad98268921c63d6535ad04224fTadashi G. Takaoka final int width, height; 2827ecc1081ab9b4e41e4b2aec7877aaaf8df29e611Tadashi G. Takaoka final boolean singleMoreKeyWithPreview = parentKeyboardView.isKeyPreviewPopupEnabled() 2837ecc1081ab9b4e41e4b2aec7877aaaf8df29e611Tadashi G. Takaoka && !parentKey.noKeyPreview() && parentKey.mMoreKeys.length == 1; 28442fd1d2d72c097b2227d4b22f0f824dbb34a4d0cTadashi G. Takaoka if (singleMoreKeyWithPreview) { 2857ecc1081ab9b4e41e4b2aec7877aaaf8df29e611Tadashi G. Takaoka // Use pre-computed width and height if this more keys keyboard has only one key to 2867ecc1081ab9b4e41e4b2aec7877aaaf8df29e611Tadashi G. Takaoka // mitigate visual flicker between key preview and more keys keyboard. 2877ecc1081ab9b4e41e4b2aec7877aaaf8df29e611Tadashi G. Takaoka // Caveats for the visual assets: To achieve this effect, both the key preview 2887ecc1081ab9b4e41e4b2aec7877aaaf8df29e611Tadashi G. Takaoka // backgrounds and the more keys keyboard panel background have the exact same 2897ecc1081ab9b4e41e4b2aec7877aaaf8df29e611Tadashi G. Takaoka // left/right/top paddings. The bottom paddings of both backgrounds don't need to 2907ecc1081ab9b4e41e4b2aec7877aaaf8df29e611Tadashi G. Takaoka // be considered because the vertical positions of both backgrounds were already 2917ecc1081ab9b4e41e4b2aec7877aaaf8df29e611Tadashi G. Takaoka // adjusted with their bottom paddings deducted. 2920e4f0da449d0fc4f0c4c6b49b4c24961da36a5d1Tadashi G. Takaoka width = keyPreviewDrawParams.mPreviewVisibleWidth; 29308ae0d5ca03ed455827e82222df249d1cafb5d71Tadashi G. Takaoka height = keyPreviewDrawParams.mPreviewVisibleHeight + mParams.mVerticalGap; 294bd8e92d8431418929276fb739f0113e2297c9d00Tadashi G. Takaoka // TODO: Remove this check. 295bd8e92d8431418929276fb739f0113e2297c9d00Tadashi G. Takaoka if (width == 0) { 296bd8e92d8431418929276fb739f0113e2297c9d00Tadashi G. Takaoka throw new IllegalArgumentException( 297bd8e92d8431418929276fb739f0113e2297c9d00Tadashi G. Takaoka "Zero width key detected: " + parentKey + " in " + parentKeyboard.mId); 298bd8e92d8431418929276fb739f0113e2297c9d00Tadashi G. Takaoka } 299a0e4f40994f779ad98268921c63d6535ad04224fTadashi G. Takaoka } else { 30008ae0d5ca03ed455827e82222df249d1cafb5d71Tadashi G. Takaoka width = getMaxKeyWidth(parentKeyboardView, parentKey, mParams.mDefaultKeyWidth, 30108ae0d5ca03ed455827e82222df249d1cafb5d71Tadashi G. Takaoka context.getResources()); 302a0e4f40994f779ad98268921c63d6535ad04224fTadashi G. Takaoka height = parentKeyboard.mMostCommonKeyHeight; 303bd8e92d8431418929276fb739f0113e2297c9d00Tadashi G. Takaoka // TODO: Remove this check. 304bd8e92d8431418929276fb739f0113e2297c9d00Tadashi G. Takaoka if (width == 0) { 305bd8e92d8431418929276fb739f0113e2297c9d00Tadashi G. Takaoka throw new IllegalArgumentException( 306bd8e92d8431418929276fb739f0113e2297c9d00Tadashi G. Takaoka "Zero width calculated: " + parentKey 307bd8e92d8431418929276fb739f0113e2297c9d00Tadashi G. Takaoka + " moreKeys=" + java.util.Arrays.toString(parentKey.mMoreKeys) 308bd8e92d8431418929276fb739f0113e2297c9d00Tadashi G. Takaoka + " in " + parentKeyboard.mId); 309bd8e92d8431418929276fb739f0113e2297c9d00Tadashi G. Takaoka } 310a0e4f40994f779ad98268921c63d6535ad04224fTadashi G. Takaoka } 3115ef4fccbb90491e1f6c2e87b47ebf9f3659949fbTadashi G. Takaoka final int dividerWidth; 3125ef4fccbb90491e1f6c2e87b47ebf9f3659949fbTadashi G. Takaoka if (parentKey.needsDividersInMoreKeys()) { 3135ef4fccbb90491e1f6c2e87b47ebf9f3659949fbTadashi G. Takaoka mDivider = mResources.getDrawable(R.drawable.more_keys_divider); 3145ef4fccbb90491e1f6c2e87b47ebf9f3659949fbTadashi G. Takaoka dividerWidth = (int)(width * DIVIDER_RATIO); 3155ef4fccbb90491e1f6c2e87b47ebf9f3659949fbTadashi G. Takaoka } else { 3165ef4fccbb90491e1f6c2e87b47ebf9f3659949fbTadashi G. Takaoka mDivider = null; 3175ef4fccbb90491e1f6c2e87b47ebf9f3659949fbTadashi G. Takaoka dividerWidth = 0; 3185ef4fccbb90491e1f6c2e87b47ebf9f3659949fbTadashi G. Takaoka } 31942fd1d2d72c097b2227d4b22f0f824dbb34a4d0cTadashi G. Takaoka mParams.setParameters(parentKey.mMoreKeys.length, parentKey.getMoreKeysColumn(), 3207ecc1081ab9b4e41e4b2aec7877aaaf8df29e611Tadashi G. Takaoka width, height, parentKey.mX + parentKey.mWidth / 2, 3217ecc1081ab9b4e41e4b2aec7877aaaf8df29e611Tadashi G. Takaoka parentKeyboardView.getMeasuredWidth(), parentKey.isFixedColumnOrderMoreKeys(), 3227ecc1081ab9b4e41e4b2aec7877aaaf8df29e611Tadashi G. Takaoka dividerWidth); 32332572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaoka } 32432572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaoka 32535ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka private static int getMaxKeyWidth(final KeyboardView view, final Key parentKey, 32608ae0d5ca03ed455827e82222df249d1cafb5d71Tadashi G. Takaoka final int minKeyWidth, final Resources res) { 32708ae0d5ca03ed455827e82222df249d1cafb5d71Tadashi G. Takaoka final float padding = 32808ae0d5ca03ed455827e82222df249d1cafb5d71Tadashi G. Takaoka res.getDimension(R.dimen.more_keys_keyboard_key_horizontal_padding) 32908ae0d5ca03ed455827e82222df249d1cafb5d71Tadashi G. Takaoka + (parentKey.hasLabelsInMoreKeys() ? minKeyWidth * LABEL_PADDING_RATIO : 0.0f); 33008ae0d5ca03ed455827e82222df249d1cafb5d71Tadashi G. Takaoka final Paint paint = view.newLabelPaint(parentKey); 3312315bfc7c8df0f6d9fb627456f2a298f5580b52dTadashi G. Takaoka int maxWidth = minKeyWidth; 332ed3bac91f242850c6d1833a5f8981b9cc208c5ddTadashi G. Takaoka for (final MoreKeySpec spec : parentKey.mMoreKeys) { 333ed3bac91f242850c6d1833a5f8981b9cc208c5ddTadashi G. Takaoka final String label = spec.mLabel; 334bd7b160cfb05ee543e3cb6ddc7bd231b3f3aba0bTadashi G. Takaoka // If the label is single letter, minKeyWidth is enough to hold the label. 335cc8c8b99bd0463f5977dea82f5e2379ea1dd4e73Tadashi G. Takaoka if (label != null && StringUtils.codePointCount(label) > 1) { 33608ae0d5ca03ed455827e82222df249d1cafb5d71Tadashi G. Takaoka maxWidth = Math.max(maxWidth, 33708ae0d5ca03ed455827e82222df249d1cafb5d71Tadashi G. Takaoka (int)(TypefaceUtils.getLabelWidth(label, paint) + padding)); 33832572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaoka } 33932572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaoka } 340be34d973349909196dc3427a5653f4e119092ea7Tadashi G. Takaoka return maxWidth; 34132572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaoka } 34232572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaoka 34332572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaoka @Override 3442affaf91a04d63e0994102299816014a8bbe11e1Tadashi G. Takaoka public MoreKeysKeyboard build() { 3452affaf91a04d63e0994102299816014a8bbe11e1Tadashi G. Takaoka final MoreKeysKeyboardParams params = mParams; 346ab0d0d8a021a9b0f179281ac9e18604ad331cc43Tadashi G. Takaoka final int moreKeyFlags = mParentKey.getMoreKeyLabelFlags(); 347ed3bac91f242850c6d1833a5f8981b9cc208c5ddTadashi G. Takaoka final MoreKeySpec[] moreKeys = mParentKey.mMoreKeys; 34842fd1d2d72c097b2227d4b22f0f824dbb34a4d0cTadashi G. Takaoka for (int n = 0; n < moreKeys.length; n++) { 349ed3bac91f242850c6d1833a5f8981b9cc208c5ddTadashi G. Takaoka final MoreKeySpec moreKeySpec = moreKeys[n]; 35032572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaoka final int row = n / params.mNumColumns; 3515ef4fccbb90491e1f6c2e87b47ebf9f3659949fbTadashi G. Takaoka final int x = params.getX(n, row); 3525ef4fccbb90491e1f6c2e87b47ebf9f3659949fbTadashi G. Takaoka final int y = params.getY(row); 353ed3bac91f242850c6d1833a5f8981b9cc208c5ddTadashi G. Takaoka final Key key = new Key(params, moreKeySpec, x, y, 3545ef4fccbb90491e1f6c2e87b47ebf9f3659949fbTadashi G. Takaoka params.mDefaultKeyWidth, params.mDefaultRowHeight, moreKeyFlags); 3552fc4248700023853980b0006c12425079e3f9257Tadashi G. Takaoka params.markAsEdgeKey(key, row); 35632572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaoka params.onAddKey(key); 3575ef4fccbb90491e1f6c2e87b47ebf9f3659949fbTadashi G. Takaoka 3585ef4fccbb90491e1f6c2e87b47ebf9f3659949fbTadashi G. Takaoka final int pos = params.getColumnPos(n); 3595ef4fccbb90491e1f6c2e87b47ebf9f3659949fbTadashi G. Takaoka // The "pos" value represents the offset from the default position. Negative means 3605ef4fccbb90491e1f6c2e87b47ebf9f3659949fbTadashi G. Takaoka // left of the default position. 3615ef4fccbb90491e1f6c2e87b47ebf9f3659949fbTadashi G. Takaoka if (params.mDividerWidth > 0 && pos != 0) { 3625ef4fccbb90491e1f6c2e87b47ebf9f3659949fbTadashi G. Takaoka final int dividerX = (pos > 0) ? x - params.mDividerWidth 3635ef4fccbb90491e1f6c2e87b47ebf9f3659949fbTadashi G. Takaoka : x + params.mDefaultKeyWidth; 3645ef4fccbb90491e1f6c2e87b47ebf9f3659949fbTadashi G. Takaoka final Key divider = new MoreKeyDivider(params, mDivider, dividerX, y); 3655ef4fccbb90491e1f6c2e87b47ebf9f3659949fbTadashi G. Takaoka params.onAddKey(divider); 3665ef4fccbb90491e1f6c2e87b47ebf9f3659949fbTadashi G. Takaoka } 36732572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaoka } 3682affaf91a04d63e0994102299816014a8bbe11e1Tadashi G. Takaoka return new MoreKeysKeyboard(params); 36932572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaoka } 37032572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaoka } 37135ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka 37235ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka private static class MoreKeyDivider extends Key.Spacer { 37335ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka private final Drawable mIcon; 37435ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka 37535ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka public MoreKeyDivider(final MoreKeysKeyboardParams params, final Drawable icon, 37635ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka final int x, final int y) { 37735ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka super(params, x, y, params.mDividerWidth, params.mDefaultRowHeight); 37835ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka mIcon = icon; 37935ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka } 38035ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka 38135ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka @Override 38235ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka public Drawable getIcon(final KeyboardIconsSet iconSet, final int alpha) { 38335ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka // KeyboardIconsSet and alpha are unused. Use the icon that has been passed to the 38435ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka // constructor. 38535ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka // TODO: Drawable itself should have an alpha value. 38635ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka mIcon.setAlpha(128); 38735ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka return mIcon; 38835ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka } 38935ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka } 39004c96ab966e8a58e5cd401362b49509751ce75d9Tadashi G. Takaoka} 391