From 32572948d7e3956efebcbd69d7c7d8403bb659e6 Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Tue, 23 Aug 2011 12:08:36 +0900 Subject: [PATCH] Refactor and rename popup mini keyoard related classes Change-Id: Ia92ec4612090b03829db9a87ce68d701db6e15bc --- .../inputmethod/keyboard/KeyDetector.java | 4 + .../keyboard/LatinKeyboardBaseView.java | 3 +- .../inputmethod/keyboard/MiniKeyboard.java | 250 ++++++++++++++++- .../keyboard/MiniKeyboardKeyDetector.java | 59 ---- .../inputmethod/keyboard/PointerTracker.java | 4 +- .../keyboard/PopupMiniKeyboardView.java | 52 +++- .../internal/MiniKeyboardBuilder.java | 259 ------------------ .../MiniKeyboardBuilderTests.java | 4 +- 8 files changed, 304 insertions(+), 331 deletions(-) delete mode 100644 java/src/com/android/inputmethod/keyboard/MiniKeyboardKeyDetector.java delete mode 100644 java/src/com/android/inputmethod/keyboard/internal/MiniKeyboardBuilder.java rename tests/src/com/android/inputmethod/keyboard/{internal => }/MiniKeyboardBuilderTests.java (99%) diff --git a/java/src/com/android/inputmethod/keyboard/KeyDetector.java b/java/src/com/android/inputmethod/keyboard/KeyDetector.java index 0a3acb48b..3298c41cf 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyDetector.java +++ b/java/src/com/android/inputmethod/keyboard/KeyDetector.java @@ -91,6 +91,10 @@ public class KeyDetector { mProximityThresholdSquare = threshold * threshold; } + public boolean alwaysAllowsSlidingInput() { + return false; + } + /** * Computes maximum size of the array that can contain all nearby key indices returned by * {@link #getKeyIndexAndNearbyCodes}. diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboardBaseView.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboardBaseView.java index 4b85bcbec..2af4594f4 100644 --- a/java/src/com/android/inputmethod/keyboard/LatinKeyboardBaseView.java +++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboardBaseView.java @@ -38,7 +38,6 @@ import com.android.inputmethod.accessibility.AccessibleKeyboardViewProxy; import com.android.inputmethod.deprecated.VoiceProxy; import com.android.inputmethod.keyboard.PointerTracker.DrawingProxy; import com.android.inputmethod.keyboard.PointerTracker.TimerProxy; -import com.android.inputmethod.keyboard.internal.MiniKeyboardBuilder; import com.android.inputmethod.latin.LatinIME; import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.StaticInnerHandlerWrapper; @@ -374,7 +373,7 @@ public class LatinKeyboardBaseView extends KeyboardView implements PointerTracke final PopupMiniKeyboardView miniKeyboardView = (PopupMiniKeyboardView)container.findViewById(R.id.mini_keyboard_view); final Keyboard parentKeyboard = getKeyboard(); - final Keyboard miniKeyboard = new MiniKeyboardBuilder( + final Keyboard miniKeyboard = new MiniKeyboard.Builder( this, parentKeyboard.mPopupKeyboardResId, parentKey, parentKeyboard).build(); miniKeyboardView.setKeyboard(miniKeyboard); diff --git a/java/src/com/android/inputmethod/keyboard/MiniKeyboard.java b/java/src/com/android/inputmethod/keyboard/MiniKeyboard.java index 08e7d7e19..17c253963 100644 --- a/java/src/com/android/inputmethod/keyboard/MiniKeyboard.java +++ b/java/src/com/android/inputmethod/keyboard/MiniKeyboard.java @@ -16,12 +16,18 @@ package com.android.inputmethod.keyboard; -import com.android.inputmethod.keyboard.internal.MiniKeyboardBuilder.MiniKeyboardParams; +import android.graphics.Paint; +import android.graphics.Rect; + +import com.android.inputmethod.keyboard.internal.KeyboardBuilder; +import com.android.inputmethod.keyboard.internal.KeyboardParams; +import com.android.inputmethod.keyboard.internal.PopupCharactersParser; +import com.android.inputmethod.latin.R; public class MiniKeyboard extends Keyboard { private final int mDefaultKeyCoordX; - public MiniKeyboard(MiniKeyboardParams params) { + private MiniKeyboard(Builder.MiniKeyboardParams params) { super(params); mDefaultKeyCoordX = params.getDefaultKeyCoordX() + params.mDefaultKeyWidth / 2; } @@ -29,4 +35,244 @@ public class MiniKeyboard extends Keyboard { public int getDefaultCoordX() { return mDefaultKeyCoordX; } + + public static class Builder extends KeyboardBuilder { + private final CharSequence[] mPopupCharacters; + + public static class MiniKeyboardParams extends KeyboardParams { + /* package */int mTopRowAdjustment; + public int mNumRows; + public int mNumColumns; + public int mLeftKeys; + public int mRightKeys; // includes default key. + + public MiniKeyboardParams() { + super(); + } + + /* package for test */MiniKeyboardParams(int numKeys, int maxColumns, int keyWidth, + int rowHeight, int coordXInParent, int parentKeyboardWidth) { + super(); + setParameters(numKeys, maxColumns, keyWidth, rowHeight, coordXInParent, + parentKeyboardWidth); + } + + /** + * Set keyboard parameters of mini keyboard. + * + * @param numKeys number of keys in this mini keyboard. + * @param maxColumns number of maximum columns of this mini keyboard. + * @param keyWidth mini keyboard key width in pixel, including horizontal gap. + * @param rowHeight mini keyboard row height in pixel, including vertical gap. + * @param coordXInParent coordinate x of the popup key in parent keyboard. + * @param parentKeyboardWidth parent keyboard width in pixel. + */ + public void setParameters(int numKeys, int maxColumns, int keyWidth, int rowHeight, + int coordXInParent, int parentKeyboardWidth) { + if (parentKeyboardWidth / keyWidth < maxColumns) { + throw new IllegalArgumentException( + "Keyboard is too small to hold mini keyboard: " + parentKeyboardWidth + + " " + keyWidth + " " + maxColumns); + } + mDefaultKeyWidth = keyWidth; + mDefaultRowHeight = rowHeight; + + final int numRows = (numKeys + maxColumns - 1) / maxColumns; + mNumRows = numRows; + final int numColumns = getOptimizedColumns(numKeys, maxColumns); + mNumColumns = numColumns; + + final int numLeftKeys = (numColumns - 1) / 2; + final int numRightKeys = numColumns - numLeftKeys; // including default key. + final int maxLeftKeys = coordXInParent / keyWidth; + final int maxRightKeys = Math.max(1, (parentKeyboardWidth - coordXInParent) + / keyWidth); + int leftKeys, rightKeys; + if (numLeftKeys > maxLeftKeys) { + leftKeys = maxLeftKeys; + rightKeys = numColumns - maxLeftKeys; + } else if (numRightKeys > maxRightKeys) { + leftKeys = numColumns - maxRightKeys; + rightKeys = maxRightKeys; + } else { + leftKeys = numLeftKeys; + rightKeys = numRightKeys; + } + // Shift right if the left edge of mini keyboard is on the edge of parent keyboard + // unless the parent key is on the left edge. + if (leftKeys * keyWidth >= coordXInParent && leftKeys > 0) { + leftKeys--; + rightKeys++; + } + // Shift left if the right edge of mini keyboard is on the edge of parent keyboard + // unless the parent key is on the right edge. + if (rightKeys * keyWidth + coordXInParent >= parentKeyboardWidth && rightKeys > 1) { + leftKeys++; + rightKeys--; + } + mLeftKeys = leftKeys; + mRightKeys = rightKeys; + + // Centering of the top row. + final boolean onEdge = (leftKeys == 0 || rightKeys == 1); + if (numRows < 2 || onEdge || getTopRowEmptySlots(numKeys, numColumns) % 2 == 0) { + mTopRowAdjustment = 0; + } else if (mLeftKeys < mRightKeys - 1) { + mTopRowAdjustment = 1; + } else { + mTopRowAdjustment = -1; + } + + mWidth = mOccupiedWidth = mNumColumns * mDefaultKeyWidth; + mHeight = mOccupiedHeight = mNumRows * mDefaultRowHeight + mVerticalGap; + } + + // Return key position according to column count (0 is default). + /* package */int getColumnPos(int n) { + final int col = n % mNumColumns; + if (col == 0) { + // default position. + return 0; + } + int pos = 0; + int right = 1; // include default position key. + int left = 0; + int i = 0; + while (true) { + // Assign right key if available. + if (right < mRightKeys) { + pos = right; + right++; + i++; + } + if (i >= col) + break; + // Assign left key if available. + if (left < mLeftKeys) { + left++; + pos = -left; + i++; + } + if (i >= col) + break; + } + return pos; + } + + private static int getTopRowEmptySlots(int numKeys, int numColumns) { + final int remainingKeys = numKeys % numColumns; + if (remainingKeys == 0) { + return 0; + } else { + return numColumns - remainingKeys; + } + } + + private int getOptimizedColumns(int numKeys, int maxColumns) { + int numColumns = Math.min(numKeys, maxColumns); + while (getTopRowEmptySlots(numKeys, numColumns) >= mNumRows) { + numColumns--; + } + return numColumns; + } + + public int getDefaultKeyCoordX() { + return mLeftKeys * mDefaultKeyWidth; + } + + public int getX(int n, int row) { + final int x = getColumnPos(n) * mDefaultKeyWidth + getDefaultKeyCoordX(); + if (isTopRow(row)) { + return x + mTopRowAdjustment * (mDefaultKeyWidth / 2); + } + return x; + } + + public int getY(int row) { + return (mNumRows - 1 - row) * mDefaultRowHeight + mTopPadding; + } + + public int getRowFlags(int row) { + int rowFlags = 0; + if (row == 0) + rowFlags |= Keyboard.EDGE_TOP; + if (isTopRow(row)) + rowFlags |= Keyboard.EDGE_BOTTOM; + return rowFlags; + } + + private boolean isTopRow(int rowCount) { + return rowCount == mNumRows - 1; + } + } + + public Builder(KeyboardView view, int xmlId, Key parentKey, Keyboard parentKeyboard) { + super(view.getContext(), new MiniKeyboardParams()); + load(parentKeyboard.mId.cloneWithNewXml(mResources.getResourceEntryName(xmlId), xmlId)); + + // HACK: Current mini keyboard design totally relies on the 9-patch + // padding about horizontal + // and vertical key spacing. To keep the visual of mini keyboard as + // is, these hacks are + // needed to keep having the same horizontal and vertical key + // spacing. + mParams.mHorizontalGap = 0; + mParams.mVerticalGap = mParams.mTopPadding = parentKeyboard.mVerticalGap / 2; + // TODO: When we have correctly padded key background 9-patch + // drawables for mini keyboard, + // revert the above hacks and uncomment the following lines. + // mParams.mHorizontalGap = parentKeyboard.mHorizontalGap; + // mParams.mVerticalGap = parentKeyboard.mVerticalGap; + + mParams.mIsRtlKeyboard = parentKeyboard.mIsRtlKeyboard; + mPopupCharacters = parentKey.mPopupCharacters; + + final int keyWidth = getMaxKeyWidth(view, mPopupCharacters, mParams.mDefaultKeyWidth); + mParams.setParameters(mPopupCharacters.length, parentKey.mMaxPopupColumn, keyWidth, + parentKeyboard.mDefaultRowHeight, parentKey.mX + + (mParams.mDefaultKeyWidth - keyWidth) / 2, view.getMeasuredWidth()); + } + + private static int getMaxKeyWidth(KeyboardView view, CharSequence[] popupCharacters, + int minKeyWidth) { + Paint paint = null; + Rect bounds = null; + int maxWidth = 0; + for (CharSequence popupSpec : popupCharacters) { + final CharSequence label = PopupCharactersParser.getLabel(popupSpec.toString()); + // If the label is single letter, minKeyWidth is enough to hold + // the label. + if (label != null && label.length() > 1) { + if (paint == null) { + paint = new Paint(); + paint.setAntiAlias(true); + } + final int labelSize = view.getDefaultLabelSizeAndSetPaint(paint); + paint.setTextSize(labelSize); + if (bounds == null) + bounds = new Rect(); + paint.getTextBounds(label.toString(), 0, label.length(), bounds); + if (maxWidth < bounds.width()) + maxWidth = bounds.width(); + } + } + final int horizontalPadding = (int) view.getContext().getResources() + .getDimension(R.dimen.mini_keyboard_key_horizontal_padding); + return Math.max(minKeyWidth, maxWidth + horizontalPadding); + } + + @Override + public MiniKeyboard build() { + final MiniKeyboardParams params = mParams; + for (int n = 0; n < mPopupCharacters.length; n++) { + final CharSequence label = mPopupCharacters[n]; + final int row = n / params.mNumColumns; + final Key key = new Key(mResources, params, label, params.getX(n, row), + params.getY(row), params.mDefaultKeyWidth, params.mDefaultRowHeight, + params.getRowFlags(row)); + params.onAddKey(key); + } + return new MiniKeyboard(params); + } + } } diff --git a/java/src/com/android/inputmethod/keyboard/MiniKeyboardKeyDetector.java b/java/src/com/android/inputmethod/keyboard/MiniKeyboardKeyDetector.java deleted file mode 100644 index 84bd44c30..000000000 --- a/java/src/com/android/inputmethod/keyboard/MiniKeyboardKeyDetector.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.android.inputmethod.keyboard; - -import java.util.List; - -public class MiniKeyboardKeyDetector extends KeyDetector { - private final int mSlideAllowanceSquare; - private final int mSlideAllowanceSquareTop; - - public MiniKeyboardKeyDetector(float slideAllowance) { - super(/* keyHysteresisDistance */0); - mSlideAllowanceSquare = (int)(slideAllowance * slideAllowance); - // Top slide allowance is slightly longer (sqrt(2) times) than other edges. - mSlideAllowanceSquareTop = mSlideAllowanceSquare * 2; - } - - @Override - protected int getMaxNearbyKeys() { - // No nearby key will be returned. - return 1; - } - - @Override - public int getKeyIndexAndNearbyCodes(int x, int y, final int[] allCodes) { - final List keys = getKeyboard().mKeys; - final int touchX = getTouchX(x); - final int touchY = getTouchY(y); - - int nearestIndex = NOT_A_KEY; - int nearestDist = (y < 0) ? mSlideAllowanceSquareTop : mSlideAllowanceSquare; - final int keyCount = keys.size(); - for (int index = 0; index < keyCount; index++) { - final int dist = keys.get(index).squaredDistanceToEdge(touchX, touchY); - if (dist < nearestDist) { - nearestIndex = index; - nearestDist = dist; - } - } - - if (allCodes != null && nearestIndex != NOT_A_KEY) - allCodes[0] = keys.get(nearestIndex).mCode; - return nearestIndex; - } -} diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java index 1f8119a0f..d33cb442b 100644 --- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java +++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java @@ -438,9 +438,9 @@ public class PointerTracker { private void onDownEventInternal(int x, int y, long eventTime) { int keyIndex = onDownKey(x, y, eventTime); // Sliding key is allowed when 1) enabled by configuration, 2) this pointer starts sliding - // from modifier key, or 3) this pointer is on mini-keyboard. + // from modifier key, or 3) this pointer's KeyDetector always allows sliding input. mIsAllowedSlidingKeyInput = sConfigSlidingKeyInputEnabled || isModifierInternal(keyIndex) - || mKeyDetector instanceof MiniKeyboardKeyDetector; + || mKeyDetector.alwaysAllowsSlidingInput(); mKeyboardLayoutHasBeenChanged = false; mKeyAlreadyProcessed = false; mIsRepeatableKey = false; diff --git a/java/src/com/android/inputmethod/keyboard/PopupMiniKeyboardView.java b/java/src/com/android/inputmethod/keyboard/PopupMiniKeyboardView.java index fb932e3e8..1230dfb44 100644 --- a/java/src/com/android/inputmethod/keyboard/PopupMiniKeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/PopupMiniKeyboardView.java @@ -28,6 +28,8 @@ import com.android.inputmethod.keyboard.PointerTracker.DrawingProxy; import com.android.inputmethod.keyboard.PointerTracker.TimerProxy; import com.android.inputmethod.latin.R; +import java.util.List; + /** * A view that renders a virtual {@link MiniKeyboard}. It handles rendering of keys and detecting * key presses and touch movements. @@ -43,6 +45,51 @@ public class PopupMiniKeyboardView extends KeyboardView implements PopupPanel { private int mOriginX; private int mOriginY; + private static class MiniKeyboardKeyDetector extends KeyDetector { + private final int mSlideAllowanceSquare; + private final int mSlideAllowanceSquareTop; + + public MiniKeyboardKeyDetector(float slideAllowance) { + super(/* keyHysteresisDistance */0); + mSlideAllowanceSquare = (int)(slideAllowance * slideAllowance); + // Top slide allowance is slightly longer (sqrt(2) times) than other edges. + mSlideAllowanceSquareTop = mSlideAllowanceSquare * 2; + } + + @Override + public boolean alwaysAllowsSlidingInput() { + return true; + } + + @Override + protected int getMaxNearbyKeys() { + // No nearby key will be returned. + return 1; + } + + @Override + public int getKeyIndexAndNearbyCodes(int x, int y, final int[] allCodes) { + final List keys = getKeyboard().mKeys; + final int touchX = getTouchX(x); + final int touchY = getTouchY(y); + + int nearestIndex = NOT_A_KEY; + int nearestDist = (y < 0) ? mSlideAllowanceSquareTop : mSlideAllowanceSquare; + final int keyCount = keys.size(); + for (int index = 0; index < keyCount; index++) { + final int dist = keys.get(index).squaredDistanceToEdge(touchX, touchY); + if (dist < nearestDist) { + nearestIndex = index; + nearestDist = dist; + } + } + + if (allCodes != null && nearestIndex != NOT_A_KEY) + allCodes[0] = keys.get(nearestIndex).mCode; + return nearestIndex; + } + } + private static final TimerProxy EMPTY_TIMER_PROXY = new TimerProxy() { @Override public void startKeyRepeatTimer(long delay, int keyIndex, PointerTracker tracker) {} @@ -145,11 +192,6 @@ public class PopupMiniKeyboardView extends KeyboardView implements PopupPanel { return EMPTY_TIMER_PROXY; } - @Override - protected void onSizeChanged(int w, int h, int oldw, int oldh) { - // Do nothing for the mini keyboard. - } - @Override public void setKeyPreviewPopupEnabled(boolean previewEnabled, int delay) { // Mini keyboard needs no pop-up key preview displayed, so we pass always false with a diff --git a/java/src/com/android/inputmethod/keyboard/internal/MiniKeyboardBuilder.java b/java/src/com/android/inputmethod/keyboard/internal/MiniKeyboardBuilder.java deleted file mode 100644 index 31a291cef..000000000 --- a/java/src/com/android/inputmethod/keyboard/internal/MiniKeyboardBuilder.java +++ /dev/null @@ -1,259 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.android.inputmethod.keyboard.internal; - -import android.graphics.Paint; -import android.graphics.Rect; - -import com.android.inputmethod.keyboard.Key; -import com.android.inputmethod.keyboard.Keyboard; -import com.android.inputmethod.keyboard.KeyboardView; -import com.android.inputmethod.keyboard.MiniKeyboard; -import com.android.inputmethod.latin.R; - -public class MiniKeyboardBuilder extends - KeyboardBuilder { - private final CharSequence[] mPopupCharacters; - - public static class MiniKeyboardParams extends KeyboardParams { - /* package */ int mTopRowAdjustment; - public int mNumRows; - public int mNumColumns; - public int mLeftKeys; - public int mRightKeys; // includes default key. - - public MiniKeyboardParams() { - super(); - } - - /* package for test */ MiniKeyboardParams(int numKeys, int maxColumns, int keyWidth, - int rowHeight, int coordXInParent, int parentKeyboardWidth) { - super(); - setParameters( - numKeys, maxColumns, keyWidth, rowHeight, coordXInParent, parentKeyboardWidth); - } - - /** - * Set keyboard parameters of mini keyboard. - * - * @param numKeys number of keys in this mini keyboard. - * @param maxColumns number of maximum columns of this mini keyboard. - * @param keyWidth mini keyboard key width in pixel, including horizontal gap. - * @param rowHeight mini keyboard row height in pixel, including vertical gap. - * @param coordXInParent coordinate x of the popup key in parent keyboard. - * @param parentKeyboardWidth parent keyboard width in pixel. - */ - public void setParameters(int numKeys, int maxColumns, int keyWidth, int rowHeight, - int coordXInParent, int parentKeyboardWidth) { - if (parentKeyboardWidth / keyWidth < maxColumns) { - throw new IllegalArgumentException("Keyboard is too small to hold mini keyboard: " - + parentKeyboardWidth + " " + keyWidth + " " + maxColumns); - } - mDefaultKeyWidth = keyWidth; - mDefaultRowHeight = rowHeight; - - final int numRows = (numKeys + maxColumns - 1) / maxColumns; - mNumRows = numRows; - final int numColumns = getOptimizedColumns(numKeys, maxColumns); - mNumColumns = numColumns; - - final int numLeftKeys = (numColumns - 1) / 2; - final int numRightKeys = numColumns - numLeftKeys; // including default key. - final int maxLeftKeys = coordXInParent / keyWidth; - final int maxRightKeys = Math.max(1, (parentKeyboardWidth - coordXInParent) / keyWidth); - int leftKeys, rightKeys; - if (numLeftKeys > maxLeftKeys) { - leftKeys = maxLeftKeys; - rightKeys = numColumns - maxLeftKeys; - } else if (numRightKeys > maxRightKeys) { - leftKeys = numColumns - maxRightKeys; - rightKeys = maxRightKeys; - } else { - leftKeys = numLeftKeys; - rightKeys = numRightKeys; - } - // Shift right if the left edge of mini keyboard is on the edge of parent keyboard - // unless the parent key is on the left edge. - if (leftKeys * keyWidth >= coordXInParent && leftKeys > 0) { - leftKeys--; - rightKeys++; - } - // Shift left if the right edge of mini keyboard is on the edge of parent keyboard - // unless the parent key is on the right edge. - if (rightKeys * keyWidth + coordXInParent >= parentKeyboardWidth && rightKeys > 1) { - leftKeys++; - rightKeys--; - } - mLeftKeys = leftKeys; - mRightKeys = rightKeys; - - // Centering of the top row. - final boolean onEdge = (leftKeys == 0 || rightKeys == 1); - if (numRows < 2 || onEdge || getTopRowEmptySlots(numKeys, numColumns) % 2 == 0) { - mTopRowAdjustment = 0; - } else if (mLeftKeys < mRightKeys - 1) { - mTopRowAdjustment = 1; - } else { - mTopRowAdjustment = -1; - } - - mWidth = mOccupiedWidth = mNumColumns * mDefaultKeyWidth; - mHeight = mOccupiedHeight = mNumRows * mDefaultRowHeight + mVerticalGap; - } - - // Return key position according to column count (0 is default). - /* package */ int getColumnPos(int n) { - final int col = n % mNumColumns; - if (col == 0) { - // default position. - return 0; - } - int pos = 0; - int right = 1; // include default position key. - int left = 0; - int i = 0; - while (true) { - // Assign right key if available. - if (right < mRightKeys) { - pos = right; - right++; - i++; - } - if (i >= col) - break; - // Assign left key if available. - if (left < mLeftKeys) { - left++; - pos = -left; - i++; - } - if (i >= col) - break; - } - return pos; - } - - private static int getTopRowEmptySlots(int numKeys, int numColumns) { - final int remainingKeys = numKeys % numColumns; - if (remainingKeys == 0) { - return 0; - } else { - return numColumns - remainingKeys; - } - } - - private int getOptimizedColumns(int numKeys, int maxColumns) { - int numColumns = Math.min(numKeys, maxColumns); - while (getTopRowEmptySlots(numKeys, numColumns) >= mNumRows) { - numColumns--; - } - return numColumns; - } - - public int getDefaultKeyCoordX() { - return mLeftKeys * mDefaultKeyWidth; - } - - public int getX(int n, int row) { - final int x = getColumnPos(n) * mDefaultKeyWidth + getDefaultKeyCoordX(); - if (isTopRow(row)) { - return x + mTopRowAdjustment * (mDefaultKeyWidth / 2); - } - return x; - } - - public int getY(int row) { - return (mNumRows - 1 - row) * mDefaultRowHeight + mTopPadding; - } - - public int getRowFlags(int row) { - int rowFlags = 0; - if (row == 0) rowFlags |= Keyboard.EDGE_TOP; - if (isTopRow(row)) rowFlags |= Keyboard.EDGE_BOTTOM; - return rowFlags; - } - - private boolean isTopRow(int rowCount) { - return rowCount == mNumRows - 1; - } - } - - public MiniKeyboardBuilder(KeyboardView view, int xmlId, Key parentKey, - Keyboard parentKeyboard) { - super(view.getContext(), new MiniKeyboardParams()); - load(parentKeyboard.mId.cloneWithNewXml(mResources.getResourceEntryName(xmlId), xmlId)); - - // HACK: Current mini keyboard design totally relies on the 9-patch padding about horizontal - // and vertical key spacing. To keep the visual of mini keyboard as is, these hacks are - // needed to keep having the same horizontal and vertical key spacing. - mParams.mHorizontalGap = 0; - mParams.mVerticalGap = mParams.mTopPadding = parentKeyboard.mVerticalGap / 2; - // TODO: When we have correctly padded key background 9-patch drawables for mini keyboard, - // revert the above hacks and uncomment the following lines. - //mParams.mHorizontalGap = parentKeyboard.mHorizontalGap; - //mParams.mVerticalGap = parentKeyboard.mVerticalGap; - - mParams.mIsRtlKeyboard = parentKeyboard.mIsRtlKeyboard; - mPopupCharacters = parentKey.mPopupCharacters; - - final int keyWidth = getMaxKeyWidth(view, mPopupCharacters, mParams.mDefaultKeyWidth); - mParams.setParameters( - mPopupCharacters.length, parentKey.mMaxPopupColumn, - keyWidth, parentKeyboard.mDefaultRowHeight, - parentKey.mX + (mParams.mDefaultKeyWidth - keyWidth) / 2, - view.getMeasuredWidth()); - } - - private static int getMaxKeyWidth(KeyboardView view, CharSequence[] popupCharacters, - int minKeyWidth) { - Paint paint = null; - Rect bounds = null; - int maxWidth = 0; - for (CharSequence popupSpec : popupCharacters) { - final CharSequence label = PopupCharactersParser.getLabel(popupSpec.toString()); - // If the label is single letter, minKeyWidth is enough to hold the label. - if (label != null && label.length() > 1) { - if (paint == null) { - paint = new Paint(); - paint.setAntiAlias(true); - } - final int labelSize = view.getDefaultLabelSizeAndSetPaint(paint); - paint.setTextSize(labelSize); - if (bounds == null) bounds = new Rect(); - paint.getTextBounds(label.toString(), 0, label.length(), bounds); - if (maxWidth < bounds.width()) - maxWidth = bounds.width(); - } - } - final int horizontalPadding = (int)view.getContext().getResources().getDimension( - R.dimen.mini_keyboard_key_horizontal_padding); - return Math.max(minKeyWidth, maxWidth + horizontalPadding); - } - - @Override - public MiniKeyboard build() { - final MiniKeyboardParams params = mParams; - for (int n = 0; n < mPopupCharacters.length; n++) { - final CharSequence label = mPopupCharacters[n]; - final int row = n / params.mNumColumns; - final Key key = new Key(mResources, params, label, params.getX(n, row), params.getY(row), - params.mDefaultKeyWidth, params.mDefaultRowHeight, params.getRowFlags(row)); - params.onAddKey(key); - } - return new MiniKeyboard(params); - } -} diff --git a/tests/src/com/android/inputmethod/keyboard/internal/MiniKeyboardBuilderTests.java b/tests/src/com/android/inputmethod/keyboard/MiniKeyboardBuilderTests.java similarity index 99% rename from tests/src/com/android/inputmethod/keyboard/internal/MiniKeyboardBuilderTests.java rename to tests/src/com/android/inputmethod/keyboard/MiniKeyboardBuilderTests.java index 1c5661bf0..a143bbad5 100644 --- a/tests/src/com/android/inputmethod/keyboard/internal/MiniKeyboardBuilderTests.java +++ b/tests/src/com/android/inputmethod/keyboard/MiniKeyboardBuilderTests.java @@ -14,9 +14,9 @@ * the License. */ -package com.android.inputmethod.keyboard.internal; +package com.android.inputmethod.keyboard; -import com.android.inputmethod.keyboard.internal.MiniKeyboardBuilder.MiniKeyboardParams; +import com.android.inputmethod.keyboard.MiniKeyboard.Builder.MiniKeyboardParams; import android.test.AndroidTestCase;