blob: fd192a3edf43f6b250905eb4a2dc5ccb43d250ba [file] [log] [blame]
/*
* 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);
}
}