diff options
Diffstat (limited to 'src/com/android/inputmethod/pinyin/XmlKeyboardLoader.java')
-rw-r--r-- | src/com/android/inputmethod/pinyin/XmlKeyboardLoader.java | 835 |
1 files changed, 835 insertions, 0 deletions
diff --git a/src/com/android/inputmethod/pinyin/XmlKeyboardLoader.java b/src/com/android/inputmethod/pinyin/XmlKeyboardLoader.java new file mode 100644 index 0000000..fd192a3 --- /dev/null +++ b/src/com/android/inputmethod/pinyin/XmlKeyboardLoader.java @@ -0,0 +1,835 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * 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.pinyin; + +import com.android.inputmethod.pinyin.SoftKeyboard.KeyRow; + +import android.content.Context; +import android.content.res.Resources; +import android.content.res.XmlResourceParser; +import android.graphics.drawable.Drawable; + +import java.io.IOException; +import java.util.regex.Pattern; + +import org.xmlpull.v1.XmlPullParserException; + +/** + * Class used to load a soft keyboard or a soft keyboard template from xml + * files. + */ +public class XmlKeyboardLoader { + /** + * The tag used to define an xml-based soft keyboard template. + */ + private static final String XMLTAG_SKB_TEMPLATE = "skb_template"; + + /** + * The tag used to indicate the soft key type which is defined inside the + * {@link #XMLTAG_SKB_TEMPLATE} element in the xml file. file. + */ + private static final String XMLTAG_KEYTYPE = "key_type"; + + /** + * The tag used to define a default key icon for enter/delete/space keys. It + * is defined inside the {@link #XMLTAG_SKB_TEMPLATE} element in the xml + * file. + */ + private static final String XMLTAG_KEYICON = "key_icon"; + + /** + * Attribute tag of the left and right margin for a key. A key's width + * should be larger than double of this value. Defined inside + * {@link #XMLTAG_SKB_TEMPLATE} and {@link #XMLTAG_KEYBOARD}. + */ + private static final String XMLATTR_KEY_XMARGIN = "key_xmargin"; + + /** + * Attribute tag of the top and bottom margin for a key. A key's height + * should be larger than double of this value. Defined inside + * {@link #XMLTAG_SKB_TEMPLATE} and {@link #XMLTAG_KEYBOARD}. + */ + private static final String XMLATTR_KEY_YMARGIN = "key_ymargin"; + + /** + * Attribute tag of the keyboard background image. Defined inside + * {@link #XMLTAG_SKB_TEMPLATE} and {@link #XMLTAG_KEYBOARD}. + */ + private static final String XMLATTR_SKB_BG = "skb_bg"; + + /** + * Attribute tag of the balloon background image for key press. Defined + * inside {@link #XMLTAG_SKB_TEMPLATE} and {@link #XMLTAG_KEYBOARD}. + */ + private static final String XMLATTR_BALLOON_BG = "balloon_bg"; + + /** + * Attribute tag of the popup balloon background image for key press or + * popup mini keyboard. Defined inside {@link #XMLTAG_SKB_TEMPLATE} and + * {@link #XMLTAG_KEYBOARD}. + */ + private static final String XMLATTR_POPUP_BG = "popup_bg"; + + /** + * Attribute tag of the color to draw key label. Defined inside + * {@link #XMLTAG_SKB_TEMPLATE} and {@link #XMLTAG_KEYTYPE}. + */ + private static final String XMLATTR_COLOR = "color"; + + /** + * Attribute tag of the color to draw key's highlighted label. Defined + * inside {@link #XMLTAG_SKB_TEMPLATE} and {@link #XMLTAG_KEYTYPE}. + */ + private static final String XMLATTR_COLOR_HIGHLIGHT = "color_highlight"; + + /** + * Attribute tag of the color to draw key's label in the popup balloon. + * Defined inside {@link #XMLTAG_SKB_TEMPLATE} and {@link #XMLTAG_KEYTYPE}. + */ + private static final String XMLATTR_COLOR_BALLOON = "color_balloon"; + + /** + * Attribute tag of the id of {@link #XMLTAG_KEYTYPE} and + * {@link #XMLTAG_KEY}. Key types and keys defined in a soft keyboard + * template should have id, because a soft keyboard needs the id to refer to + * these default definitions. If a key defined in {@link #XMLTAG_KEYBOARD} + * does not id, that means the key is newly defined; if it has id (and only + * has id), the id is used to find the default definition from the soft + * keyboard template. + */ + private static final String XMLATTR_ID = "id"; + + /** + * Attribute tag of the key background for a specified key type. Defined + * inside {@link #XMLTAG_KEYTYPE}. + */ + private static final String XMLATTR_KEYTYPE_BG = "bg"; + + /** + * Attribute tag of the key high-light background for a specified key type. + * Defined inside {@link #XMLTAG_KEYTYPE}. + */ + private static final String XMLATTR_KEYTYPE_HLBG = "hlbg"; + + /** + * Attribute tag of the starting x-position of an element. It can be defined + * in {@link #XMLTAG_ROW} and {@link #XMLTAG_KEY} in {XMLTAG_SKB_TEMPLATE}. + * If not defined, 0 will be used. For a key defined in + * {@link #XMLTAG_KEYBOARD}, it always use its previous keys information to + * calculate its own position. + */ + private static final String XMLATTR_START_POS_X = "start_pos_x"; + + /** + * Attribute tag of the starting y-position of an element. It can be defined + * in {@link #XMLTAG_ROW} and {@link #XMLTAG_KEY} in {XMLTAG_SKB_TEMPLATE}. + * If not defined, 0 will be used. For a key defined in + * {@link #XMLTAG_KEYBOARD}, it always use its previous keys information to + * calculate its own position. + */ + private static final String XMLATTR_START_POS_Y = "start_pos_y"; + + /** + * Attribute tag of a row's id. Defined {@link #XMLTAG_ROW}. If not defined, + * -1 will be used. Rows with id -1 will be enabled always, rows with same + * row id will be enabled when the id is the same to the activated id of the + * soft keyboard. + */ + private static final String XMLATTR_ROW_ID = "row_id"; + + /** The tag used to indicate the keyboard element in the xml file. */ + private static final String XMLTAG_KEYBOARD = "keyboard"; + + /** The tag used to indicate the row element in the xml file. */ + private static final String XMLTAG_ROW = "row"; + + /** The tag used to indicate key-array element in the xml file. */ + private static final String XMLTAG_KEYS = "keys"; + + /** + * The tag used to indicate a key element in the xml file. If the element is + * defined in a soft keyboard template, it should have an id. If it is + * defined in a soft keyboard, id is not required. + */ + private static final String XMLTAG_KEY = "key"; + + /** The tag used to indicate a key's toggle element in the xml file. */ + private static final String XMLTAG_TOGGLE_STATE = "toggle_state"; + + /** + * Attribute tag of the toggle state id for toggle key. Defined inside + * {@link #XMLTAG_TOGGLE_STATE} + */ + private static final String XMLATTR_TOGGLE_STATE_ID = "state_id"; + + /** Attribute tag of key template for the soft keyboard. */ + private static final String XMLATTR_SKB_TEMPLATE = "skb_template"; + + /** + * Attribute tag used to indicate whether this soft keyboard needs to be + * cached in memory for future use. {@link #DEFAULT_SKB_CACHE_FLAG} + * specifies the default value. + */ + private static final String XMLATTR_SKB_CACHE_FLAG = "skb_cache_flag"; + + /** + * Attribute tag used to indicate whether this soft keyboard is sticky. A + * sticky soft keyboard will keep the current layout unless user makes a + * switch explicitly. A none sticky soft keyboard will automatically goes + * back to the previous keyboard after click a none-function key. + * {@link #DEFAULT_SKB_STICKY_FLAG} specifies the default value. + */ + private static final String XMLATTR_SKB_STICKY_FLAG = "skb_sticky_flag"; + + /** Attribute tag to indicate whether it is a QWERTY soft keyboard. */ + private static final String XMLATTR_QWERTY = "qwerty"; + + /** + * When the soft keyboard is a QWERTY one, this attribute tag to get the + * information that whether it is defined in upper case. + */ + private static final String XMLATTR_QWERTY_UPPERCASE = "qwerty_uppercase"; + + /** Attribute tag of key type. */ + private static final String XMLATTR_KEY_TYPE = "key_type"; + + /** Attribute tag of key width. */ + private static final String XMLATTR_KEY_WIDTH = "width"; + + /** Attribute tag of key height. */ + private static final String XMLATTR_KEY_HEIGHT = "height"; + + /** Attribute tag of the key's repeating ability. */ + private static final String XMLATTR_KEY_REPEAT = "repeat"; + + /** Attribute tag of the key's behavior for balloon. */ + private static final String XMLATTR_KEY_BALLOON = "balloon"; + + /** Attribute tag of the key splitter in a key array. */ + private static final String XMLATTR_KEY_SPLITTER = "splitter"; + + /** Attribute tag of the key labels in a key array. */ + private static final String XMLATTR_KEY_LABELS = "labels"; + + /** Attribute tag of the key codes in a key array. */ + private static final String XMLATTR_KEY_CODES = "codes"; + + /** Attribute tag of the key label in a key. */ + private static final String XMLATTR_KEY_LABEL = "label"; + + /** Attribute tag of the key code in a key. */ + private static final String XMLATTR_KEY_CODE = "code"; + + /** Attribute tag of the key icon in a key. */ + private static final String XMLATTR_KEY_ICON = "icon"; + + /** Attribute tag of the key's popup icon in a key. */ + private static final String XMLATTR_KEY_ICON_POPUP = "icon_popup"; + + /** The id for a mini popup soft keyboard. */ + private static final String XMLATTR_KEY_POPUP_SKBID = "popup_skb"; + + private static boolean DEFAULT_SKB_CACHE_FLAG = true; + + private static boolean DEFAULT_SKB_STICKY_FLAG = true; + + /** + * The key type id for invalid key type. It is also used to generate next + * valid key type id by adding 1. + */ + private static final int KEYTYPE_ID_LAST = -1; + + private Context mContext; + + private Resources mResources; + + /** The event type in parsing the xml file. */ + private int mXmlEventType; + + /** + * The current soft keyboard template used by the current soft keyboard + * under loading. + **/ + private SkbTemplate mSkbTemplate; + + /** The x position for the next key. */ + float mKeyXPos; + + /** The y position for the next key. */ + float mKeyYPos; + + /** The width of the keyboard to load. */ + int mSkbWidth; + + /** The height of the keyboard to load. */ + int mSkbHeight; + + /** Key margin in x-way. */ + float mKeyXMargin = 0; + + /** Key margin in y-way. */ + float mKeyYMargin = 0; + + /** + * Used to indicate whether next event has been fetched during processing + * the the current event. + */ + boolean mNextEventFetched = false; + + String mAttrTmp; + + class KeyCommonAttributes { + XmlResourceParser mXrp; + int keyType; + float keyWidth; + float keyHeight; + boolean repeat; + boolean balloon; + + KeyCommonAttributes(XmlResourceParser xrp) { + mXrp = xrp; + balloon = true; + } + + // Make sure the default object is not null. + boolean getAttributes(KeyCommonAttributes defAttr) { + keyType = getInteger(mXrp, XMLATTR_KEY_TYPE, defAttr.keyType); + keyWidth = getFloat(mXrp, XMLATTR_KEY_WIDTH, defAttr.keyWidth); + keyHeight = getFloat(mXrp, XMLATTR_KEY_HEIGHT, defAttr.keyHeight); + repeat = getBoolean(mXrp, XMLATTR_KEY_REPEAT, defAttr.repeat); + balloon = getBoolean(mXrp, XMLATTR_KEY_BALLOON, defAttr.balloon); + if (keyType < 0 || keyWidth <= 0 || keyHeight <= 0) { + return false; + } + return true; + } + } + + public XmlKeyboardLoader(Context context) { + mContext = context; + mResources = mContext.getResources(); + } + + public SkbTemplate loadSkbTemplate(int resourceId) { + if (null == mContext || 0 == resourceId) { + return null; + } + Resources r = mResources; + XmlResourceParser xrp = r.getXml(resourceId); + + KeyCommonAttributes attrDef = new KeyCommonAttributes(xrp); + KeyCommonAttributes attrKey = new KeyCommonAttributes(xrp); + + mSkbTemplate = new SkbTemplate(resourceId); + int lastKeyTypeId = KEYTYPE_ID_LAST; + int globalColor = 0; + int globalColorHl = 0; + int globalColorBalloon = 0; + try { + mXmlEventType = xrp.next(); + while (mXmlEventType != XmlResourceParser.END_DOCUMENT) { + mNextEventFetched = false; + if (mXmlEventType == XmlResourceParser.START_TAG) { + String attribute = xrp.getName(); + if (XMLTAG_SKB_TEMPLATE.compareTo(attribute) == 0) { + Drawable skbBg = getDrawable(xrp, XMLATTR_SKB_BG, null); + Drawable balloonBg = getDrawable(xrp, + XMLATTR_BALLOON_BG, null); + Drawable popupBg = getDrawable(xrp, XMLATTR_POPUP_BG, + null); + if (null == skbBg || null == balloonBg + || null == popupBg) { + return null; + } + mSkbTemplate.setBackgrounds(skbBg, balloonBg, popupBg); + + float xMargin = getFloat(xrp, XMLATTR_KEY_XMARGIN, 0); + float yMargin = getFloat(xrp, XMLATTR_KEY_YMARGIN, 0); + mSkbTemplate.setMargins(xMargin, yMargin); + + // Get default global colors. + globalColor = getColor(xrp, XMLATTR_COLOR, 0); + globalColorHl = getColor(xrp, XMLATTR_COLOR_HIGHLIGHT, + 0xffffffff); + globalColorBalloon = getColor(xrp, + XMLATTR_COLOR_BALLOON, 0xffffffff); + } else if (XMLTAG_KEYTYPE.compareTo(attribute) == 0) { + int id = getInteger(xrp, XMLATTR_ID, KEYTYPE_ID_LAST); + Drawable bg = getDrawable(xrp, XMLATTR_KEYTYPE_BG, null); + Drawable hlBg = getDrawable(xrp, XMLATTR_KEYTYPE_HLBG, + null); + int color = getColor(xrp, XMLATTR_COLOR, globalColor); + int colorHl = getColor(xrp, XMLATTR_COLOR_HIGHLIGHT, + globalColorHl); + int colorBalloon = getColor(xrp, XMLATTR_COLOR_BALLOON, + globalColorBalloon); + if (id != lastKeyTypeId + 1) { + return null; + } + SoftKeyType keyType = mSkbTemplate.createKeyType(id, + bg, hlBg); + keyType.setColors(color, colorHl, colorBalloon); + if (!mSkbTemplate.addKeyType(keyType)) { + return null; + } + lastKeyTypeId = id; + } else if (XMLTAG_KEYICON.compareTo(attribute) == 0) { + int keyCode = getInteger(xrp, XMLATTR_KEY_CODE, 0); + Drawable icon = getDrawable(xrp, XMLATTR_KEY_ICON, null); + Drawable iconPopup = getDrawable(xrp, + XMLATTR_KEY_ICON_POPUP, null); + if (null != icon && null != iconPopup) { + mSkbTemplate.addDefaultKeyIcons(keyCode, icon, + iconPopup); + } + } else if (XMLTAG_KEY.compareTo(attribute) == 0) { + int keyId = this.getInteger(xrp, XMLATTR_ID, -1); + if (-1 == keyId) return null; + + if (!attrKey.getAttributes(attrDef)) { + return null; + } + + // Update the key position for the key. + mKeyXPos = getFloat(xrp, XMLATTR_START_POS_X, 0); + mKeyYPos = getFloat(xrp, XMLATTR_START_POS_Y, 0); + + SoftKey softKey = getSoftKey(xrp, attrKey); + if (null == softKey) return null; + mSkbTemplate.addDefaultKey(keyId, softKey); + } + } + // Get the next tag. + if (!mNextEventFetched) mXmlEventType = xrp.next(); + } + xrp.close(); + return mSkbTemplate; + } catch (XmlPullParserException e) { + // Log.e(TAG, "Ill-formatted keyboard template resource file"); + } catch (IOException e) { + // Log.e(TAG, "Unable to keyboard template resource file"); + } + return null; + } + + public SoftKeyboard loadKeyboard(int resourceId, int skbWidth, int skbHeight) { + if (null == mContext) return null; + Resources r = mResources; + SkbPool skbPool = SkbPool.getInstance(); + XmlResourceParser xrp = mContext.getResources().getXml(resourceId); + mSkbTemplate = null; + SoftKeyboard softKeyboard = null; + Drawable skbBg; + Drawable popupBg; + Drawable balloonBg; + SoftKey softKey = null; + + KeyCommonAttributes attrDef = new KeyCommonAttributes(xrp); + KeyCommonAttributes attrSkb = new KeyCommonAttributes(xrp); + KeyCommonAttributes attrRow = new KeyCommonAttributes(xrp); + KeyCommonAttributes attrKeys = new KeyCommonAttributes(xrp); + KeyCommonAttributes attrKey = new KeyCommonAttributes(xrp); + + mKeyXPos = 0; + mKeyYPos = 0; + mSkbWidth = skbWidth; + mSkbHeight = skbHeight; + + try { + mKeyXMargin = 0; + mKeyYMargin = 0; + mXmlEventType = xrp.next(); + while (mXmlEventType != XmlResourceParser.END_DOCUMENT) { + mNextEventFetched = false; + if (mXmlEventType == XmlResourceParser.START_TAG) { + String attr = xrp.getName(); + // 1. Is it the root element, "keyboard"? + if (XMLTAG_KEYBOARD.compareTo(attr) == 0) { + // 1.1 Get the keyboard template id. + int skbTemplateId = xrp.getAttributeResourceValue(null, + XMLATTR_SKB_TEMPLATE, 0); + + // 1.2 Try to get the template from pool. If it is not + // in, the pool will try to load it. + mSkbTemplate = skbPool.getSkbTemplate(skbTemplateId, + mContext); + + if (null == mSkbTemplate + || !attrSkb.getAttributes(attrDef)) { + return null; + } + + boolean cacheFlag = getBoolean(xrp, + XMLATTR_SKB_CACHE_FLAG, DEFAULT_SKB_CACHE_FLAG); + boolean stickyFlag = getBoolean(xrp, + XMLATTR_SKB_STICKY_FLAG, + DEFAULT_SKB_STICKY_FLAG); + boolean isQwerty = getBoolean(xrp, XMLATTR_QWERTY, + false); + boolean isQwertyUpperCase = getBoolean(xrp, + XMLATTR_QWERTY_UPPERCASE, false); + + softKeyboard = new SoftKeyboard(resourceId, + mSkbTemplate, mSkbWidth, mSkbHeight); + softKeyboard.setFlags(cacheFlag, stickyFlag, isQwerty, + isQwertyUpperCase); + + mKeyXMargin = getFloat(xrp, XMLATTR_KEY_XMARGIN, + mSkbTemplate.getXMargin()); + mKeyYMargin = getFloat(xrp, XMLATTR_KEY_YMARGIN, + mSkbTemplate.getYMargin()); + skbBg = getDrawable(xrp, XMLATTR_SKB_BG, null); + popupBg = getDrawable(xrp, XMLATTR_POPUP_BG, null); + balloonBg = getDrawable(xrp, XMLATTR_BALLOON_BG, null); + if (null != skbBg) { + softKeyboard.setSkbBackground(skbBg); + } + if (null != popupBg) { + softKeyboard.setPopupBackground(popupBg); + } + if (null != balloonBg) { + softKeyboard.setKeyBalloonBackground(balloonBg); + } + softKeyboard.setKeyMargins(mKeyXMargin, mKeyYMargin); + } else if (XMLTAG_ROW.compareTo(attr) == 0) { + if (!attrRow.getAttributes(attrSkb)) { + return null; + } + // Get the starting positions for the row. + mKeyXPos = getFloat(xrp, XMLATTR_START_POS_X, 0); + mKeyYPos = getFloat(xrp, XMLATTR_START_POS_Y, mKeyYPos); + int rowId = getInteger(xrp, XMLATTR_ROW_ID, + KeyRow.ALWAYS_SHOW_ROW_ID); + softKeyboard.beginNewRow(rowId, mKeyYPos); + } else if (XMLTAG_KEYS.compareTo(attr) == 0) { + if (null == softKeyboard) return null; + if (!attrKeys.getAttributes(attrRow)) { + return null; + } + + String splitter = xrp.getAttributeValue(null, + XMLATTR_KEY_SPLITTER); + splitter = Pattern.quote(splitter); + String labels = xrp.getAttributeValue(null, + XMLATTR_KEY_LABELS); + String codes = xrp.getAttributeValue(null, + XMLATTR_KEY_CODES); + if (null == splitter || null == labels) { + return null; + } + String labelArr[] = labels.split(splitter); + String codeArr[] = null; + if (null != codes) { + codeArr = codes.split(splitter); + if (labelArr.length != codeArr.length) { + return null; + } + } + + for (int i = 0; i < labelArr.length; i++) { + softKey = new SoftKey(); + int keyCode = 0; + if (null != codeArr) { + keyCode = Integer.valueOf(codeArr[i]); + } + softKey.setKeyAttribute(keyCode, labelArr[i], + attrKeys.repeat, attrKeys.balloon); + + softKey.setKeyType(mSkbTemplate + .getKeyType(attrKeys.keyType), null, null); + + float left, right, top, bottom; + left = mKeyXPos; + + right = left + attrKeys.keyWidth; + top = mKeyYPos; + bottom = top + attrKeys.keyHeight; + + if (right - left < 2 * mKeyXMargin) return null; + if (bottom - top < 2 * mKeyYMargin) return null; + + softKey.setKeyDimensions(left, top, right, bottom); + softKeyboard.addSoftKey(softKey); + mKeyXPos = right; + if ((int) mKeyXPos * mSkbWidth > mSkbWidth) { + return null; + } + } + } else if (XMLTAG_KEY.compareTo(attr) == 0) { + if (null == softKeyboard) { + return null; + } + if (!attrKey.getAttributes(attrRow)) { + return null; + } + + int keyId = this.getInteger(xrp, XMLATTR_ID, -1); + if (keyId >= 0) { + softKey = mSkbTemplate.getDefaultKey(keyId); + } else { + softKey = getSoftKey(xrp, attrKey); + } + if (null == softKey) return null; + + // Update the position for next key. + mKeyXPos = softKey.mRightF; + if ((int) mKeyXPos * mSkbWidth > mSkbWidth) { + return null; + } + // If the current xml event type becomes a starting tag, + // it indicates that we have parsed too much to get + // toggling states, and we started a new row. In this + // case, the row starting position information should + // be updated. + if (mXmlEventType == XmlResourceParser.START_TAG) { + attr = xrp.getName(); + if (XMLTAG_ROW.compareTo(attr) == 0) { + mKeyYPos += attrRow.keyHeight; + if ((int) mKeyYPos * mSkbHeight > mSkbHeight) { + return null; + } + } + } + softKeyboard.addSoftKey(softKey); + } + } else if (mXmlEventType == XmlResourceParser.END_TAG) { + String attr = xrp.getName(); + if (XMLTAG_ROW.compareTo(attr) == 0) { + mKeyYPos += attrRow.keyHeight; + if ((int) mKeyYPos * mSkbHeight > mSkbHeight) { + return null; + } + } + } + + // Get the next tag. + if (!mNextEventFetched) mXmlEventType = xrp.next(); + } + xrp.close(); + softKeyboard.setSkbCoreSize(mSkbWidth, mSkbHeight); + return softKeyboard; + } catch (XmlPullParserException e) { + // Log.e(TAG, "Ill-formatted keybaord resource file"); + } catch (IOException e) { + // Log.e(TAG, "Unable to read keyboard resource file"); + } + return null; + } + + // Caller makes sure xrp and r are valid. + private SoftKey getSoftKey(XmlResourceParser xrp, + KeyCommonAttributes attrKey) throws XmlPullParserException, + IOException { + int keyCode = getInteger(xrp, XMLATTR_KEY_CODE, 0); + String keyLabel = getString(xrp, XMLATTR_KEY_LABEL, null); + Drawable keyIcon = getDrawable(xrp, XMLATTR_KEY_ICON, null); + Drawable keyIconPopup = getDrawable(xrp, XMLATTR_KEY_ICON_POPUP, null); + int popupSkbId = xrp.getAttributeResourceValue(null, + XMLATTR_KEY_POPUP_SKBID, 0); + + if (null == keyLabel && null == keyIcon) { + keyIcon = mSkbTemplate.getDefaultKeyIcon(keyCode); + keyIconPopup = mSkbTemplate.getDefaultKeyIconPopup(keyCode); + if (null == keyIcon || null == keyIconPopup) return null; + } + + // Dimension information must been initialized before + // getting toggle state, because mKeyYPos may be changed + // to next row when trying to get toggle state. + float left, right, top, bottom; + left = mKeyXPos; + right = left + attrKey.keyWidth; + top = mKeyYPos; + bottom = top + attrKey.keyHeight; + + if (right - left < 2 * mKeyXMargin) return null; + if (bottom - top < 2 * mKeyYMargin) return null; + + // Try to find if the next tag is + // {@link #XMLTAG_TOGGLE_STATE_OF_KEY}, if yes, try to + // create a toggle key. + boolean toggleKey = false; + mXmlEventType = xrp.next(); + mNextEventFetched = true; + + SoftKey softKey; + if (mXmlEventType == XmlResourceParser.START_TAG) { + mAttrTmp = xrp.getName(); + if (mAttrTmp.compareTo(XMLTAG_TOGGLE_STATE) == 0) { + toggleKey = true; + } + } + if (toggleKey) { + softKey = new SoftKeyToggle(); + if (!((SoftKeyToggle) softKey).setToggleStates(getToggleStates( + attrKey, (SoftKeyToggle) softKey, keyCode))) { + return null; + } + } else { + softKey = new SoftKey(); + } + + // Set the normal state + softKey.setKeyAttribute(keyCode, keyLabel, attrKey.repeat, + attrKey.balloon); + softKey.setPopupSkbId(popupSkbId); + softKey.setKeyType(mSkbTemplate.getKeyType(attrKey.keyType), keyIcon, + keyIconPopup); + + softKey.setKeyDimensions(left, top, right, bottom); + return softKey; + } + + private SoftKeyToggle.ToggleState getToggleStates( + KeyCommonAttributes attrKey, SoftKeyToggle softKey, int defKeyCode) + throws XmlPullParserException, IOException { + XmlResourceParser xrp = attrKey.mXrp; + int stateId = getInteger(xrp, XMLATTR_TOGGLE_STATE_ID, 0); + if (0 == stateId) return null; + + String keyLabel = getString(xrp, XMLATTR_KEY_LABEL, null); + int keyTypeId = getInteger(xrp, XMLATTR_KEY_TYPE, KEYTYPE_ID_LAST); + int keyCode; + if (null == keyLabel) { + keyCode = getInteger(xrp, XMLATTR_KEY_CODE, defKeyCode); + } else { + keyCode = getInteger(xrp, XMLATTR_KEY_CODE, 0); + } + Drawable icon = getDrawable(xrp, XMLATTR_KEY_ICON, null); + Drawable iconPopup = getDrawable(xrp, XMLATTR_KEY_ICON_POPUP, null); + if (null == icon && null == keyLabel) { + return null; + } + SoftKeyToggle.ToggleState rootState = softKey.createToggleState(); + rootState.setStateId(stateId); + rootState.mKeyType = null; + if (KEYTYPE_ID_LAST != keyTypeId) { + rootState.mKeyType = mSkbTemplate.getKeyType(keyTypeId); + } + rootState.mKeyCode = keyCode; + rootState.mKeyIcon = icon; + rootState.mKeyIconPopup = iconPopup; + rootState.mKeyLabel = keyLabel; + + boolean repeat = getBoolean(xrp, XMLATTR_KEY_REPEAT, attrKey.repeat); + boolean balloon = getBoolean(xrp, XMLATTR_KEY_BALLOON, attrKey.balloon); + rootState.setStateFlags(repeat, balloon); + + rootState.mNextState = null; + + // If there is another toggle state. + mXmlEventType = xrp.next(); + while (mXmlEventType != XmlResourceParser.START_TAG + && mXmlEventType != XmlResourceParser.END_DOCUMENT) { + mXmlEventType = xrp.next(); + } + if (mXmlEventType == XmlResourceParser.START_TAG) { + String attr = xrp.getName(); + if (attr.compareTo(XMLTAG_TOGGLE_STATE) == 0) { + SoftKeyToggle.ToggleState nextState = getToggleStates(attrKey, + softKey, defKeyCode); + if (null == nextState) return null; + rootState.mNextState = nextState; + } + } + + return rootState; + } + + private int getInteger(XmlResourceParser xrp, String name, int defValue) { + int resId = xrp.getAttributeResourceValue(null, name, 0); + String s; + if (resId == 0) { + s = xrp.getAttributeValue(null, name); + if (null == s) return defValue; + try { + int ret = Integer.valueOf(s); + return ret; + } catch (NumberFormatException e) { + return defValue; + } + } else { + return Integer.parseInt(mContext.getResources().getString(resId)); + } + } + + private int getColor(XmlResourceParser xrp, String name, int defValue) { + int resId = xrp.getAttributeResourceValue(null, name, 0); + String s; + if (resId == 0) { + s = xrp.getAttributeValue(null, name); + if (null == s) return defValue; + try { + int ret = Integer.valueOf(s); + return ret; + } catch (NumberFormatException e) { + return defValue; + } + } else { + return mContext.getResources().getColor(resId); + } + } + + private String getString(XmlResourceParser xrp, String name, String defValue) { + int resId = xrp.getAttributeResourceValue(null, name, 0); + if (resId == 0) { + return xrp.getAttributeValue(null, name); + } else { + return mContext.getResources().getString(resId); + } + } + + private float getFloat(XmlResourceParser xrp, String name, float defValue) { + int resId = xrp.getAttributeResourceValue(null, name, 0); + if (resId == 0) { + String s = xrp.getAttributeValue(null, name); + if (null == s) return defValue; + try { + float ret; + if (s.endsWith("%p")) { + ret = Float.parseFloat(s.substring(0, s.length() - 2)) / 100; + } else { + ret = Float.parseFloat(s); + } + return ret; + } catch (NumberFormatException e) { + return defValue; + } + } else { + return mContext.getResources().getDimension(resId); + } + } + + private boolean getBoolean(XmlResourceParser xrp, String name, + boolean defValue) { + String s = xrp.getAttributeValue(null, name); + if (null == s) return defValue; + try { + boolean ret = Boolean.parseBoolean(s); + return ret; + } catch (NumberFormatException e) { + return defValue; + } + } + + private Drawable getDrawable(XmlResourceParser xrp, String name, + Drawable defValue) { + int resId = xrp.getAttributeResourceValue(null, name, 0); + if (0 == resId) return defValue; + return mResources.getDrawable(resId); + } +} |