aboutsummaryrefslogtreecommitdiffstats
path: root/java/src/com/android/inputmethod/latin/BaseKeyboardParser.java
diff options
context:
space:
mode:
Diffstat (limited to 'java/src/com/android/inputmethod/latin/BaseKeyboardParser.java')
-rw-r--r--java/src/com/android/inputmethod/latin/BaseKeyboardParser.java197
1 files changed, 173 insertions, 24 deletions
diff --git a/java/src/com/android/inputmethod/latin/BaseKeyboardParser.java b/java/src/com/android/inputmethod/latin/BaseKeyboardParser.java
index 628e764b5..496f65174 100644
--- a/java/src/com/android/inputmethod/latin/BaseKeyboardParser.java
+++ b/java/src/com/android/inputmethod/latin/BaseKeyboardParser.java
@@ -18,6 +18,7 @@ package com.android.inputmethod.latin;
import com.android.inputmethod.latin.BaseKeyboard.Key;
import com.android.inputmethod.latin.BaseKeyboard.Row;
+import com.android.inputmethod.latin.KeyboardSwitcher.KeyboardId;
import org.xmlpull.v1.XmlPullParserException;
@@ -52,7 +53,7 @@ import java.util.List;
* ...
* >/Keyboard<
* </pre>
- * The xml file which is included in other file must have &gt;merge&lt; as root element, such as:
+ * The XML file which is included in other file must have &gt;merge&lt; as root element, such as:
* <pre>
* &gt;!-- xml/other_keys.xml --&lt;
* &gt;merge&lt;
@@ -70,6 +71,38 @@ import java.util.List;
* ...
* &gt;/merge&lt;
* </pre>
+ * You can also use switch-case-default tags to select Rows and Keys.
+ * <pre>
+ * &gt;switch&lt;
+ * &gt;case case_attribute*&lt;
+ * &gt;!-- Any valid tags at switch position --&lt;
+ * &gt;/case&lt;
+ * ...
+ * &gt;default&lt;
+ * &gt;!-- Any valid tags at switch position --&lt;
+ * &gt;/default&lt;
+ * &gt;/switch&lt;
+ * </pre>
+ *
+ * TODO: These are some random ideas to improve this parser.
+ * - can specify keyWidth attribute by multiplication of default keyWidth
+ * for example: keyWidth="200%b" ("b" stands for "base")
+ * - can declare style and specify styles within tags.
+ * for example:
+ * &gt;switch&lt;
+ * &gt;case colorScheme="white"&lt;
+ * &gt;declare-style name="shift-key" parentStyle="modifier-key"&lt;
+ * &gt;item name="keyIcon"&lt;@drawable/sym_keyboard_shift"&gt;/item&lt;
+ * &gt;/declare-style&lt;
+ * &gt;/case&lt;
+ * &gt;case colorScheme="black"&lt;
+ * &gt;declare-style name="shift-key" parentStyle="modifier-key"&lt;
+ * &gt;item name="keyIcon"&lt;@drawable/sym_bkeyboard_shift"&gt;/item&lt;
+ * &gt;/declare-style&lt;
+ * &gt;/case&lt;
+ * &gt;/switch&lt;
+ * ...
+ * &gt;Key include-style="shift-key" ... /&lt;
*/
public class BaseKeyboardParser {
private static final String TAG = "BaseKeyboardParser";
@@ -83,6 +116,17 @@ public class BaseKeyboardParser {
private static final String TAG_SPACER = "Spacer";
private static final String TAG_INCLUDE = "include";
private static final String TAG_MERGE = "merge";
+ private static final String TAG_SWITCH = "switch";
+ private static final String TAG_CASE = "case";
+ private static final String TAG_DEFAULT = "default";
+
+ // String representation of KeyboardSwitcher.MODE_xxx.
+ private static final String MODE_TEXT = "text";
+ private static final String MODE_URL = "url";
+ private static final String MODE_EMAIL = "email";
+ private static final String MODE_IM = "im";
+ private static final String MODE_WEB = "web";
+ private static final String MODE_PHONE = "phone";
private final BaseKeyboard mKeyboard;
private final Resources mResources;
@@ -143,7 +187,7 @@ public class BaseKeyboardParser {
a.recycle();
}
- private void parseKeyboardContent(XmlResourceParser parser, final List<Key> keys)
+ private void parseKeyboardContent(XmlResourceParser parser, List<Key> keys)
throws XmlPullParserException, IOException {
if (DEBUG_PARSER) debugEnterMethod("parseKeyboardContent", keys == null);
int event;
@@ -153,14 +197,13 @@ public class BaseKeyboardParser {
if (DEBUG_TAG) debugStartTag("parseKeyboardContent", tag, keys == null);
if (TAG_ROW.equals(tag)) {
Row row = mKeyboard.createRowFromXml(mResources, parser);
- if (keys != null && maybeStartRow(row)) {
- parseRowContent(parser, row, keys);
- } else {
- // Skip entire <Row></Row>
- parseRowContent(parser, row, null);
- }
+ if (keys != null)
+ startRow(row);
+ parseRowContent(parser, row, keys);
} else if (TAG_INCLUDE.equals(tag)) {
parseIncludeKeyboardContent(parser, keys);
+ } else if (TAG_SWITCH.equals(tag)) {
+ parseSwitchKeyboardContent(parser, keys);
} else {
throw new IllegalStartTag(parser, TAG_ROW);
}
@@ -170,6 +213,8 @@ public class BaseKeyboardParser {
if (TAG_KEYBOARD.equals(tag)) {
endKeyboard(mKeyboard.getVerticalGap());
break;
+ } else if (TAG_CASE.equals(tag) || TAG_DEFAULT.equals(tag)) {
+ break;
} else if (TAG_MERGE.equals(tag)) {
break;
} else {
@@ -194,6 +239,8 @@ public class BaseKeyboardParser {
parseSpacer(parser, keys);
} else if (TAG_INCLUDE.equals(tag)) {
parseIncludeRowContent(parser, row, keys);
+ } else if (TAG_SWITCH.equals(tag)) {
+ parseSwitchRowContent(parser, row, keys);
} else {
throw new IllegalStartTag(parser, TAG_KEY);
}
@@ -204,6 +251,8 @@ public class BaseKeyboardParser {
if (keys != null)
endRow();
break;
+ } else if (TAG_CASE.equals(tag) || TAG_DEFAULT.equals(tag)) {
+ break;
} else if (TAG_MERGE.equals(tag)) {
break;
} else {
@@ -237,7 +286,7 @@ public class BaseKeyboardParser {
} else {
final TypedArray a = mResources.obtainAttributes(Xml.asAttributeSet(parser),
R.styleable.BaseKeyboard);
- int gap = getDimensionOrFraction(a, R.styleable.BaseKeyboard_horizontalGap,
+ final int gap = getDimensionOrFraction(a, R.styleable.BaseKeyboard_horizontalGap,
mKeyboard.getKeyboardWidth(), 0);
a.recycle();
checkEndTag(TAG_SPACER, parser);
@@ -247,17 +296,20 @@ public class BaseKeyboardParser {
private void parseIncludeKeyboardContent(XmlResourceParser parser, List<Key> keys)
throws XmlPullParserException, IOException {
+ if (DEBUG_PARSER) debugEnterMethod("parseIncludeKeyboardContent", keys == null);
parseIncludeInternal(parser, null, keys);
+ if (DEBUG_PARSER) debugLeaveMethod("parseIncludeKeyboardContent", keys == null);
}
private void parseIncludeRowContent(XmlResourceParser parser, Row row, List<Key> keys)
throws XmlPullParserException, IOException {
+ if (DEBUG_PARSER) debugEnterMethod("parseIncludeRowContent", keys == null);
parseIncludeInternal(parser, row, keys);
+ if (DEBUG_PARSER) debugLeaveMethod("parseIncludeRowContent", keys == null);
}
private void parseIncludeInternal(XmlResourceParser parser, Row row, List<Key> keys)
throws XmlPullParserException, IOException {
- if (DEBUG_PARSER) debugEnterMethod("parseInclude", keys == null);
if (keys == null) {
checkEndTag(TAG_INCLUDE, parser);
} else {
@@ -272,7 +324,6 @@ public class BaseKeyboardParser {
throw new ParseException("No keyboardLayout attribute in <include/>", parser);
parseMerge(mResources.getLayout(keyboardLayout), row, keys);
}
- if (DEBUG_PARSER) debugLeaveMethod("parseInclude", keys == null);
}
private void parseMerge(XmlResourceParser parser, Row row, List<Key> keys)
@@ -281,7 +332,7 @@ public class BaseKeyboardParser {
int event;
while ((event = parser.next()) != XmlResourceParser.END_DOCUMENT) {
if (event == XmlResourceParser.START_TAG) {
- String tag = parser.getName();
+ final String tag = parser.getName();
if (DEBUG_TAG) debugStartTag("parseMerge", tag, keys == null);
if (TAG_MERGE.equals(tag)) {
if (row == null) {
@@ -299,6 +350,113 @@ public class BaseKeyboardParser {
if (DEBUG_PARSER) debugLeaveMethod("parseMerge", keys == null);
}
+ private void parseSwitchKeyboardContent(XmlResourceParser parser, List<Key> keys)
+ throws XmlPullParserException, IOException {
+ if (DEBUG_PARSER) debugEnterMethod("parseSwitchKeyboardContent", keys == null);
+ parseSwitchInternal(parser, null, keys);
+ if (DEBUG_PARSER) debugLeaveMethod("parseSwitchKeyboardContent", keys == null);
+ }
+
+ private void parseSwitchRowContent(XmlResourceParser parser, Row row, List<Key> keys)
+ throws XmlPullParserException, IOException {
+ if (DEBUG_PARSER) debugEnterMethod("parseSwitchRowContent", keys == null);
+ parseSwitchInternal(parser, row, keys);
+ if (DEBUG_PARSER) debugLeaveMethod("parseSwitchRowContent", keys == null);
+ }
+
+ private void parseSwitchInternal(XmlResourceParser parser, Row row, List<Key> keys)
+ throws XmlPullParserException, IOException {
+ boolean selected = false;
+ int event;
+ if (DEBUG_TAG) Log.d(TAG, "parseSwitchInternal: id=" + mKeyboard.mId);
+ while ((event = parser.next()) != XmlResourceParser.END_DOCUMENT) {
+ if (event == XmlResourceParser.START_TAG) {
+ final String tag = parser.getName();
+ if (DEBUG_TAG) debugStartTag("parseSwitchInternal", tag, keys == null);
+ if (TAG_CASE.equals(tag)) {
+ selected |= parseCase(parser, row, selected ? null : keys);
+ } else if (TAG_DEFAULT.equals(tag)) {
+ selected |= parseDefault(parser, row, selected ? null : keys);
+ } else {
+ throw new IllegalStartTag(parser, TAG_KEY);
+ }
+ } else if (event == XmlResourceParser.END_TAG) {
+ final String tag = parser.getName();
+ if (DEBUG_TAG) debugEndTag("parseRowContent", tag, keys == null);
+ if (TAG_SWITCH.equals(tag)) {
+ break;
+ } else {
+ throw new IllegalEndTag(parser, TAG_KEY);
+ }
+ }
+ }
+ }
+
+ private boolean parseCase(XmlResourceParser parser, Row row, List<Key> keys)
+ throws XmlPullParserException, IOException {
+ if (DEBUG_PARSER) debugEnterMethod("parseCase", keys == null);
+ final boolean selected = parseCaseCondition(parser);
+ if (row == null) {
+ // Processing Rows.
+ parseKeyboardContent(parser, selected ? keys : null);
+ } else {
+ // Processing Keys.
+ parseRowContent(parser, row, selected ? keys : null);
+ }
+ if (DEBUG_PARSER) debugLeaveMethod("parseCase", keys == null || !selected);
+ return selected;
+ }
+
+ private boolean parseCaseCondition(XmlResourceParser parser) {
+ final BaseKeyboard keyboard = mKeyboard;
+ final TypedArray a = mResources.obtainAttributes(Xml.asAttributeSet(parser),
+ R.styleable.BaseKeyboard_Case);
+ final String mode = a.getString(R.styleable.BaseKeyboard_Case_mode);
+ final String settingsKey = a.getString(R.styleable.BaseKeyboard_Case_settingsKey);
+ final String voiceKey = a.getString(R.styleable.BaseKeyboard_Case_voiceKey);
+ a.recycle();
+
+ final KeyboardId id = keyboard.mId;
+ if (id == null)
+ return true;
+ final boolean modeMatched = (mode == null
+ || id.mMode == parseModeString(mode));
+ final boolean settingsKeyMatched = (settingsKey == null
+ || id.mHasSettingsKey == Boolean.parseBoolean(settingsKey));
+ final boolean voiceKeyMatched = (voiceKey == null
+ || id.mHasVoiceKey == Boolean.parseBoolean(voiceKey));
+ final boolean selected = modeMatched && settingsKeyMatched && voiceKeyMatched;
+ if (DEBUG_TAG) {
+ Log.d(TAG, "parseCaseCondition: " + Boolean.toString(selected).toUpperCase()
+ + (mode != null ? " mode=" + mode : "")
+ + (settingsKey != null ? " settingsKey="+settingsKey : "")
+ + (voiceKey != null ? " voiceKey=" + voiceKey : ""));
+ }
+ return selected;
+ }
+
+ private static int parseModeString(String mode) {
+ if (mode.equals(MODE_TEXT)) return KeyboardSwitcher.MODE_TEXT;
+ if (mode.equals(MODE_URL)) return KeyboardSwitcher.MODE_URL;
+ if (mode.equals(MODE_EMAIL)) return KeyboardSwitcher.MODE_EMAIL;
+ if (mode.equals(MODE_IM)) return KeyboardSwitcher.MODE_IM;
+ if (mode.equals(MODE_WEB)) return KeyboardSwitcher.MODE_WEB;
+ if (mode.equals(MODE_PHONE)) return KeyboardSwitcher.MODE_PHONE;
+ throw new RuntimeException("uknown mode attribute in Keyboard XML: " + mode);
+ }
+
+ private boolean parseDefault(XmlResourceParser parser, Row row, List<Key> keys)
+ throws XmlPullParserException, IOException {
+ if (DEBUG_PARSER) debugEnterMethod("parseDefault", keys == null);
+ if (row == null) {
+ parseKeyboardContent(parser, keys);
+ } else {
+ parseRowContent(parser, row, keys);
+ }
+ if (DEBUG_PARSER) debugLeaveMethod("parseDefault", keys == null);
+ return true;
+ }
+
private static void checkEndTag(String tag, XmlResourceParser parser)
throws XmlPullParserException, IOException {
if (parser.next() == XmlResourceParser.END_TAG && tag.equals(parser.getName()))
@@ -306,18 +464,9 @@ public class BaseKeyboardParser {
throw new NonEmptyTag(tag, parser);
}
- // return true if the row is valid for this keyboard mode
- private boolean maybeStartRow(Row row) {
- if (DEBUG_TAG)
- Log.d(TAG, String.format("startRow: mode=0x%08x keyboardMode=0x%08x",
- row.mode, mKeyboard.getKeyboardMode()));
- if (row.mode == 0 || row.mode == mKeyboard.getKeyboardMode()) {
- mCurrentX = 0;
- mCurrentRow = row;
- return true;
- } else {
- return false;
- }
+ private void startRow(Row row) {
+ mCurrentX = 0;
+ mCurrentRow = row;
}
private void endRow() {