diff --git a/java/res/values/attrs.xml b/java/res/values/attrs.xml index 7de41f0a0..3f99cdae6 100644 --- a/java/res/values/attrs.xml +++ b/java/res/values/attrs.xml @@ -123,6 +123,8 @@ + + @@ -153,4 +155,9 @@ + + + + + diff --git a/java/res/values/keycodes.xml b/java/res/values/keycodes.xml index cbfe89690..54fa61026 100644 --- a/java/res/values/keycodes.xml +++ b/java/res/values/keycodes.xml @@ -23,7 +23,7 @@ 10 32 -1 - -2 + -2 -5 -100 diff --git a/java/res/values/strings.xml b/java/res/values/strings.xml index 018a1f983..09449dc0d 100644 --- a/java/res/values/strings.xml +++ b/java/res/values/strings.xml @@ -219,11 +219,11 @@ Send - \?123 + \?123 123 - ABC + ABC ALT diff --git a/java/res/xml-xlarge/kbd_phone.xml b/java/res/xml-xlarge/kbd_phone.xml index f30499622..4bbd69d46 100644 --- a/java/res/xml-xlarge/kbd_phone.xml +++ b/java/res/xml-xlarge/kbd_phone.xml @@ -69,7 +69,7 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/java/res/xml/kbd_phone.xml b/java/res/xml/kbd_phone.xml index e6f6a09f5..a01d697a7 100644 --- a/java/res/xml/kbd_phone.xml +++ b/java/res/xml/kbd_phone.xml @@ -25,6 +25,8 @@ latin:verticalGap="@dimen/key_bottom_gap" latin:keyHeight="@dimen/key_height" > + @@ -40,8 +42,8 @@ latin:keyIcon="@drawable/sym_keyboard_num3" /> @@ -57,8 +59,8 @@ latin:keyIcon="@drawable/sym_keyboard_num6" /> @@ -73,19 +75,15 @@ latin:codes="57" latin:keyIcon="@drawable/sym_keyboard_num9" /> @@ -97,10 +95,8 @@ latin:keyIcon="@drawable/sym_keyboard_space" latin:iconPreview="@drawable/sym_keyboard_feedback_space" /> diff --git a/java/res/xml/kbd_phone_black.xml b/java/res/xml/kbd_phone_black.xml index 86759d676..75ce34a74 100644 --- a/java/res/xml/kbd_phone_black.xml +++ b/java/res/xml/kbd_phone_black.xml @@ -82,7 +82,7 @@ latin:rowEdgeFlags="bottom" > + @@ -37,8 +38,8 @@ latin:keyLabel=")" /> @@ -54,8 +55,8 @@ latin:keyLabel="," /> @@ -71,19 +72,15 @@ latin:codes="35" latin:keyIcon="@drawable/sym_keyboard_numpound" /> diff --git a/java/res/xml/kbd_phone_symbols_black.xml b/java/res/xml/kbd_phone_symbols_black.xml index 3e46c5307..06db969ed 100644 --- a/java/res/xml/kbd_phone_symbols_black.xml +++ b/java/res/xml/kbd_phone_symbols_black.xml @@ -80,7 +80,7 @@ latin:rowEdgeFlags="bottom" > + @@ -117,12 +119,8 @@ - + diff --git a/java/res/xml/kbd_qwerty_black_symbol.xml b/java/res/xml/kbd_qwerty_black_symbol.xml index c1ef170f9..840db9c5a 100644 --- a/java/res/xml/kbd_qwerty_black_symbol.xml +++ b/java/res/xml/kbd_qwerty_black_symbol.xml @@ -34,7 +34,7 @@ latin:hasVoiceKey="false" > - - - - + + + + + + + + diff --git a/java/res/xml/kbd_qwerty_row4.xml b/java/res/xml/kbd_qwerty_row4.xml index a5113ea76..cd03c51fc 100644 --- a/java/res/xml/kbd_qwerty_row4.xml +++ b/java/res/xml/kbd_qwerty_row4.xml @@ -29,8 +29,10 @@ - + @@ -38,52 +40,36 @@ latin:mode="web" > + latin:keyStyle="spaceKeyStyle" + latin:keyWidth="20%p" /> + latin:keyStyle="tabKeyStyle" + latin:keyWidth="20%p" /> + latin:keyStyle="spaceKeyStyle" + latin:keyWidth="40%p" /> + latin:keyStyle="functionalKeyStyle" /> @@ -91,13 +77,12 @@ - + latin:keyStyle="toSymbolKeyStyle" + latin:keyWidth="15%p" + latin:keyEdgeFlags="left" /> + @@ -105,62 +90,43 @@ latin:mode="web" > + latin:keyStyle="spaceKeyStyle" + latin:keyWidth="30%p" /> + latin:keyStyle="tabKeyStyle" /> + latin:keyStyle="spaceKeyStyle" + latin:keyWidth="30%p" /> + latin:keyStyle="functionalKeyStyle" /> diff --git a/java/res/xml/kbd_qwerty_symbol.xml b/java/res/xml/kbd_qwerty_symbol.xml deleted file mode 100644 index e90091c36..000000000 --- a/java/res/xml/kbd_qwerty_symbol.xml +++ /dev/null @@ -1,84 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/java/res/xml/kbd_symbols.xml b/java/res/xml/kbd_symbols.xml index 55b7681f9..e9df8163a 100644 --- a/java/res/xml/kbd_symbols.xml +++ b/java/res/xml/kbd_symbols.xml @@ -25,6 +25,8 @@ latin:verticalGap="@dimen/key_bottom_gap" latin:keyHeight="@dimen/key_height" > + @@ -105,11 +107,8 @@ diff --git a/java/res/xml/kbd_symbols_black_row4.xml b/java/res/xml/kbd_symbols_black_row4.xml index a50f8c05d..57f491b97 100644 --- a/java/res/xml/kbd_symbols_black_row4.xml +++ b/java/res/xml/kbd_symbols_black_row4.xml @@ -29,8 +29,8 @@ latin:hasSettingsKey="false" > + latin:keyStyle="micKeyStyle" /> + latin:keyStyle="functionalKeyStyle" /> diff --git a/java/res/xml/kbd_symbols_row4.xml b/java/res/xml/kbd_symbols_row4.xml index f012a4d25..1a5417d08 100644 --- a/java/res/xml/kbd_symbols_row4.xml +++ b/java/res/xml/kbd_symbols_row4.xml @@ -29,44 +29,32 @@ latin:hasSettingsKey="false" > + latin:keyStyle="spaceKeyStyle" + latin:keyWidth="40%p" /> + latin:keyStyle="functionalKeyStyle" /> @@ -75,49 +63,34 @@ latin:hasSettingsKey="true" > + latin:keyStyle="settingsKeyStyle" /> + latin:keyStyle="spaceKeyStyle" + latin:keyWidth="30%p" /> + latin:keyStyle="functionalKeyStyle" /> diff --git a/java/res/xml/kbd_symbols_shift.xml b/java/res/xml/kbd_symbols_shift.xml index 52796561d..f3e79f71e 100644 --- a/java/res/xml/kbd_symbols_shift.xml +++ b/java/res/xml/kbd_symbols_shift.xml @@ -25,6 +25,8 @@ latin:verticalGap="@dimen/key_bottom_gap" latin:keyHeight="@dimen/key_height" > + @@ -58,7 +60,8 @@ @@ -86,11 +89,8 @@ @@ -113,12 +113,8 @@ latin:popupKeyboard="@xml/kbd_popup_template" latin:popupCharacters="≥»›" /> diff --git a/java/res/xml/kbd_symbols_shift_black_row4.xml b/java/res/xml/kbd_symbols_shift_black_row4.xml index 4e5ddcdd4..731cc6eb8 100644 --- a/java/res/xml/kbd_symbols_shift_black_row4.xml +++ b/java/res/xml/kbd_symbols_shift_black_row4.xml @@ -29,8 +29,8 @@ latin:hasSettingsKey="false" > + latin:keyStyle="functionalKeyStyle" /> + latin:keyStyle="spaceKeyStyle" + latin:keyWidth="40%p" /> + latin:keyStyle="functionalKeyStyle" /> @@ -74,48 +62,33 @@ latin:hasSettingsKey="true" > + latin:keyStyle="settingsKeyStyle" /> + latin:keyStyle="functionalKeyStyle" /> + latin:keyStyle="spaceKeyStyle" + latin:keyWidth="30%p" /> + latin:keyStyle="functionalKeyStyle" /> diff --git a/java/src/com/android/inputmethod/latin/BaseKeyboard.java b/java/src/com/android/inputmethod/latin/BaseKeyboard.java index cb0ac216c..485cc3153 100644 --- a/java/src/com/android/inputmethod/latin/BaseKeyboard.java +++ b/java/src/com/android/inputmethod/latin/BaseKeyboard.java @@ -16,6 +16,8 @@ package com.android.inputmethod.latin; +import com.android.inputmethod.latin.BaseKeyboardParser.ParseException; +import com.android.inputmethod.latin.KeyStyles.KeyStyle; import com.android.inputmethod.latin.KeyboardSwitcher.KeyboardId; import org.xmlpull.v1.XmlPullParserException; @@ -26,14 +28,11 @@ import android.content.res.TypedArray; import android.content.res.XmlResourceParser; import android.graphics.drawable.Drawable; import android.text.TextUtils; -import android.util.Log; -import android.util.TypedValue; import android.util.Xml; import java.io.IOException; import java.util.ArrayList; import java.util.List; -import java.util.StringTokenizer; /** * Loads an XML description of a keyboard and stores the attributes of the keys. A keyboard @@ -284,7 +283,8 @@ public class BaseKeyboard { * @param y the y coordinate of the top-left * @param parser the XML parser containing the attributes for this key */ - public Key(Resources res, Row parent, int x, int y, XmlResourceParser parser) { + public Key(Resources res, Row parent, int x, int y, XmlResourceParser parser, + KeyStyles keyStyles) { this(parent); TypedArray a = res.obtainAttributes(Xml.asAttributeSet(parser), @@ -299,44 +299,47 @@ public class BaseKeyboard { R.styleable.BaseKeyboard_keyWidth, keyboard.mDisplayWidth, parent.defaultWidth) - gap; a.recycle(); + a = res.obtainAttributes(Xml.asAttributeSet(parser), R.styleable.BaseKeyboard_Key); + final KeyStyle style; + if (a.hasValue(R.styleable.BaseKeyboard_Key_keyStyle)) { + String styleName = a.getString(R.styleable.BaseKeyboard_Key_keyStyle); + style = keyStyles.getKeyStyle(styleName); + if (style == null) + throw new ParseException("Unknown key style: " + styleName, parser); + } else { + style = keyStyles.getEmptyKeyStyle(); + } + // Horizontal gap is divided equally to both sides of the key. this.x = x + gap / 2; this.y = y; - TypedValue codesValue = new TypedValue(); - a.getValue(R.styleable.BaseKeyboard_Key_codes, codesValue); - if (codesValue.type == TypedValue.TYPE_INT_DEC - || codesValue.type == TypedValue.TYPE_INT_HEX) { - codes = new int[] { codesValue.data }; - } else if (codesValue.type == TypedValue.TYPE_STRING) { - codes = parseCSV(codesValue.string.toString()); - } - - iconPreview = a.getDrawable(R.styleable.BaseKeyboard_Key_iconPreview); + codes = style.getIntArray(a, R.styleable.BaseKeyboard_Key_codes); + iconPreview = style.getDrawable(a, R.styleable.BaseKeyboard_Key_iconPreview); setDefaultBounds(iconPreview); - popupCharacters = a.getText(R.styleable.BaseKeyboard_Key_popupCharacters); - popupResId = a.getResourceId(R.styleable.BaseKeyboard_Key_popupKeyboard, 0); - repeatable = a.getBoolean(R.styleable.BaseKeyboard_Key_isRepeatable, false); - modifier = a.getBoolean(R.styleable.BaseKeyboard_Key_isModifier, false); - sticky = a.getBoolean(R.styleable.BaseKeyboard_Key_isSticky, false); - edgeFlags = a.getInt(R.styleable.BaseKeyboard_Key_keyEdgeFlags, 0); + popupCharacters = style.getText(a, R.styleable.BaseKeyboard_Key_popupCharacters); + popupResId = style.getResourceId(a, R.styleable.BaseKeyboard_Key_popupKeyboard, 0); + repeatable = style.getBoolean(a, R.styleable.BaseKeyboard_Key_isRepeatable, false); + modifier = style.getBoolean(a, R.styleable.BaseKeyboard_Key_isModifier, false); + sticky = style.getBoolean(a, R.styleable.BaseKeyboard_Key_isSticky, false); + edgeFlags = style.getFlag(a, R.styleable.BaseKeyboard_Key_keyEdgeFlags, 0); edgeFlags |= parent.rowEdgeFlags; - icon = a.getDrawable(R.styleable.BaseKeyboard_Key_keyIcon); + icon = style.getDrawable(a, R.styleable.BaseKeyboard_Key_keyIcon); setDefaultBounds(icon); - hintIcon = a.getDrawable(R.styleable.BaseKeyboard_Key_keyHintIcon); + hintIcon = style.getDrawable(a, R.styleable.BaseKeyboard_Key_keyHintIcon); setDefaultBounds(hintIcon); - manualTemporaryUpperCaseHintIcon = a.getDrawable( + manualTemporaryUpperCaseHintIcon = style.getDrawable(a, R.styleable.BaseKeyboard_Key_manualTemporaryUpperCaseHintIcon); setDefaultBounds(manualTemporaryUpperCaseHintIcon); - label = a.getText(R.styleable.BaseKeyboard_Key_keyLabel); - labelOption = a.getInt(R.styleable.BaseKeyboard_Key_keyLabelOption, 0); - manualTemporaryUpperCaseCode = a.getInt( + label = style.getText(a, R.styleable.BaseKeyboard_Key_keyLabel); + labelOption = style.getFlag(a, R.styleable.BaseKeyboard_Key_keyLabelOption, 0); + manualTemporaryUpperCaseCode = style.getInt(a, R.styleable.BaseKeyboard_Key_manualTemporaryUpperCaseCode, 0); - text = a.getText(R.styleable.BaseKeyboard_Key_keyOutputText); + text = style.getText(a, R.styleable.BaseKeyboard_Key_keyOutputText); if (codes == null && !TextUtils.isEmpty(label)) { codes = new int[] { label.charAt(0) }; @@ -366,28 +369,6 @@ public class BaseKeyboard { } } - private int[] parseCSV(String value) { - int count = 0; - int lastIndex = 0; - if (value.length() > 0) { - count++; - while ((lastIndex = value.indexOf(",", lastIndex + 1)) > 0) { - count++; - } - } - int[] values = new int[count]; - count = 0; - StringTokenizer st = new StringTokenizer(value, ","); - while (st.hasMoreTokens()) { - try { - values[count++] = Integer.parseInt(st.nextToken()); - } catch (NumberFormatException nfe) { - Log.e(TAG, "Error parsing keycodes " + value); - } - } - return values; - } - /** * Detects if a point falls inside this key. * @param x the x-coordinate of the point @@ -560,6 +541,10 @@ public class BaseKeyboard { mTotalHeight = y + mDefaultHeight; } + public KeyboardId getKeyboardId() { + return mId; + } + public List getKeys() { return mKeys; } @@ -688,14 +673,15 @@ public class BaseKeyboard { // TODO should be private protected BaseKeyboard.Key createKeyFromXml(Resources res, Row parent, int x, int y, - XmlResourceParser parser) { - return new BaseKeyboard.Key(res, parent, x, y, parser); + XmlResourceParser parser, KeyStyles keyStyles) { + return new BaseKeyboard.Key(res, parent, x, y, parser, keyStyles); } private void loadKeyboard(Context context, int xmlLayoutResId) { try { - BaseKeyboardParser parser = new BaseKeyboardParser(this, context.getResources()); - parser.parseKeyboard(context.getResources().getXml(xmlLayoutResId)); + final Resources res = context.getResources(); + BaseKeyboardParser parser = new BaseKeyboardParser(this, res); + parser.parseKeyboard(res.getXml(xmlLayoutResId)); // mTotalWidth is the width of this keyboard which is maximum width of row. mTotalWidth = parser.getMaxRowWidth(); mTotalHeight = parser.getTotalHeight(); diff --git a/java/src/com/android/inputmethod/latin/BaseKeyboardParser.java b/java/src/com/android/inputmethod/latin/BaseKeyboardParser.java index 1aee2fcef..ea209c515 100644 --- a/java/src/com/android/inputmethod/latin/BaseKeyboardParser.java +++ b/java/src/com/android/inputmethod/latin/BaseKeyboardParser.java @@ -83,27 +83,25 @@ import java.util.List; * >/default< * >/switch< * - * - * 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: + * You can declare Key style and specify styles within Key tags. + *
  *     >switch<
  *       >case colorScheme="white"<
- *         >declare-style name="shift-key" parentStyle="modifier-key"<
- *           >item name="keyIcon"<@drawable/sym_keyboard_shift">/item<
- *         >/declare-style<
+ *         >key-style styleName="shift-key" parentStyle="modifier-key"
+ *           keyIcon="@drawable/sym_keyboard_shift"
+ *         /<
  *       >/case<
  *       >case colorScheme="black"<
- *         >declare-style name="shift-key" parentStyle="modifier-key"<
- *           >item name="keyIcon"<@drawable/sym_bkeyboard_shift">/item<
- *         >/declare-style<
+ *         >key-style styleName="shift-key" parentStyle="modifier-key"
+ *           keyIcon="@drawable/sym_bkeyboard_shift"
+ *         /<
  *       >/case<
  *     >/switch<
  *     ...
- *     >Key include-style="shift-key" ... /<
+ *     >Key keyStyle="shift-key" ... /<
+ * 
*/ + public class BaseKeyboardParser { private static final String TAG = "BaseKeyboardParser"; private static final boolean DEBUG_TAG = false; @@ -118,6 +116,7 @@ public class BaseKeyboardParser { private static final String TAG_SWITCH = "switch"; private static final String TAG_CASE = "case"; private static final String TAG_DEFAULT = "default"; + private static final String TAG_KEY_STYLE = "key-style"; private final BaseKeyboard mKeyboard; private final Resources mResources; @@ -127,6 +126,7 @@ public class BaseKeyboardParser { private int mMaxRowWidth = 0; private int mTotalHeight = 0; private Row mCurrentRow = null; + private final KeyStyles mKeyStyles = new KeyStyles(); public BaseKeyboardParser(BaseKeyboard keyboard, Resources res) { mKeyboard = keyboard; @@ -192,6 +192,8 @@ public class BaseKeyboardParser { parseIncludeKeyboardContent(parser, keys); } else if (TAG_SWITCH.equals(tag)) { parseSwitchKeyboardContent(parser, keys); + } else if (TAG_KEY_STYLE.equals(tag)) { + parseKeyStyle(parser, keys); } else { throw new IllegalStartTag(parser, TAG_ROW); } @@ -205,6 +207,8 @@ public class BaseKeyboardParser { break; } else if (TAG_MERGE.equals(tag)) { break; + } else if (TAG_KEY_STYLE.equals(tag)) { + continue; } else { throw new IllegalEndTag(parser, TAG_ROW); } @@ -227,6 +231,8 @@ public class BaseKeyboardParser { parseIncludeRowContent(parser, row, keys); } else if (TAG_SWITCH.equals(tag)) { parseSwitchRowContent(parser, row, keys); + } else if (TAG_KEY_STYLE.equals(tag)) { + parseKeyStyle(parser, keys); } else { throw new IllegalStartTag(parser, TAG_KEY); } @@ -241,6 +247,8 @@ public class BaseKeyboardParser { break; } else if (TAG_MERGE.equals(tag)) { break; + } else if (TAG_KEY_STYLE.equals(tag)) { + continue; } else { throw new IllegalEndTag(parser, TAG_KEY); } @@ -253,7 +261,8 @@ public class BaseKeyboardParser { if (keys == null) { checkEndTag(TAG_KEY, parser); } else { - Key key = mKeyboard.createKeyFromXml(mResources, row, mCurrentX, mCurrentY, parser); + Key key = mKeyboard.createKeyFromXml(mResources, row, mCurrentX, mCurrentY, parser, + mKeyStyles); checkEndTag(TAG_KEY, parser); keys.add(key); if (key.codes[0] == BaseKeyboard.KEYCODE_SHIFT) @@ -439,6 +448,24 @@ public class BaseKeyboardParser { return true; } + private void parseKeyStyle(XmlResourceParser parser, List keys) + throws XmlPullParserException, IOException { + TypedArray a = mResources.obtainAttributes(Xml.asAttributeSet(parser), + R.styleable.BaseKeyboard_KeyStyle); + TypedArray keyAttrs = mResources.obtainAttributes(Xml.asAttributeSet(parser), + R.styleable.BaseKeyboard_Key); + try { + if (!a.hasValue(R.styleable.BaseKeyboard_KeyStyle_styleName)) + throw new ParseException("<" + TAG_KEY_STYLE + + "/> needs styleName attribute", parser); + if (keys != null) + mKeyStyles.parseKeyStyleAttributes(a, keyAttrs, parser); + } finally { + a.recycle(); + keyAttrs.recycle(); + } + } + private static void checkEndTag(String tag, XmlResourceParser parser) throws XmlPullParserException, IOException { if (parser.next() == XmlResourceParser.END_TAG && tag.equals(parser.getName())) @@ -486,7 +513,7 @@ public class BaseKeyboardParser { } @SuppressWarnings("serial") - private static class ParseException extends InflateException { + public static class ParseException extends InflateException { public ParseException(String msg, XmlResourceParser parser) { super(msg + " at line " + parser.getLineNumber()); } diff --git a/java/src/com/android/inputmethod/latin/KeyStyles.java b/java/src/com/android/inputmethod/latin/KeyStyles.java new file mode 100644 index 000000000..e53e351a3 --- /dev/null +++ b/java/src/com/android/inputmethod/latin/KeyStyles.java @@ -0,0 +1,237 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * 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.latin; + +import com.android.inputmethod.latin.BaseKeyboardParser.ParseException; + +import android.content.res.TypedArray; +import android.content.res.XmlResourceParser; +import android.graphics.drawable.Drawable; +import android.util.Log; +import android.util.TypedValue; + +import java.util.HashMap; +import java.util.StringTokenizer; + +public class KeyStyles { + private static final String TAG = "KeyStyles"; + + private final HashMap mStyles = + new HashMap(); + private static final KeyStyle EMPTY_KEY_STYLE = new EmptyKeyStyle(); + + public interface KeyStyle { + public int[] getIntArray(TypedArray a, int index); + public Drawable getDrawable(TypedArray a, int index); + public CharSequence getText(TypedArray a, int index); + public int getResourceId(TypedArray a, int index, int defaultValue); + public int getInt(TypedArray a, int index, int defaultValue); + public int getFlag(TypedArray a, int index, int defaultValue); + public boolean getBoolean(TypedArray a, int index, boolean defaultValue); + } + + public static class EmptyKeyStyle implements KeyStyle { + private EmptyKeyStyle() { + } + + public int[] getIntArray(TypedArray a, int index) { + return parseIntArray(a, index); + } + + public Drawable getDrawable(TypedArray a, int index) { + return a.getDrawable(index); + } + + public CharSequence getText(TypedArray a, int index) { + return a.getText(index); + } + + public int getResourceId(TypedArray a, int index, int defaultValue) { + return a.getResourceId(index, defaultValue); + } + + public int getInt(TypedArray a, int index, int defaultValue) { + return a.getInt(index, defaultValue); + } + + public int getFlag(TypedArray a, int index, int defaultValue) { + return a.getInt(index, defaultValue); + } + + public boolean getBoolean(TypedArray a, int index, boolean defaultValue) { + return a.getBoolean(index, defaultValue); + } + + protected static int[] parseIntArray(TypedArray a, int index) { + TypedValue v = new TypedValue(); + a.getValue(index, v); + if (v.type == TypedValue.TYPE_INT_DEC || v.type == TypedValue.TYPE_INT_HEX) { + return new int[] { v.data }; + } else if (v.type == TypedValue.TYPE_STRING) { + return parseCSV(v.string.toString()); + } else { + return null; + } + } + + private static int[] parseCSV(String value) { + int count = 0; + int lastIndex = 0; + if (value.length() > 0) { + count++; + while ((lastIndex = value.indexOf(",", lastIndex + 1)) > 0) { + count++; + } + } + int[] values = new int[count]; + count = 0; + StringTokenizer st = new StringTokenizer(value, ","); + while (st.hasMoreTokens()) { + try { + values[count++] = Integer.parseInt(st.nextToken()); + } catch (NumberFormatException nfe) { + Log.e(TAG, "Error parsing integer CSV " + value); + } + } + return values; + } + } + + public static class DeclaredKeyStyle extends EmptyKeyStyle { + private final HashMap mAttributes = new HashMap(); + + @Override + public int[] getIntArray(TypedArray a, int index) { + return a.hasValue(index) + ? super.getIntArray(a, index) : (int[])mAttributes.get(index); + } + + @Override + public Drawable getDrawable(TypedArray a, int index) { + return a.hasValue(index) + ? super.getDrawable(a, index) : (Drawable)mAttributes.get(index); + } + + @Override + public CharSequence getText(TypedArray a, int index) { + return a.hasValue(index) + ? super.getText(a, index) : (CharSequence)mAttributes.get(index); + } + + @Override + public int getResourceId(TypedArray a, int index, int defaultValue) { + final Integer value = (Integer)mAttributes.get(index); + return super.getResourceId(a, index, (value != null) ? value : defaultValue); + } + + @Override + public int getFlag(TypedArray a, int index, int defaultValue) { + final Integer value = (Integer)mAttributes.get(index); + return super.getFlag(a, index, defaultValue) | (value != null ? value : 0); + } + + @Override + public boolean getBoolean(TypedArray a, int index, boolean defaultValue) { + final Boolean value = (Boolean)mAttributes.get(index); + return super.getBoolean(a, index, (value != null) ? value : defaultValue); + } + + private DeclaredKeyStyle() { + super(); + } + + private void parseKeyStyleAttributes(TypedArray a) { + // TODO: Currently not all Key attributes can be declared as style. + readIntArray(a, R.styleable.BaseKeyboard_Key_codes); + readText(a, R.styleable.BaseKeyboard_Key_keyLabel); + readFlag(a, R.styleable.BaseKeyboard_Key_keyLabelOption); + readText(a, R.styleable.BaseKeyboard_Key_keyOutputText); + readDrawable(a, R.styleable.BaseKeyboard_Key_keyIcon); + readDrawable(a, R.styleable.BaseKeyboard_Key_iconPreview); + readDrawable(a, R.styleable.BaseKeyboard_Key_keyHintIcon); + readResourceId(a, R.styleable.BaseKeyboard_Key_popupKeyboard); + readBoolean(a, R.styleable.BaseKeyboard_Key_isModifier); + readBoolean(a, R.styleable.BaseKeyboard_Key_isSticky); + readBoolean(a, R.styleable.BaseKeyboard_Key_isRepeatable); + } + + private void readDrawable(TypedArray a, int index) { + if (a.hasValue(index)) + mAttributes.put(index, a.getDrawable(index)); + } + + private void readText(TypedArray a, int index) { + if (a.hasValue(index)) + mAttributes.put(index, a.getText(index)); + } + + private void readResourceId(TypedArray a, int index) { + if (a.hasValue(index)) + mAttributes.put(index, a.getResourceId(index, 0)); + } + + private void readFlag(TypedArray a, int index) { + final Integer value = (Integer)mAttributes.get(index); + if (a.hasValue(index)) + mAttributes.put(index, a.getInt(index, 0) | (value != null ? value : 0)); + } + + private void readBoolean(TypedArray a, int index) { + if (a.hasValue(index)) + mAttributes.put(index, a.getBoolean(index, false)); + } + + private void readIntArray(TypedArray a, int index) { + if (a.hasValue(index)) { + final int[] value = parseIntArray(a, index); + if (value != null) + mAttributes.put(index, value); + } + } + + private void addParent(DeclaredKeyStyle parentStyle) { + mAttributes.putAll(parentStyle.mAttributes); + } + } + + public void parseKeyStyleAttributes(TypedArray a, TypedArray keyAttrs, + XmlResourceParser parser) { + String styleName = a.getString(R.styleable.BaseKeyboard_KeyStyle_styleName); + if (mStyles.containsKey(styleName)) + throw new ParseException("duplicate key style declared: " + styleName, parser); + + final DeclaredKeyStyle style = new DeclaredKeyStyle(); + if (a.hasValue(R.styleable.BaseKeyboard_KeyStyle_parentStyle)) { + String parentStyle = a.getString( + R.styleable.BaseKeyboard_KeyStyle_parentStyle); + final DeclaredKeyStyle parent = mStyles.get(parentStyle); + if (parent == null) + throw new ParseException("Unknown parentStyle " + parent, parser); + style.addParent(parent); + } + style.parseKeyStyleAttributes(keyAttrs); + mStyles.put(styleName, style); + } + + public KeyStyle getKeyStyle(String styleName) { + return mStyles.get(styleName); + } + + public KeyStyle getEmptyKeyStyle() { + return EMPTY_KEY_STYLE; + } +} diff --git a/java/src/com/android/inputmethod/latin/LatinKeyboard.java b/java/src/com/android/inputmethod/latin/LatinKeyboard.java index 1242818d8..fc62053fe 100644 --- a/java/src/com/android/inputmethod/latin/LatinKeyboard.java +++ b/java/src/com/android/inputmethod/latin/LatinKeyboard.java @@ -127,8 +127,8 @@ public class LatinKeyboard extends BaseKeyboard { @Override protected Key createKeyFromXml(Resources res, Row parent, int x, int y, - XmlResourceParser parser) { - Key key = new LatinKey(res, parent, x, y, parser); + XmlResourceParser parser, KeyStyles keyStyles) { + Key key = new LatinKey(res, parent, x, y, parser, keyStyles); switch (key.codes[0]) { case LatinIME.KEYCODE_ENTER: mEnterKey = key; @@ -619,8 +619,8 @@ public class LatinKeyboard extends BaseKeyboard { private boolean mShiftLockEnabled; public LatinKey(Resources res, BaseKeyboard.Row parent, int x, int y, - XmlResourceParser parser) { - super(res, parent, x, y, parser); + XmlResourceParser parser, KeyStyles keyStyles) { + super(res, parent, x, y, parser, keyStyles); if (popupCharacters != null && popupCharacters.length() == 0) { // If there is a keyboard with no keys specified in popupCharacters popupResId = 0;