Optimize rare Key attributes to separate class

This change also removes per-Key verticalGap and horizontalGap.

Change-Id: Id4d2129022fbbfbf5d740b8d1257032c945bb775
main
Tadashi G. Takaoka 2012-08-28 17:19:49 +09:00
parent 61bc66b324
commit 29d5973fd3
7 changed files with 112 additions and 69 deletions

View File

@ -55,7 +55,6 @@ public class Key {
* The key code (unicode or custom code) that this key generates.
*/
public final int mCode;
public final int mAltCode;
/** Label to display */
public final String mLabel;
@ -90,22 +89,11 @@ public class Key {
/** Icon to display instead of a label. Icon takes precedence over a label */
private final int mIconId;
/** Icon for disabled state */
private final int mDisabledIconId;
/** Preview version of the icon, for the preview popup */
private final int mPreviewIconId;
/** Width of the key, not including the gap */
public final int mWidth;
/** Height of the key, not including the gap */
public final int mHeight;
/** The horizontal gap around this key */
public final int mHorizontalGap;
/** The vertical gap below this key */
public final int mVerticalGap;
/** The visual insets */
public final int mVisualInsetsLeft;
public final int mVisualInsetsRight;
/** X coordinate of the key in the keyboard layout */
public final int mX;
/** Y coordinate of the key in the keyboard layout */
@ -113,8 +101,6 @@ public class Key {
/** Hit bounding box of the key */
public final Rect mHitBox = new Rect();
/** Text to output when pressed. This can be multiple characters, like ".com" */
public final CharSequence mOutputText;
/** More keys */
public final MoreKeySpec[] mMoreKeys;
/** More keys column number and flags */
@ -144,6 +130,32 @@ public class Key {
private static final int ACTION_FLAGS_ALT_CODE_WHILE_TYPING = 0x04;
private static final int ACTION_FLAGS_ENABLE_LONG_PRESS = 0x08;
private final OptionalAttributes mOptionalAttributes;
private static class OptionalAttributes {
/** Text to output when pressed. This can be multiple characters, like ".com" */
public final String mOutputText;
public final int mAltCode;
/** Icon for disabled state */
public final int mDisabledIconId;
/** Preview version of the icon, for the preview popup */
public final int mPreviewIconId;
/** The visual insets */
public final int mVisualInsetsLeft;
public final int mVisualInsetsRight;
public OptionalAttributes(final String outputText, final int altCode,
final int disabledIconId, final int previewIconId,
final int visualInsetsLeft, final int visualInsetsRight) {
mOutputText = outputText;
mAltCode = altCode;
mDisabledIconId = disabledIconId;
mPreviewIconId = previewIconId;
mVisualInsetsLeft = visualInsetsLeft;
mVisualInsetsRight = visualInsetsRight;
}
}
private final int mHashCode;
/** The current pressed state of this key */
@ -166,10 +178,7 @@ public class Key {
public Key(Keyboard.Params params, String label, String hintLabel, int iconId,
int code, String outputText, int x, int y, int width, int height, int labelFlags) {
mHeight = height - params.mVerticalGap;
mHorizontalGap = params.mHorizontalGap;
mVerticalGap = params.mVerticalGap;
mVisualInsetsLeft = mVisualInsetsRight = 0;
mWidth = width - mHorizontalGap;
mWidth = width - params.mHorizontalGap;
mHintLabel = hintLabel;
mLabelFlags = labelFlags;
mBackgroundType = BACKGROUND_TYPE_NORMAL;
@ -177,15 +186,17 @@ public class Key {
mMoreKeys = null;
mMoreKeysColumnAndFlags = 0;
mLabel = label;
mOutputText = outputText;
if (outputText == null) {
mOptionalAttributes = null;
} else {
mOptionalAttributes = new OptionalAttributes(outputText, CODE_UNSPECIFIED,
ICON_UNDEFINED, ICON_UNDEFINED, 0, 0);
}
mCode = code;
mEnabled = (code != CODE_UNSPECIFIED);
mAltCode = CODE_UNSPECIFIED;
mIconId = iconId;
mDisabledIconId = ICON_UNDEFINED;
mPreviewIconId = ICON_UNDEFINED;
// Horizontal gap is divided equally to both sides of the key.
mX = x + mHorizontalGap / 2;
mX = x + params.mHorizontalGap / 2;
mY = y;
mHitBox.set(x, y, x + width + 1, y + height);
@ -206,8 +217,7 @@ public class Key {
XmlPullParser parser) throws XmlPullParserException {
final float horizontalGap = isSpacer() ? 0 : params.mHorizontalGap;
final int keyHeight = row.mRowHeight;
mVerticalGap = params.mVerticalGap;
mHeight = keyHeight - mVerticalGap;
mHeight = keyHeight - params.mVerticalGap;
final TypedArray keyAttr = res.obtainAttributes(Xml.asAttributeSet(parser),
R.styleable.Keyboard_Key);
@ -221,7 +231,6 @@ public class Key {
mX = Math.round(keyXPos + horizontalGap / 2);
mY = keyYPos;
mWidth = Math.round(keyWidth - horizontalGap);
mHorizontalGap = Math.round(horizontalGap);
mHitBox.set(Math.round(keyXPos), keyYPos, Math.round(keyXPos + keyWidth) + 1,
keyYPos + keyHeight);
// Update row to have current x coordinate.
@ -230,15 +239,15 @@ public class Key {
mBackgroundType = style.getInt(keyAttr,
R.styleable.Keyboard_Key_backgroundType, row.getDefaultBackgroundType());
mVisualInsetsLeft = Math.round(ResourceUtils.getDimensionOrFraction(keyAttr,
final int visualInsetsLeft = Math.round(ResourceUtils.getDimensionOrFraction(keyAttr,
R.styleable.Keyboard_Key_visualInsetsLeft, params.mBaseWidth, 0));
mVisualInsetsRight = Math.round(ResourceUtils.getDimensionOrFraction(keyAttr,
final int visualInsetsRight = Math.round(ResourceUtils.getDimensionOrFraction(keyAttr,
R.styleable.Keyboard_Key_visualInsetsRight, params.mBaseWidth, 0));
mIconId = KeySpecParser.getIconId(style.getString(keyAttr,
R.styleable.Keyboard_Key_keyIcon));
mDisabledIconId = KeySpecParser.getIconId(style.getString(keyAttr,
final int disabledIconId = KeySpecParser.getIconId(style.getString(keyAttr,
R.styleable.Keyboard_Key_keyIconDisabled));
mPreviewIconId = KeySpecParser.getIconId(style.getString(keyAttr,
final int previewIconId = KeySpecParser.getIconId(style.getString(keyAttr,
R.styleable.Keyboard_Key_keyIconPreview));
mLabelFlags = style.getFlag(keyAttr, R.styleable.Keyboard_Key_keyLabelFlags)
@ -332,11 +341,20 @@ public class Key {
} else {
mCode = KeySpecParser.toUpperCaseOfCodeForLocale(code, needsToUpperCase, locale);
}
mOutputText = outputText;
mAltCode = KeySpecParser.toUpperCaseOfCodeForLocale(
final int altCode = KeySpecParser.toUpperCaseOfCodeForLocale(
KeySpecParser.parseCode(style.getString(keyAttr,
R.styleable.Keyboard_Key_altCode), params.mCodesSet, CODE_UNSPECIFIED),
needsToUpperCase, locale);
if (outputText == null && altCode == CODE_UNSPECIFIED
&& disabledIconId == ICON_UNDEFINED && previewIconId == ICON_UNDEFINED
&& visualInsetsLeft == 0 && visualInsetsRight == 0) {
mOptionalAttributes = null;
} else {
mOptionalAttributes = new OptionalAttributes(outputText, altCode,
disabledIconId, previewIconId,
visualInsetsLeft, visualInsetsRight);
}
mHashCode = computeHashCode(this);
keyAttr.recycle();
@ -371,17 +389,17 @@ public class Key {
key.mIconId,
key.mBackgroundType,
Arrays.hashCode(key.mMoreKeys),
key.mOutputText,
key.getOutputText(),
key.mActionFlags,
key.mLabelFlags,
// Key can be distinguishable without the following members.
// key.mAltCode,
// key.mDisabledIconId,
// key.mPreviewIconId,
// key.mOptionalAttributes.mAltCode,
// key.mOptionalAttributes.mDisabledIconId,
// key.mOptionalAttributes.mPreviewIconId,
// key.mHorizontalGap,
// key.mVerticalGap,
// key.mVisualInsetLeft,
// key.mVisualInsetRight,
// key.mOptionalAttributes.mVisualInsetLeft,
// key.mOptionalAttributes.mVisualInsetRight,
// key.mMaxMoreKeysColumn,
});
}
@ -398,7 +416,7 @@ public class Key {
&& o.mIconId == mIconId
&& o.mBackgroundType == mBackgroundType
&& Arrays.equals(o.mMoreKeys, mMoreKeys)
&& TextUtils.equals(o.mOutputText, mOutputText)
&& TextUtils.equals(o.getOutputText(), getOutputText())
&& o.mActionFlags == mActionFlags
&& o.mLabelFlags == mLabelFlags;
}
@ -578,8 +596,20 @@ public class Key {
return (mMoreKeysColumnAndFlags & MORE_KEYS_FLAGS_EMBEDDED_MORE_KEY) != 0;
}
public String getOutputText() {
final OptionalAttributes attrs = mOptionalAttributes;
return (attrs != null) ? attrs.mOutputText : null;
}
public int getAltCode() {
final OptionalAttributes attrs = mOptionalAttributes;
return (attrs != null) ? attrs.mAltCode : CODE_UNSPECIFIED;
}
public Drawable getIcon(KeyboardIconsSet iconSet, int alpha) {
final int iconId = mEnabled ? mIconId : mDisabledIconId;
final OptionalAttributes attrs = mOptionalAttributes;
final int disabledIconId = (attrs != null) ? attrs.mDisabledIconId : ICON_UNDEFINED;
final int iconId = mEnabled ? mIconId : disabledIconId;
final Drawable icon = iconSet.getIconDrawable(iconId);
if (icon != null) {
icon.setAlpha(alpha);
@ -588,9 +618,21 @@ public class Key {
}
public Drawable getPreviewIcon(KeyboardIconsSet iconSet) {
return mPreviewIconId != ICON_UNDEFINED
? iconSet.getIconDrawable(mPreviewIconId)
: iconSet.getIconDrawable(mIconId);
final OptionalAttributes attrs = mOptionalAttributes;
final int previewIconId = (attrs != null) ? attrs.mPreviewIconId : ICON_UNDEFINED;
return previewIconId != ICON_UNDEFINED
? iconSet.getIconDrawable(previewIconId) : iconSet.getIconDrawable(mIconId);
}
public int getDrawX() {
final OptionalAttributes attrs = mOptionalAttributes;
return (attrs == null) ? mX : mX + attrs.mVisualInsetsLeft;
}
public int getDrawWidth() {
final OptionalAttributes attrs = mOptionalAttributes;
return (attrs == null) ? mWidth
: mWidth - attrs.mVisualInsetsLeft - attrs.mVisualInsetsRight;
}
/**

View File

@ -396,14 +396,14 @@ public class Keyboard {
}
private void updateHistogram(Key key) {
final int height = key.mHeight + key.mVerticalGap;
final int height = key.mHeight + mVerticalGap;
final int heightCount = updateHistogramCounter(mHeightHistogram, height);
if (heightCount > mMaxHeightCount) {
mMaxHeightCount = heightCount;
mMostCommonKeyHeight = height;
}
final int width = key.mWidth + key.mHorizontalGap;
final int width = key.mWidth + mHorizontalGap;
final int widthCount = updateHistogramCounter(mWidthHistogram, width);
if (widthCount > mMaxWidthCount) {
mMaxWidthCount = widthCount;

View File

@ -608,7 +608,7 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
}
private void onDrawKey(Key key, Canvas canvas, Paint paint, KeyDrawParams params) {
final int keyDrawX = key.mX + key.mVisualInsetsLeft + getPaddingLeft();
final int keyDrawX = key.getDrawX() + getPaddingLeft();
final int keyDrawY = key.mY + getPaddingTop();
canvas.translate(keyDrawX, keyDrawY);
@ -623,8 +623,7 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
// Draw key background.
protected void onDrawKeyBackground(Key key, Canvas canvas, KeyDrawParams params) {
final int bgWidth = key.mWidth - key.mVisualInsetsLeft - key.mVisualInsetsRight
+ params.mPadding.left + params.mPadding.right;
final int bgWidth = key.getDrawWidth() + params.mPadding.left + params.mPadding.right;
final int bgHeight = key.mHeight + params.mPadding.top + params.mPadding.bottom;
final int bgX = -params.mPadding.left;
final int bgY = -params.mPadding.top;
@ -645,7 +644,7 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
// Draw key top visuals.
protected void onDrawKeyTopVisuals(Key key, Canvas canvas, Paint paint, KeyDrawParams params) {
final int keyWidth = key.mWidth - key.mVisualInsetsLeft - key.mVisualInsetsRight;
final int keyWidth = key.getDrawWidth();
final int keyHeight = key.mHeight;
final float centerX = keyWidth * 0.5f;
final float centerY = keyHeight * 0.5f;
@ -821,7 +820,7 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
// Draw popup hint "..." at the bottom right corner of the key.
protected void drawKeyPopupHint(Key key, Canvas canvas, Paint paint, KeyDrawParams params) {
final int keyWidth = key.mWidth - key.mVisualInsetsLeft - key.mVisualInsetsRight;
final int keyWidth = key.getDrawWidth();
final int keyHeight = key.mHeight;
paint.setTypeface(params.mKeyTypeface);
@ -1012,7 +1011,11 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
@SuppressWarnings("deprecation") // setBackgroundDrawable is replaced by setBackground in API16
@Override
public void showKeyPreview(PointerTracker tracker) {
if (!mShowKeyPreviewPopup) return;
final KeyPreviewDrawParams params = mKeyPreviewDrawParams;
if (!mShowKeyPreviewPopup) {
params.mPreviewVisibleOffset = -mKeyboard.mVerticalGap;
return;
}
final TextView previewText = getKeyPreviewText(tracker.mPointerId);
// If the key preview has no parent view yet, add it to the ViewGroup which can place
@ -1029,7 +1032,6 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
if (key == null)
return;
final KeyPreviewDrawParams params = mKeyPreviewDrawParams;
final String label = key.isShiftedLetterActivated() ? key.mHintLabel : key.mLabel;
// What we show as preview should match what we show on a key top in onDraw().
if (label != null) {
@ -1052,7 +1054,7 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
previewText.measure(
ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
final int keyDrawWidth = key.mWidth - key.mVisualInsetsLeft - key.mVisualInsetsRight;
final int keyDrawWidth = key.getDrawWidth();
final int previewWidth = previewText.getMeasuredWidth();
final int previewHeight = params.mPreviewHeight;
// The width and height of visible part of the key preview background. The content marker
@ -1068,8 +1070,7 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
// The key preview is horizontally aligned with the center of the visible part of the
// parent key. If it doesn't fit in this {@link KeyboardView}, it is moved inward to fit and
// the left/right background is used if such background is specified.
int previewX = key.mX + key.mVisualInsetsLeft - (previewWidth - keyDrawWidth) / 2
+ params.mCoordinates[0];
int previewX = key.getDrawX() - (previewWidth - keyDrawWidth) / 2 + params.mCoordinates[0];
if (previewX < 0) {
previewX = 0;
if (params.mPreviewLeftBackground != null) {

View File

@ -618,9 +618,9 @@ public class MainKeyboardView extends KeyboardView implements PointerTracker.Key
// The more keys keyboard is usually vertically aligned with the top edge of the parent key
// (plus vertical gap). If the key preview is enabled, the more keys keyboard is vertically
// aligned with the bottom edge of the visible part of the key preview.
final int pointY = parentKey.mY + (keyPreviewEnabled
? mKeyPreviewDrawParams.mPreviewVisibleOffset
: -parentKey.mVerticalGap);
// {@code mPreviewVisibleOffset} has been set appropriately in
// {@link KeyboardView#showKeyPreview(PointerTracker)}.
final int pointY = parentKey.mY + mKeyPreviewDrawParams.mPreviewVisibleOffset;
moreKeysPanel.showMoreKeysPanel(
this, this, pointX, pointY, mMoreKeysWindow, mKeyboardActionListener);
final int translatedX = moreKeysPanel.translateX(tracker.getLastX());

View File

@ -330,10 +330,10 @@ public class PointerTracker implements PointerTrackerQueue.Element {
final int y) {
final boolean ignoreModifierKey = mIgnoreModifierKey && key.isModifier();
final boolean altersCode = key.altCodeWhileTyping() && mTimerProxy.isTypingState();
final int code = altersCode ? key.mAltCode : primaryCode;
final int code = altersCode ? key.getAltCode() : primaryCode;
if (DEBUG_LISTENER) {
Log.d(TAG, "onCodeInput: " + Keyboard.printableCode(code) + " text=" + key.mOutputText
+ " x=" + x + " y=" + y
Log.d(TAG, "onCodeInput: " + Keyboard.printableCode(code)
+ " text=" + key.getOutputText() + " x=" + x + " y=" + y
+ " ignoreModifier=" + ignoreModifierKey + " altersCode=" + altersCode
+ " enabled=" + key.isEnabled());
}
@ -347,7 +347,7 @@ public class PointerTracker implements PointerTrackerQueue.Element {
// Even if the key is disabled, it should respond if it is in the altCodeWhileTyping state.
if (key.isEnabled() || altersCode) {
if (code == Keyboard.CODE_OUTPUT_TEXT) {
mListener.onTextInput(key.mOutputText);
mListener.onTextInput(key.getOutputText());
} else if (code != Keyboard.CODE_UNSPECIFIED) {
mListener.onCodeInput(code, x, y);
}
@ -440,13 +440,13 @@ public class PointerTracker implements PointerTrackerQueue.Element {
}
if (key.altCodeWhileTyping()) {
final int altCode = key.mAltCode;
final int altCode = key.getAltCode();
final Key altKey = mKeyboard.getKey(altCode);
if (altKey != null) {
updateReleaseKeyGraphics(altKey);
}
for (final Key k : mKeyboard.mAltCodeKeysWhileTyping) {
if (k != key && k.mAltCode == altCode) {
if (k != key && k.getAltCode() == altCode) {
updateReleaseKeyGraphics(k);
}
}
@ -479,13 +479,13 @@ public class PointerTracker implements PointerTrackerQueue.Element {
}
if (key.altCodeWhileTyping() && mTimerProxy.isTypingState()) {
final int altCode = key.mAltCode;
final int altCode = key.getAltCode();
final Key altKey = mKeyboard.getKey(altCode);
if (altKey != null) {
updatePressKeyGraphics(altKey);
}
for (final Key k : mKeyboard.mAltCodeKeysWhileTyping) {
if (k != key && k.mAltCode == altCode) {
if (k != key && k.getAltCode() == altCode) {
updatePressKeyGraphics(k);
}
}

View File

@ -257,7 +257,7 @@ public class ResearchLog {
for (Key keyboardKey : keyboardKeys) {
mJsonWriter.beginObject();
mJsonWriter.name("code").value(keyboardKey.mCode);
mJsonWriter.name("altCode").value(keyboardKey.mAltCode);
mJsonWriter.name("altCode").value(keyboardKey.getAltCode());
mJsonWriter.name("x").value(keyboardKey.mX);
mJsonWriter.name("y").value(keyboardKey.mY);
mJsonWriter.name("w").value(keyboardKey.mWidth);

View File

@ -1045,7 +1045,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
final int y, final boolean ignoreModifierKey, final boolean altersCode,
final int code) {
if (key != null) {
CharSequence outputText = key.mOutputText;
String outputText = key.getOutputText();
final Object[] values = {
Keyboard.printableCode(scrubDigitFromCodePoint(code)), outputText == null ? null
: scrubDigitsFromString(outputText.toString()),