aboutsummaryrefslogtreecommitdiffstats
path: root/java/src
diff options
context:
space:
mode:
authorTadashi G. Takaoka <takaoka@google.com>2011-05-30 20:05:50 +0900
committerTadashi G. Takaoka <takaoka@google.com>2011-05-31 17:52:32 +0900
commit327763e5181fe73a1d6d806a57e2456c84159f2a (patch)
tree224c7f2d85673fe038e39d14668104eb68082049 /java/src
parent88251a95557480340718053efb8b3574fb513008 (diff)
downloadlatinime-327763e5181fe73a1d6d806a57e2456c84159f2a.tar.gz
latinime-327763e5181fe73a1d6d806a57e2456c84159f2a.tar.xz
latinime-327763e5181fe73a1d6d806a57e2456c84159f2a.zip
Adaptive keyboard width/position parser
This change introduces the following features to Keyboard XML format. * "keyXPos" can specify the key X coordinate directly. * "keyXPos" can be negative. The X coordinate will be calcluated from the right edge of the keyboard toward left. * "keyWidth" can be zero to be filled up to the right side. * "keyWidth can be negative. The key will be filled up to both sides. * Spacer's horizontalGap is renamed as keyWidth, and can be inherited from key-style. * Spacer can have keyXPos attribute. Using these syntax, all keyboard layouts have been re-written. Cherry-Pick: I314b2e8ca2aa145ff9506cbf927140a15685af42 Bug: 4442045 Change-Id: I048fe5eaef020d8472ab577e9d326042bae2f3fa
Diffstat (limited to 'java/src')
-rw-r--r--java/src/com/android/inputmethod/keyboard/Key.java45
-rw-r--r--java/src/com/android/inputmethod/keyboard/KeyboardId.java2
-rw-r--r--java/src/com/android/inputmethod/keyboard/KeyboardParser.java54
3 files changed, 78 insertions, 23 deletions
diff --git a/java/src/com/android/inputmethod/keyboard/Key.java b/java/src/com/android/inputmethod/keyboard/Key.java
index ef86d66ad..cb529461a 100644
--- a/java/src/com/android/inputmethod/keyboard/Key.java
+++ b/java/src/com/android/inputmethod/keyboard/Key.java
@@ -101,6 +101,10 @@ public class Key {
/** Key is enabled and responds on press */
public boolean mEnabled = true;
+ // keyWidth constants
+ private static final int KEYWIDTH_FILL_RIGHT = 0;
+ private static final int KEYWIDTH_FILL_BOTH = -1;
+
private final static int[] KEY_STATE_NORMAL_ON = {
android.R.attr.state_checkable,
android.R.attr.state_checked
@@ -140,7 +144,7 @@ public class Key {
};
/**
- * This constructor is being used only for key in mini popup keyboard.
+ * This constructor is being used only for key in popup mini keyboard.
*/
public Key(Resources res, Keyboard keyboard, CharSequence popupCharacter, int x, int y,
int width, int height, int edgeFlags) {
@@ -178,6 +182,7 @@ public class Key {
* @param x the x coordinate of the top-left
* @param y the y coordinate of the top-left
* @param parser the XML parser containing the attributes for this key
+ * @param keyStyles active key styles set
*/
public Key(Resources res, Row row, int x, int y, XmlResourceParser parser,
KeyStyles keyStyles) {
@@ -185,6 +190,7 @@ public class Key {
final TypedArray keyboardAttr = res.obtainAttributes(Xml.asAttributeSet(parser),
R.styleable.Keyboard);
+ int keyWidth;
try {
mHeight = KeyboardParser.getDimensionOrFraction(keyboardAttr,
R.styleable.Keyboard_rowHeight,
@@ -192,17 +198,13 @@ public class Key {
mGap = KeyboardParser.getDimensionOrFraction(keyboardAttr,
R.styleable.Keyboard_horizontalGap,
mKeyboard.getDisplayWidth(), row.mDefaultHorizontalGap);
- mWidth = KeyboardParser.getDimensionOrFraction(keyboardAttr,
+ keyWidth = KeyboardParser.getDimensionOrFraction(keyboardAttr,
R.styleable.Keyboard_keyWidth,
- mKeyboard.getDisplayWidth(), row.mDefaultWidth) - mGap;
+ mKeyboard.getDisplayWidth(), row.mDefaultWidth);
} finally {
keyboardAttr.recycle();
}
- // Horizontal gap is divided equally to both sides of the key.
- mX = x + mGap / 2;
- mY = y;
-
final TypedArray keyAttr = res.obtainAttributes(Xml.asAttributeSet(parser),
R.styleable.Keyboard_Key);
try {
@@ -216,6 +218,35 @@ public class Key {
style = keyStyles.getEmptyKeyStyle();
}
+ final int keyboardWidth = mKeyboard.getDisplayWidth();
+ int keyXPos = KeyboardParser.getDimensionOrFraction(keyAttr,
+ R.styleable.Keyboard_Key_keyXPos, keyboardWidth, x);
+ if (keyXPos < 0) {
+ // If keyXPos is negative, the actual x-coordinate will be k + keyXPos.
+ keyXPos += keyboardWidth;
+ if (keyXPos < x) {
+ // keyXPos shouldn't be less than x because drawable area for this key starts
+ // at x. Or, this key will overlaps the adjacent key on its left hand side.
+ keyXPos = x;
+ }
+ }
+ if (keyWidth == KEYWIDTH_FILL_RIGHT) {
+ // If keyWidth is zero, the actual key width will be determined to fill out the
+ // area up to the right edge of the keyboard.
+ keyWidth = keyboardWidth - keyXPos;
+ } else if (keyWidth <= KEYWIDTH_FILL_BOTH) {
+ // If keyWidth is negative, the actual key width will be determined to fill out the
+ // area between the nearest key on the left hand side and the right edge of the
+ // keyboard.
+ keyXPos = x;
+ keyWidth = keyboardWidth - keyXPos;
+ }
+
+ // Horizontal gap is divided equally to both sides of the key.
+ mX = keyXPos + mGap / 2;
+ mY = y;
+ mWidth = keyWidth - mGap;
+
final CharSequence[] popupCharacters = style.getTextArray(keyAttr,
R.styleable.Keyboard_Key_popupCharacters);
if (res.getBoolean(R.bool.config_digit_popup_characters_enabled)) {
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardId.java b/java/src/com/android/inputmethod/keyboard/KeyboardId.java
index 88d23985a..7c03ec71e 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardId.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardId.java
@@ -159,7 +159,7 @@ public class KeyboardId {
@Override
public String toString() {
- return String.format("[%s.xml %s %s%d %s %s %s %s%s%s%s%s%s]",
+ return String.format("[%s.xml %s %s%d %s %s %s%s%s%s%s%s%s]",
mXmlName,
mLocale,
(mOrientation == 1 ? "port" : "land"), mWidth,
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardParser.java b/java/src/com/android/inputmethod/keyboard/KeyboardParser.java
index 43d9f271f..4ae011347 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardParser.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardParser.java
@@ -280,7 +280,7 @@ public class KeyboardParser {
if (TAG_KEY.equals(tag)) {
parseKey(parser, row, keys);
} else if (TAG_SPACER.equals(tag)) {
- parseSpacer(parser, keys);
+ parseSpacer(parser, row, keys);
} else if (TAG_INCLUDE.equals(tag)) {
parseIncludeRowContent(parser, row, keys);
} else if (TAG_SWITCH.equals(tag)) {
@@ -327,19 +327,32 @@ public class KeyboardParser {
}
}
- private void parseSpacer(XmlResourceParser parser, List<Key> keys)
+ private void parseSpacer(XmlResourceParser parser, Row row, List<Key> keys)
throws XmlPullParserException, IOException {
if (keys == null) {
checkEndTag(TAG_SPACER, parser);
} else {
if (DEBUG) Log.d(TAG, String.format("<%s />", TAG_SPACER));
- final TypedArray a = mResources.obtainAttributes(Xml.asAttributeSet(parser),
+ final TypedArray keyboardAttr = mResources.obtainAttributes(Xml.asAttributeSet(parser),
R.styleable.Keyboard);
- final int gap = getDimensionOrFraction(a, R.styleable.Keyboard_horizontalGap,
- mKeyboard.getDisplayWidth(), 0);
- a.recycle();
+ if (keyboardAttr.hasValue(R.styleable.Keyboard_horizontalGap))
+ throw new IllegalAttribute(parser, "horizontalGap");
+ final int defaultWidth = (row != null) ? row.mDefaultWidth : 0;
+ final int keyWidth = getDimensionOrFraction(keyboardAttr, R.styleable.Keyboard_keyWidth,
+ mKeyboard.getDisplayWidth(), defaultWidth);
+ keyboardAttr.recycle();
+
+ final TypedArray keyAttr = mResources.obtainAttributes(Xml.asAttributeSet(parser),
+ R.styleable.Keyboard_Key);
+ int keyXPos = KeyboardParser.getDimensionOrFraction(keyAttr,
+ R.styleable.Keyboard_Key_keyXPos, mKeyboard.getDisplayWidth(), mCurrentX);
+ if (keyXPos < 0) {
+ // If keyXPos is negative, the actual x-coordinate will be display_width + keyXPos.
+ keyXPos += mKeyboard.getDisplayWidth();
+ }
+
checkEndTag(TAG_SPACER, parser);
- setSpacer(gap);
+ setSpacer(keyXPos, keyWidth);
}
}
@@ -566,14 +579,14 @@ public class KeyboardParser {
private void startRow(Row row) {
mCurrentX = 0;
- setSpacer(mHorizontalEdgesPadding);
+ setSpacer(mCurrentX, mHorizontalEdgesPadding);
mCurrentRow = row;
}
private void endRow() {
if (mCurrentRow == null)
throw new InflateException("orphant end row tag");
- setSpacer(mHorizontalEdgesPadding);
+ setSpacer(mCurrentX, mHorizontalEdgesPadding);
if (mCurrentX > mMaxRowWidth)
mMaxRowWidth = mCurrentX;
mCurrentY += mCurrentRow.mDefaultHeight;
@@ -581,7 +594,7 @@ public class KeyboardParser {
}
private void endKey(Key key) {
- mCurrentX += key.mGap + key.mWidth;
+ mCurrentX = key.mX + key.mGap + key.mWidth;
}
private void endKeyboard(int defaultVerticalGap) {
@@ -589,19 +602,23 @@ public class KeyboardParser {
mTotalHeight = mCurrentY - defaultVerticalGap;
}
- private void setSpacer(int gap) {
- mCurrentX += gap;
+ private void setSpacer(int keyXPos, int width) {
+ mCurrentX = keyXPos + width;
}
public static int getDimensionOrFraction(TypedArray a, int index, int base, int defValue) {
final TypedValue value = a.peekValue(index);
if (value == null)
return defValue;
- if (value.type == TypedValue.TYPE_DIMENSION) {
- return a.getDimensionPixelOffset(index, defValue);
- } else if (value.type == TypedValue.TYPE_FRACTION) {
+ if (value.type == TypedValue.TYPE_FRACTION) {
// Round it to avoid values like 47.9999 from getting truncated
return Math.round(a.getFraction(index, base, base, defValue));
+ } else if (value.type == TypedValue.TYPE_DIMENSION) {
+ return a.getDimensionPixelOffset(index, defValue);
+ } else if (value.type >= TypedValue.TYPE_FIRST_INT
+ && value.type <= TypedValue.TYPE_LAST_INT) {
+ // For enum value.
+ return a.getInt(index, defValue);
}
return defValue;
}
@@ -628,6 +645,13 @@ public class KeyboardParser {
}
@SuppressWarnings("serial")
+ private static class IllegalAttribute extends ParseException {
+ public IllegalAttribute(XmlResourceParser parser, String attribute) {
+ super("Tag " + parser.getName() + " has illegal attribute " + attribute, parser);
+ }
+ }
+
+ @SuppressWarnings("serial")
private static class NonEmptyTag extends ParseException {
public NonEmptyTag(String tag, XmlResourceParser parser) {
super(tag + " must be empty tag", parser);