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;
2032572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaokaimport android.graphics.Paint;
215ef4fccbb90491e1f6c2e87b47ebf9f3659949fbTadashi G. Takaokaimport android.graphics.drawable.Drawable;
2232572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaoka
2315f6d4ae34664ea3d92827a2c3003198c0bac70bTadashi G. Takaokaimport com.android.inputmethod.annotations.UsedForTesting;
240e4f0da449d0fc4f0c4c6b49b4c24961da36a5d1Tadashi G. Takaokaimport com.android.inputmethod.keyboard.internal.KeyPreviewDrawParams;
2535ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaokaimport com.android.inputmethod.keyboard.internal.KeyboardBuilder;
265ef4fccbb90491e1f6c2e87b47ebf9f3659949fbTadashi G. Takaokaimport com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
2735ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaokaimport com.android.inputmethod.keyboard.internal.KeyboardParams;
2835ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaokaimport com.android.inputmethod.keyboard.internal.MoreKeySpec;
2932572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaokaimport com.android.inputmethod.latin.R;
30e28eba5074664d5716b8e58b8d0a235746b261ebKen Wakasaimport com.android.inputmethod.latin.utils.StringUtils;
31ccf4a310279b13bbf0b6aac76a0878178c1dfb7dTadashi G. Takaokaimport com.android.inputmethod.latin.utils.TypefaceUtils;
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)) {
78b0e76724edcde33dbfa17b56c3f5858705cd06eeTadashi G. Takaoka                throw new IllegalArgumentException("Keyboard is too small to hold more keys: "
79b0e76724edcde33dbfa17b56c3f5858705cd06eeTadashi G. Takaoka                        + parentKeyboardWidth + " " + keyWidth + " " + numKeys + " " + maxColumns);
8032572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaoka            }
8135ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            mDefaultKeyWidth = keyWidth;
8235ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            mDefaultRowHeight = rowHeight;
8335ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka
8435ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            final int numRows = (numKeys + maxColumns - 1) / maxColumns;
8535ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            mNumRows = numRows;
8635ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            final int numColumns = mIsFixedOrder ? Math.min(numKeys, maxColumns)
8735ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka                    : getOptimizedColumns(numKeys, maxColumns);
8835ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            mNumColumns = numColumns;
8935ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            final int topKeys = numKeys % numColumns;
9035ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            mTopKeys = topKeys == 0 ? numColumns : topKeys;
9135ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka
9235ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            final int numLeftKeys = (numColumns - 1) / 2;
9335ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            final int numRightKeys = numColumns - numLeftKeys; // including default key.
9435ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            // Maximum number of keys we can layout both side of the parent key
9535ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            final int maxLeftKeys = coordXInParent / keyWidth;
9635ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            final int maxRightKeys = (parentKeyboardWidth - coordXInParent) / keyWidth;
9735ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            int leftKeys, rightKeys;
9835ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            if (numLeftKeys > maxLeftKeys) {
9935ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka                leftKeys = maxLeftKeys;
10035ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka                rightKeys = numColumns - leftKeys;
10135ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            } else if (numRightKeys > maxRightKeys + 1) {
10235ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka                rightKeys = maxRightKeys + 1; // include default key
10335ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka                leftKeys = numColumns - rightKeys;
10435ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            } else {
10535ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka                leftKeys = numLeftKeys;
10635ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka                rightKeys = numRightKeys;
10732572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaoka            }
10835ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            // If the left keys fill the left side of the parent key, entire more keys keyboard
10935ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            // should be shifted to the right unless the parent key is on the left edge.
11035ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            if (maxLeftKeys == leftKeys && leftKeys > 0) {
11135ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka                leftKeys--;
11235ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka                rightKeys++;
113aeeed758480b0fac848f4556884d978f3004555bTadashi G. Takaoka            }
11435ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            // If the right keys fill the right side of the parent key, entire more keys
11535ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            // should be shifted to the left unless the parent key is on the right edge.
11635ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            if (maxRightKeys == rightKeys - 1 && rightKeys > 1) {
11735ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka                leftKeys++;
11835ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka                rightKeys--;
119aeeed758480b0fac848f4556884d978f3004555bTadashi G. Takaoka            }
12035ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            mLeftKeys = leftKeys;
12135ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            mRightKeys = rightKeys;
12235ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka
12335ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            // Adjustment of the top row.
12435ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            mTopRowAdjustment = mIsFixedOrder ? getFixedOrderTopRowAdjustment()
12535ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka                    : getAutoOrderTopRowAdjustment();
12635ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            mDividerWidth = dividerWidth;
12735ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            mColumnWidth = mDefaultKeyWidth + mDividerWidth;
12835ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            mBaseWidth = mOccupiedWidth = mNumColumns * mColumnWidth - mDividerWidth;
12935ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            // Need to subtract the bottom row's gutter only.
13035ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            mBaseHeight = mOccupiedHeight = mNumRows * mDefaultRowHeight - mVerticalGap
13135ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka                    + mTopPadding + mBottomPadding;
13235ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka        }
133aeeed758480b0fac848f4556884d978f3004555bTadashi G. Takaoka
13435ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka        private int getFixedOrderTopRowAdjustment() {
13535ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            if (mNumRows == 1 || mTopKeys % 2 == 1 || mTopKeys == mNumColumns
13635ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka                    || mLeftKeys == 0  || mRightKeys == 1) {
13735ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka                return 0;
138aeeed758480b0fac848f4556884d978f3004555bTadashi G. Takaoka            }
13935ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            return -1;
14035ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka        }
141aeeed758480b0fac848f4556884d978f3004555bTadashi G. Takaoka
14235ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka        private int getAutoOrderTopRowAdjustment() {
14335ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            if (mNumRows == 1 || mTopKeys == 1 || mNumColumns % 2 == mTopKeys % 2
14435ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka                    || mLeftKeys == 0 || mRightKeys == 1) {
14535ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka                return 0;
146aeeed758480b0fac848f4556884d978f3004555bTadashi G. Takaoka            }
14735ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            return -1;
14835ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka        }
149aeeed758480b0fac848f4556884d978f3004555bTadashi G. Takaoka
15035ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka        // Return key position according to column count (0 is default).
15135ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka        /* package */int getColumnPos(final int n) {
15235ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            return mIsFixedOrder ? getFixedOrderColumnPos(n) : getAutomaticColumnPos(n);
15335ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka        }
154aeeed758480b0fac848f4556884d978f3004555bTadashi G. Takaoka
15535ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka        private int getFixedOrderColumnPos(final int n) {
15635ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            final int col = n % mNumColumns;
15735ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            final int row = n / mNumColumns;
15835ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            if (!isTopRow(row)) {
15935ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka                return col - mLeftKeys;
16035ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            }
16135ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            final int rightSideKeys = mTopKeys / 2;
16235ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            final int leftSideKeys = mTopKeys - (rightSideKeys + 1);
16335ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            final int pos = col - leftSideKeys;
16435ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            final int numLeftKeys = mLeftKeys + mTopRowAdjustment;
16535ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            final int numRightKeys = mRightKeys - 1;
16635ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            if (numRightKeys >= rightSideKeys && numLeftKeys >= leftSideKeys) {
16732572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaoka                return pos;
16835ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            } else if (numRightKeys < rightSideKeys) {
16935ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka                return pos - (rightSideKeys - numRightKeys);
17035ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            } else { // numLeftKeys < leftSideKeys
17135ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka                return pos + (leftSideKeys - numLeftKeys);
17232572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaoka            }
17335ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka        }
17432572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaoka
17535ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka        private int getAutomaticColumnPos(final int n) {
17635ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            final int col = n % mNumColumns;
17735ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            final int row = n / mNumColumns;
17835ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            int leftKeys = mLeftKeys;
17935ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            if (isTopRow(row)) {
18035ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka                leftKeys += mTopRowAdjustment;
18135ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            }
18235ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            if (col == 0) {
18335ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka                // default position.
18435ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka                return 0;
18532572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaoka            }
18632572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaoka
18735ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            int pos = 0;
18835ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            int right = 1; // include default position key.
18935ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            int left = 0;
19035ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            int i = 0;
19135ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            while (true) {
19235ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka                // Assign right key if available.
19335ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka                if (right < mRightKeys) {
19435ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka                    pos = right;
19535ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka                    right++;
19635ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka                    i++;
19732572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaoka                }
19835ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka                if (i >= col)
19935ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka                    break;
20035ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka                // Assign left key if available.
20135ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka                if (left < leftKeys) {
20235ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka                    left++;
20335ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka                    pos = -left;
20435ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka                    i++;
20535ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka                }
20635ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka                if (i >= col)
20735ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka                    break;
20832572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaoka            }
20935ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            return pos;
21035ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka        }
21132572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaoka
21235ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka        private static int getTopRowEmptySlots(final int numKeys, final int numColumns) {
21335ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            final int remainings = numKeys % numColumns;
21435ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            return remainings == 0 ? 0 : numColumns - remainings;
21535ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka        }
21632572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaoka
21735ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka        private int getOptimizedColumns(final int numKeys, final int maxColumns) {
21835ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            int numColumns = Math.min(numKeys, maxColumns);
21935ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            while (getTopRowEmptySlots(numKeys, numColumns) >= mNumRows) {
22035ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka                numColumns--;
22132572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaoka            }
22235ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            return numColumns;
22335ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka        }
22432572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaoka
22535ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka        public int getDefaultKeyCoordX() {
22635ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            return mLeftKeys * mColumnWidth;
22735ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka        }
22832572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaoka
22935ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka        public int getX(final int n, final int row) {
23035ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            final int x = getColumnPos(n) * mColumnWidth + getDefaultKeyCoordX();
23135ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            if (isTopRow(row)) {
23235ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka                return x + mTopRowAdjustment * (mColumnWidth / 2);
23332572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaoka            }
23435ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            return x;
23535ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka        }
23632572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaoka
23735ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka        public int getY(final int row) {
23835ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            return (mNumRows - 1 - row) * mDefaultRowHeight + mTopPadding;
23932572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaoka        }
24032572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaoka
24135ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka        public void markAsEdgeKey(final Key key, final int row) {
24235ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            if (row == 0)
24335ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka                key.markAsTopEdge(this);
24435ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            if (isTopRow(row))
24535ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka                key.markAsBottomEdge(this);
24635ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka        }
24735ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka
24835ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka        private boolean isTopRow(final int rowCount) {
24935ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            return mNumRows > 1 && rowCount == mNumRows - 1;
25035ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka        }
25135ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka    }
25235ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka
25335ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka    public static class Builder extends KeyboardBuilder<MoreKeysKeyboardParams> {
25435ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka        private final Key mParentKey;
25535ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka        private final Drawable mDivider;
25635ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka
25735ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka        private static final float LABEL_PADDING_RATIO = 0.2f;
25835ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka        private static final float DIVIDER_RATIO = 0.2f;
25935ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka
2607ecc1081ab9b4e41e4b2aec7877aaaf8df29e611Tadashi G. Takaoka        /**
2617ecc1081ab9b4e41e4b2aec7877aaaf8df29e611Tadashi G. Takaoka         * The builder of MoreKeysKeyboard.
262a729377395967f7652d93992cbcf50cd2ff522d1Tadashi G. Takaoka         * @param context the context of {@link MoreKeysKeyboardView}.
2637ecc1081ab9b4e41e4b2aec7877aaaf8df29e611Tadashi G. Takaoka         * @param parentKey the {@link Key} that invokes more keys keyboard.
2647ecc1081ab9b4e41e4b2aec7877aaaf8df29e611Tadashi G. Takaoka         * @param parentKeyboardView the {@link KeyboardView} that contains the parentKey.
2650e4f0da449d0fc4f0c4c6b49b4c24961da36a5d1Tadashi G. Takaoka         * @param keyPreviewDrawParams the parameter to place key preview.
2667ecc1081ab9b4e41e4b2aec7877aaaf8df29e611Tadashi G. Takaoka         */
267a729377395967f7652d93992cbcf50cd2ff522d1Tadashi G. Takaoka        public Builder(final Context context, final Key parentKey,
2680e4f0da449d0fc4f0c4c6b49b4c24961da36a5d1Tadashi G. Takaoka                final MainKeyboardView parentKeyboardView,
2690e4f0da449d0fc4f0c4c6b49b4c24961da36a5d1Tadashi G. Takaoka                final KeyPreviewDrawParams keyPreviewDrawParams) {
270a729377395967f7652d93992cbcf50cd2ff522d1Tadashi G. Takaoka            super(context, new MoreKeysKeyboardParams());
2717ecc1081ab9b4e41e4b2aec7877aaaf8df29e611Tadashi G. Takaoka            final Keyboard parentKeyboard = parentKeyboardView.getKeyboard();
2727ecc1081ab9b4e41e4b2aec7877aaaf8df29e611Tadashi G. Takaoka            load(parentKeyboard.mMoreKeysTemplate, parentKeyboard.mId);
27332572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaoka
2742affaf91a04d63e0994102299816014a8bbe11e1Tadashi G. Takaoka            // TODO: More keys keyboard's vertical gap is currently calculated heuristically.
275ea0c567f86bd19015d53fc038c4579df776cfec3Tadashi G. Takaoka            // Should revise the algorithm.
276ea0c567f86bd19015d53fc038c4579df776cfec3Tadashi G. Takaoka            mParams.mVerticalGap = parentKeyboard.mVerticalGap / 2;
27742fd1d2d72c097b2227d4b22f0f824dbb34a4d0cTadashi G. Takaoka            mParentKey = parentKey;
27832572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaoka
2797dc60f9db729e93cb591492574a436418c553ebfTadashi G. Takaoka            final MoreKeySpec[] moreKeys = parentKey.getMoreKeys();
280a0e4f40994f779ad98268921c63d6535ad04224fTadashi G. Takaoka            final int width, height;
281bafe4b8a4eef6c656137e6bb7bce841e98119cafTadashi G. Takaoka            // {@link KeyPreviewDrawParams#mPreviewVisibleWidth} should have been set at
282bafe4b8a4eef6c656137e6bb7bce841e98119cafTadashi G. Takaoka            // {@link MainKeyboardView#showKeyPreview(PointerTracker}, though there may be
283bafe4b8a4eef6c656137e6bb7bce841e98119cafTadashi G. Takaoka            // some chances that the value is zero. <code>width == 0</code> will cause
284bafe4b8a4eef6c656137e6bb7bce841e98119cafTadashi G. Takaoka            // zero-division error at
285bafe4b8a4eef6c656137e6bb7bce841e98119cafTadashi G. Takaoka            // {@link MoreKeysKeyboardParams#setParameters(int,int,int,int,int,int,boolean,int)}.
2867ecc1081ab9b4e41e4b2aec7877aaaf8df29e611Tadashi G. Takaoka            final boolean singleMoreKeyWithPreview = parentKeyboardView.isKeyPreviewPopupEnabled()
2877dc60f9db729e93cb591492574a436418c553ebfTadashi G. Takaoka                    && !parentKey.noKeyPreview() && moreKeys.length == 1
288bafe4b8a4eef6c656137e6bb7bce841e98119cafTadashi G. Takaoka                    && keyPreviewDrawParams.mPreviewVisibleWidth > 0;
28942fd1d2d72c097b2227d4b22f0f824dbb34a4d0cTadashi G. Takaoka            if (singleMoreKeyWithPreview) {
2907ecc1081ab9b4e41e4b2aec7877aaaf8df29e611Tadashi G. Takaoka                // Use pre-computed width and height if this more keys keyboard has only one key to
2917ecc1081ab9b4e41e4b2aec7877aaaf8df29e611Tadashi G. Takaoka                // mitigate visual flicker between key preview and more keys keyboard.
2927ecc1081ab9b4e41e4b2aec7877aaaf8df29e611Tadashi G. Takaoka                // Caveats for the visual assets: To achieve this effect, both the key preview
2937ecc1081ab9b4e41e4b2aec7877aaaf8df29e611Tadashi G. Takaoka                // backgrounds and the more keys keyboard panel background have the exact same
2947ecc1081ab9b4e41e4b2aec7877aaaf8df29e611Tadashi G. Takaoka                // left/right/top paddings. The bottom paddings of both backgrounds don't need to
2957ecc1081ab9b4e41e4b2aec7877aaaf8df29e611Tadashi G. Takaoka                // be considered because the vertical positions of both backgrounds were already
2967ecc1081ab9b4e41e4b2aec7877aaaf8df29e611Tadashi G. Takaoka                // adjusted with their bottom paddings deducted.
2970e4f0da449d0fc4f0c4c6b49b4c24961da36a5d1Tadashi G. Takaoka                width = keyPreviewDrawParams.mPreviewVisibleWidth;
29808ae0d5ca03ed455827e82222df249d1cafb5d71Tadashi G. Takaoka                height = keyPreviewDrawParams.mPreviewVisibleHeight + mParams.mVerticalGap;
299a0e4f40994f779ad98268921c63d6535ad04224fTadashi G. Takaoka            } else {
300b0e76724edcde33dbfa17b56c3f5858705cd06eeTadashi G. Takaoka                final float padding = context.getResources().getDimension(
301b0e76724edcde33dbfa17b56c3f5858705cd06eeTadashi G. Takaoka                        R.dimen.more_keys_keyboard_key_horizontal_padding)
302b0e76724edcde33dbfa17b56c3f5858705cd06eeTadashi G. Takaoka                        + (parentKey.hasLabelsInMoreKeys()
303b0e76724edcde33dbfa17b56c3f5858705cd06eeTadashi G. Takaoka                                ? mParams.mDefaultKeyWidth * LABEL_PADDING_RATIO : 0.0f);
304b0e76724edcde33dbfa17b56c3f5858705cd06eeTadashi G. Takaoka                width = getMaxKeyWidth(parentKey, mParams.mDefaultKeyWidth, padding,
305b0e76724edcde33dbfa17b56c3f5858705cd06eeTadashi G. Takaoka                        parentKeyboardView.newLabelPaint(parentKey));
306a0e4f40994f779ad98268921c63d6535ad04224fTadashi G. Takaoka                height = parentKeyboard.mMostCommonKeyHeight;
307a0e4f40994f779ad98268921c63d6535ad04224fTadashi G. Takaoka            }
3085ef4fccbb90491e1f6c2e87b47ebf9f3659949fbTadashi G. Takaoka            final int dividerWidth;
3095ef4fccbb90491e1f6c2e87b47ebf9f3659949fbTadashi G. Takaoka            if (parentKey.needsDividersInMoreKeys()) {
3105ef4fccbb90491e1f6c2e87b47ebf9f3659949fbTadashi G. Takaoka                mDivider = mResources.getDrawable(R.drawable.more_keys_divider);
3115ef4fccbb90491e1f6c2e87b47ebf9f3659949fbTadashi G. Takaoka                dividerWidth = (int)(width * DIVIDER_RATIO);
3125ef4fccbb90491e1f6c2e87b47ebf9f3659949fbTadashi G. Takaoka            } else {
3135ef4fccbb90491e1f6c2e87b47ebf9f3659949fbTadashi G. Takaoka                mDivider = null;
3145ef4fccbb90491e1f6c2e87b47ebf9f3659949fbTadashi G. Takaoka                dividerWidth = 0;
3155ef4fccbb90491e1f6c2e87b47ebf9f3659949fbTadashi G. Takaoka            }
3167dc60f9db729e93cb591492574a436418c553ebfTadashi G. Takaoka            mParams.setParameters(moreKeys.length, parentKey.getMoreKeysColumn(),
3177dc60f9db729e93cb591492574a436418c553ebfTadashi G. Takaoka                    width, height, parentKey.getX() + parentKey.getWidth() / 2,
318b0e76724edcde33dbfa17b56c3f5858705cd06eeTadashi G. Takaoka                    parentKeyboard.mId.mWidth, parentKey.isFixedColumnOrderMoreKeys(),
3197ecc1081ab9b4e41e4b2aec7877aaaf8df29e611Tadashi G. Takaoka                    dividerWidth);
32032572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaoka        }
32132572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaoka
322b0e76724edcde33dbfa17b56c3f5858705cd06eeTadashi G. Takaoka        private static int getMaxKeyWidth(final Key parentKey, final int minKeyWidth,
323b0e76724edcde33dbfa17b56c3f5858705cd06eeTadashi G. Takaoka                final float padding, final Paint paint) {
3242315bfc7c8df0f6d9fb627456f2a298f5580b52dTadashi G. Takaoka            int maxWidth = minKeyWidth;
3257dc60f9db729e93cb591492574a436418c553ebfTadashi G. Takaoka            for (final MoreKeySpec spec : parentKey.getMoreKeys()) {
326ed3bac91f242850c6d1833a5f8981b9cc208c5ddTadashi G. Takaoka                final String label = spec.mLabel;
327bd7b160cfb05ee543e3cb6ddc7bd231b3f3aba0bTadashi G. Takaoka                // If the label is single letter, minKeyWidth is enough to hold the label.
328cc8c8b99bd0463f5977dea82f5e2379ea1dd4e73Tadashi G. Takaoka                if (label != null && StringUtils.codePointCount(label) > 1) {
32908ae0d5ca03ed455827e82222df249d1cafb5d71Tadashi G. Takaoka                    maxWidth = Math.max(maxWidth,
33008ae0d5ca03ed455827e82222df249d1cafb5d71Tadashi G. Takaoka                            (int)(TypefaceUtils.getLabelWidth(label, paint) + padding));
33132572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaoka                }
33232572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaoka            }
333be34d973349909196dc3427a5653f4e119092ea7Tadashi G. Takaoka            return maxWidth;
33432572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaoka        }
33532572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaoka
33632572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaoka        @Override
3372affaf91a04d63e0994102299816014a8bbe11e1Tadashi G. Takaoka        public MoreKeysKeyboard build() {
3382affaf91a04d63e0994102299816014a8bbe11e1Tadashi G. Takaoka            final MoreKeysKeyboardParams params = mParams;
339ab0d0d8a021a9b0f179281ac9e18604ad331cc43Tadashi G. Takaoka            final int moreKeyFlags = mParentKey.getMoreKeyLabelFlags();
3407dc60f9db729e93cb591492574a436418c553ebfTadashi G. Takaoka            final MoreKeySpec[] moreKeys = mParentKey.getMoreKeys();
34142fd1d2d72c097b2227d4b22f0f824dbb34a4d0cTadashi G. Takaoka            for (int n = 0; n < moreKeys.length; n++) {
342ed3bac91f242850c6d1833a5f8981b9cc208c5ddTadashi G. Takaoka                final MoreKeySpec moreKeySpec = moreKeys[n];
34332572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaoka                final int row = n / params.mNumColumns;
3445ef4fccbb90491e1f6c2e87b47ebf9f3659949fbTadashi G. Takaoka                final int x = params.getX(n, row);
3455ef4fccbb90491e1f6c2e87b47ebf9f3659949fbTadashi G. Takaoka                final int y = params.getY(row);
346ed3bac91f242850c6d1833a5f8981b9cc208c5ddTadashi G. Takaoka                final Key key = new Key(params, moreKeySpec, x, y,
3475ef4fccbb90491e1f6c2e87b47ebf9f3659949fbTadashi G. Takaoka                        params.mDefaultKeyWidth, params.mDefaultRowHeight, moreKeyFlags);
3482fc4248700023853980b0006c12425079e3f9257Tadashi G. Takaoka                params.markAsEdgeKey(key, row);
34932572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaoka                params.onAddKey(key);
3505ef4fccbb90491e1f6c2e87b47ebf9f3659949fbTadashi G. Takaoka
3515ef4fccbb90491e1f6c2e87b47ebf9f3659949fbTadashi G. Takaoka                final int pos = params.getColumnPos(n);
3525ef4fccbb90491e1f6c2e87b47ebf9f3659949fbTadashi G. Takaoka                // The "pos" value represents the offset from the default position. Negative means
3535ef4fccbb90491e1f6c2e87b47ebf9f3659949fbTadashi G. Takaoka                // left of the default position.
3545ef4fccbb90491e1f6c2e87b47ebf9f3659949fbTadashi G. Takaoka                if (params.mDividerWidth > 0 && pos != 0) {
3555ef4fccbb90491e1f6c2e87b47ebf9f3659949fbTadashi G. Takaoka                    final int dividerX = (pos > 0) ? x - params.mDividerWidth
3565ef4fccbb90491e1f6c2e87b47ebf9f3659949fbTadashi G. Takaoka                            : x + params.mDefaultKeyWidth;
3575ef4fccbb90491e1f6c2e87b47ebf9f3659949fbTadashi G. Takaoka                    final Key divider = new MoreKeyDivider(params, mDivider, dividerX, y);
3585ef4fccbb90491e1f6c2e87b47ebf9f3659949fbTadashi G. Takaoka                    params.onAddKey(divider);
3595ef4fccbb90491e1f6c2e87b47ebf9f3659949fbTadashi G. Takaoka                }
36032572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaoka            }
3612affaf91a04d63e0994102299816014a8bbe11e1Tadashi G. Takaoka            return new MoreKeysKeyboard(params);
36232572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaoka        }
36332572948d7e3956efebcbd69d7c7d8403bb659e6Tadashi G. Takaoka    }
36435ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka
36535ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka    private static class MoreKeyDivider extends Key.Spacer {
36635ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka        private final Drawable mIcon;
36735ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka
36835ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka        public MoreKeyDivider(final MoreKeysKeyboardParams params, final Drawable icon,
36935ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka                final int x, final int y) {
37035ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            super(params, x, y, params.mDividerWidth, params.mDefaultRowHeight);
37135ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            mIcon = icon;
37235ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka        }
37335ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka
37435ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka        @Override
37535ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka        public Drawable getIcon(final KeyboardIconsSet iconSet, final int alpha) {
37635ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            // KeyboardIconsSet and alpha are unused. Use the icon that has been passed to the
37735ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            // constructor.
37835ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            // TODO: Drawable itself should have an alpha value.
37935ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            mIcon.setAlpha(128);
38035ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka            return mIcon;
38135ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka        }
38235ff94547c16c84c5b6fafdae0b4a683be782b97Tadashi G. Takaoka    }
38304c96ab966e8a58e5cd401362b49509751ce75d9Tadashi G. Takaoka}
384