Refactor more keys spec handling

Change-Id: Ibd95eff0725724ea35ad58e1d1ec7ec3d02a6e90
main
Tadashi G. Takaoka 2012-03-01 13:09:39 +09:00
parent 36aa8e39b5
commit 42fd1d2d72
5 changed files with 78 additions and 56 deletions

View File

@ -103,11 +103,12 @@ public class Key {
public final CharSequence mOutputText; public final CharSequence mOutputText;
/** More keys */ /** More keys */
public final String[] mMoreKeys; public final String[] mMoreKeys;
/** More keys maximum column number */ /** More keys column number and flags */
public final int mMaxMoreKeysColumn; private final int mMoreKeysColumnAndFlags;
public static final int MORE_KEYS_FIXED_COLUMN_ORDER = 0x80000000; private static final int MORE_KEYS_COLUMN_MASK = 0x000000ff;
private static final String AUTO_COLUMN_ORDER = "!autoColumnOrder!"; private static final int MORE_KEYS_FLAGS_FIXED_COLUMN_ORDER = 0x80000000;
private static final String FIXED_COLUMN_ORDER = "!fixedColumnOrder!"; private static final String MORE_KEYS_AUTO_COLUMN_ORDER = "!autoColumnOrder!";
private static final String MORE_KEYS_FIXED_COLUMN_ORDER = "!fixedColumnOrder!";
/** Background type that represents different key background visual than normal one. */ /** Background type that represents different key background visual than normal one. */
public final int mBackgroundType; public final int mBackgroundType;
@ -146,7 +147,7 @@ public class Key {
* This constructor is being used only for key in popup suggestions pane. * This constructor is being used only for key in popup suggestions pane.
*/ */
public Key(Keyboard.Params params, String label, String hintLabel, int iconId, public Key(Keyboard.Params params, String label, String hintLabel, int iconId,
int code, CharSequence outputText, int x, int y, int width, int height) { int code, String outputText, int x, int y, int width, int height) {
mHeight = height - params.mVerticalGap; mHeight = height - params.mVerticalGap;
mHorizontalGap = params.mHorizontalGap; mHorizontalGap = params.mHorizontalGap;
mVerticalGap = params.mVerticalGap; mVerticalGap = params.mVerticalGap;
@ -157,7 +158,7 @@ public class Key {
mBackgroundType = BACKGROUND_TYPE_NORMAL; mBackgroundType = BACKGROUND_TYPE_NORMAL;
mActionFlags = 0; mActionFlags = 0;
mMoreKeys = null; mMoreKeys = null;
mMaxMoreKeysColumn = 0; mMoreKeysColumnAndFlags = 0;
mLabel = label; mLabel = label;
mOutputText = outputText; mOutputText = outputText;
mCode = code; mCode = code;
@ -236,15 +237,18 @@ public class Key {
final boolean preserveCase = (mLabelFlags & LABEL_FLAGS_PRESERVE_CASE) != 0; final boolean preserveCase = (mLabelFlags & LABEL_FLAGS_PRESERVE_CASE) != 0;
int actionFlags = style.getFlag(keyAttr, R.styleable.Keyboard_Key_keyActionFlags); int actionFlags = style.getFlag(keyAttr, R.styleable.Keyboard_Key_keyActionFlags);
String[] moreKeys = style.getStringArray(keyAttr, R.styleable.Keyboard_Key_moreKeys); String[] moreKeys = style.getStringArray(keyAttr, R.styleable.Keyboard_Key_moreKeys);
int column;
if ((column = parseMoreKeysColumnOrder(moreKeys, AUTO_COLUMN_ORDER)) > 0) { int moreKeysColumn = style.getInt(keyAttr,
mMaxMoreKeysColumn = column;
} else if ((column = parseMoreKeysColumnOrder(moreKeys, FIXED_COLUMN_ORDER)) > 0) {
mMaxMoreKeysColumn = column | MORE_KEYS_FIXED_COLUMN_ORDER;
} else {
mMaxMoreKeysColumn = style.getInt(keyAttr,
R.styleable.Keyboard_Key_maxMoreKeysColumn, params.mMaxMoreKeysKeyboardColumn); R.styleable.Keyboard_Key_maxMoreKeysColumn, params.mMaxMoreKeysKeyboardColumn);
int value;
if ((value = KeySpecParser.getIntValue(moreKeys, MORE_KEYS_AUTO_COLUMN_ORDER, -1)) > 0) {
moreKeysColumn = value & MORE_KEYS_COLUMN_MASK;
} }
if ((value = KeySpecParser.getIntValue(moreKeys, MORE_KEYS_FIXED_COLUMN_ORDER, -1)) > 0) {
moreKeysColumn = MORE_KEYS_FLAGS_FIXED_COLUMN_ORDER | (value & MORE_KEYS_COLUMN_MASK);
}
mMoreKeysColumnAndFlags = moreKeysColumn;
final String[] additionalMoreKeys = style.getStringArray( final String[] additionalMoreKeys = style.getStringArray(
keyAttr, R.styleable.Keyboard_Key_additionalMoreKeys); keyAttr, R.styleable.Keyboard_Key_additionalMoreKeys);
moreKeys = KeySpecParser.insertAddtionalMoreKeys(moreKeys, additionalMoreKeys); moreKeys = KeySpecParser.insertAddtionalMoreKeys(moreKeys, additionalMoreKeys);
@ -311,21 +315,6 @@ public class Key {
} }
} }
private static int parseMoreKeysColumnOrder(String[] moreKeys, String key) {
if (moreKeys == null || moreKeys.length == 0 || moreKeys[0] == null
|| !moreKeys[0].startsWith(key)) {
return -1;
}
try {
final int column = Integer.parseInt(moreKeys[0].substring(key.length()));
moreKeys[0] = null;
return column;
} catch (NumberFormatException e) {
Log.w(TAG, "column number should follow after " + key);
return 0;
}
}
private static int adjustCaseOfCodeForKeyboardId(int code, boolean preserveCase, private static int adjustCaseOfCodeForKeyboardId(int code, boolean preserveCase,
KeyboardId id) { KeyboardId id) {
if (!Keyboard.isLetterCode(code) || preserveCase) return code; if (!Keyboard.isLetterCode(code) || preserveCase) return code;
@ -532,6 +521,14 @@ public class Key {
return (mLabelFlags & LABEL_FLAGS_SHIFTED_LETTER_ACTIVATED) != 0; return (mLabelFlags & LABEL_FLAGS_SHIFTED_LETTER_ACTIVATED) != 0;
} }
public int getMoreKeysColumn() {
return mMoreKeysColumnAndFlags & MORE_KEYS_COLUMN_MASK;
}
public boolean isFixedColumnOrderMoreKeys() {
return (mMoreKeysColumnAndFlags & MORE_KEYS_FLAGS_FIXED_COLUMN_ORDER) != 0;
}
public Drawable getIcon(KeyboardIconsSet iconSet) { public Drawable getIcon(KeyboardIconsSet iconSet) {
return iconSet.getIconDrawable(mIconId); return iconSet.getIconDrawable(mIconId);
} }

View File

@ -34,7 +34,7 @@ public class MoreKeysKeyboard extends Keyboard {
} }
public static class Builder extends Keyboard.Builder<Builder.MoreKeysKeyboardParams> { public static class Builder extends Keyboard.Builder<Builder.MoreKeysKeyboardParams> {
private final String[] mMoreKeys; private final Key mParentKey;
public static class MoreKeysKeyboardParams extends Keyboard.Params { public static class MoreKeysKeyboardParams extends Keyboard.Params {
public boolean mIsFixedOrder; public boolean mIsFixedOrder;
@ -49,28 +49,20 @@ public class MoreKeysKeyboard extends Keyboard {
super(); super();
} }
/* package for test */MoreKeysKeyboardParams(int numKeys, int maxColumns, int keyWidth,
int rowHeight, int coordXInParent, int parentKeyboardWidth) {
super();
setParameters(numKeys, maxColumns, keyWidth, rowHeight, coordXInParent,
parentKeyboardWidth);
}
/** /**
* Set keyboard parameters of more keys keyboard. * Set keyboard parameters of more keys keyboard.
* *
* @param numKeys number of keys in this more keys keyboard. * @param numKeys number of keys in this more keys keyboard.
* @param maxColumnsAndFlags number of maximum columns of this more keys keyboard. * @param maxColumns number of maximum columns of this more keys keyboard.
* This might have {@link Key#MORE_KEYS_FIXED_COLUMN_ORDER} flag.
* @param keyWidth more keys keyboard key width in pixel, including horizontal gap. * @param keyWidth more keys keyboard key width in pixel, including horizontal gap.
* @param rowHeight more keys keyboard row height in pixel, including vertical gap. * @param rowHeight more keys keyboard row height in pixel, including vertical gap.
* @param coordXInParent coordinate x of the key preview in parent keyboard. * @param coordXInParent coordinate x of the key preview in parent keyboard.
* @param parentKeyboardWidth parent keyboard width in pixel. * @param parentKeyboardWidth parent keyboard width in pixel.
* @param isFixedColumnOrder if true, more keys should be laid out in fixed order.
*/ */
public void setParameters(int numKeys, int maxColumnsAndFlags, int keyWidth, public void setParameters(int numKeys, int maxColumns, int keyWidth, int rowHeight,
int rowHeight, int coordXInParent, int parentKeyboardWidth) { int coordXInParent, int parentKeyboardWidth, boolean isFixedColumnOrder) {
mIsFixedOrder = (maxColumnsAndFlags & Key.MORE_KEYS_FIXED_COLUMN_ORDER) != 0; mIsFixedOrder = isFixedColumnOrder;
final int maxColumns = maxColumnsAndFlags & ~Key.MORE_KEYS_FIXED_COLUMN_ORDER;
if (parentKeyboardWidth / keyWidth < maxColumns) { if (parentKeyboardWidth / keyWidth < maxColumns) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"Keyboard is too small to hold more keys keyboard: " "Keyboard is too small to hold more keys keyboard: "
@ -253,7 +245,7 @@ public class MoreKeysKeyboard extends Keyboard {
// TODO: More keys keyboard's vertical gap is currently calculated heuristically. // TODO: More keys keyboard's vertical gap is currently calculated heuristically.
// Should revise the algorithm. // Should revise the algorithm.
mParams.mVerticalGap = parentKeyboard.mVerticalGap / 2; mParams.mVerticalGap = parentKeyboard.mVerticalGap / 2;
mMoreKeys = parentKey.mMoreKeys; mParentKey = parentKey;
final int previewWidth = view.mKeyPreviewDrawParams.mPreviewBackgroundWidth; final int previewWidth = view.mKeyPreviewDrawParams.mPreviewBackgroundWidth;
final int previewHeight = view.mKeyPreviewDrawParams.mPreviewBackgroundHeight; final int previewHeight = view.mKeyPreviewDrawParams.mPreviewBackgroundHeight;
@ -261,20 +253,24 @@ public class MoreKeysKeyboard extends Keyboard {
// Use pre-computed width and height if these values are available and more keys // Use pre-computed width and height if these values are available and more keys
// keyboard has only one key to mitigate visual flicker between key preview and more // keyboard has only one key to mitigate visual flicker between key preview and more
// keys keyboard. // keys keyboard.
if (view.isKeyPreviewPopupEnabled() && mMoreKeys.length == 1 && previewWidth > 0 final boolean validKeyPreview = view.isKeyPreviewPopupEnabled() && (previewWidth > 0)
&& previewHeight > 0) { && (previewHeight > 0);
final boolean singleMoreKeyWithPreview = validKeyPreview
&& parentKey.mMoreKeys.length == 1;
if (singleMoreKeyWithPreview) {
width = previewWidth; width = previewWidth;
height = previewHeight + mParams.mVerticalGap; height = previewHeight + mParams.mVerticalGap;
} else { } else {
width = getMaxKeyWidth(view, parentKey.mMoreKeys, mParams.mDefaultKeyWidth); width = getMaxKeyWidth(view, parentKey.mMoreKeys, mParams.mDefaultKeyWidth);
height = parentKeyboard.mMostCommonKeyHeight; height = parentKeyboard.mMostCommonKeyHeight;
} }
mParams.setParameters(mMoreKeys.length, parentKey.mMaxMoreKeysColumn, width, height, mParams.setParameters(parentKey.mMoreKeys.length, parentKey.getMoreKeysColumn(),
parentKey.mX + parentKey.mWidth / 2, view.getMeasuredWidth()); width, height, parentKey.mX + parentKey.mWidth / 2, view.getMeasuredWidth(),
parentKey.isFixedColumnOrderMoreKeys());
} }
private static int getMaxKeyWidth(KeyboardView view, String[] moreKeys, int minKeyWidth) { private static int getMaxKeyWidth(KeyboardView view, String[] moreKeys, int minKeyWidth) {
final int padding = (int) view.getContext().getResources() final int padding = (int) view.getResources()
.getDimension(R.dimen.more_keys_keyboard_key_horizontal_padding); .getDimension(R.dimen.more_keys_keyboard_key_horizontal_padding);
Paint paint = null; Paint paint = null;
int maxWidth = minKeyWidth; int maxWidth = minKeyWidth;
@ -298,8 +294,9 @@ public class MoreKeysKeyboard extends Keyboard {
@Override @Override
public MoreKeysKeyboard build() { public MoreKeysKeyboard build() {
final MoreKeysKeyboardParams params = mParams; final MoreKeysKeyboardParams params = mParams;
for (int n = 0; n < mMoreKeys.length; n++) { final String[] moreKeys = mParentKey.mMoreKeys;
final String moreKeySpec = mMoreKeys[n]; for (int n = 0; n < moreKeys.length; n++) {
final String moreKeySpec = moreKeys[n];
final int row = n / params.mNumColumns; final int row = n / params.mNumColumns;
final Key key = new Key(mResources, params, moreKeySpec, params.getX(n, row), final Key key = new Key(mResources, params, moreKeySpec, params.getX(n, row),
params.getY(row), params.mDefaultKeyWidth, params.mDefaultRowHeight); params.getY(row), params.mDefaultKeyWidth, params.mDefaultRowHeight);

View File

@ -426,4 +426,28 @@ public class KeySpecParser {
return list.toArray(new String[list.size()]); return list.toArray(new String[list.size()]);
} }
} }
public static int getIntValue(String[] moreKeys, String key, int defaultValue) {
if (moreKeys == null) {
return defaultValue;
}
boolean foundValue = false;
int value = defaultValue;
for (int i = 0; i < moreKeys.length; i++) {
final String moreKeySpec = moreKeys[i];
if (moreKeySpec == null || !moreKeySpec.startsWith(key)) {
continue;
}
moreKeys[i] = null;
try {
if (!foundValue) {
value = Integer.parseInt(moreKeySpec.substring(key.length()));
}
} catch (NumberFormatException e) {
throw new RuntimeException(
"integer should follow after " + key + ": " + moreKeySpec);
}
}
return value;
}
} }

View File

@ -41,10 +41,12 @@ public class MoreKeysKeyboardBuilderFixedOrderTests extends AndroidTestCase {
super.setUp(); super.setUp();
} }
private static MoreKeysKeyboardParams createParams(int numKeys, int fixColumns, private static MoreKeysKeyboardParams createParams(int numKeys, int columnNum,
int coordXInParnet) { int coordXInParnet) {
return new MoreKeysKeyboardParams(numKeys, fixColumns | Key.MORE_KEYS_FIXED_COLUMN_ORDER, final MoreKeysKeyboardParams params = new MoreKeysKeyboardParams();
WIDTH, HEIGHT, coordXInParnet, KEYBOARD_WIDTH); params.setParameters(numKeys, columnNum, WIDTH, HEIGHT, coordXInParnet, KEYBOARD_WIDTH,
/* isFixedOrderColumn */true);
return params;
} }
public void testLayoutError() { public void testLayoutError() {

View File

@ -43,8 +43,10 @@ public class MoreKeysKeyboardBuilderTests extends AndroidTestCase {
private static MoreKeysKeyboardParams createParams(int numKeys, int maxColumns, private static MoreKeysKeyboardParams createParams(int numKeys, int maxColumns,
int coordXInParnet) { int coordXInParnet) {
return new MoreKeysKeyboardParams(numKeys, maxColumns, WIDTH, HEIGHT, coordXInParnet, final MoreKeysKeyboardParams params = new MoreKeysKeyboardParams();
KEYBOARD_WIDTH); params.setParameters(numKeys, maxColumns, WIDTH, HEIGHT, coordXInParnet, KEYBOARD_WIDTH,
/* isFixedOrderColumn */false);
return params;
} }
public void testLayoutError() { public void testLayoutError() {