LatinIME/java/src/com/android/inputmethod/keyboard/internal/KeyStylesSet.java

231 lines
8.8 KiB
Java

/*
* Copyright (C) 2010 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.keyboard.internal;
import android.content.res.TypedArray;
import android.util.Log;
import android.util.SparseArray;
import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.utils.XmlParseUtils;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import java.util.Arrays;
import java.util.HashMap;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public final class KeyStylesSet {
private static final String TAG = KeyStylesSet.class.getSimpleName();
private static final boolean DEBUG = false;
@Nonnull
private final HashMap<String, KeyStyle> mStyles = new HashMap<>();
@Nonnull
private final KeyboardTextsSet mTextsSet;
@Nonnull
private final KeyStyle mEmptyKeyStyle;
@Nonnull
private static final String EMPTY_STYLE_NAME = "<empty>";
public KeyStylesSet(@Nonnull final KeyboardTextsSet textsSet) {
mTextsSet = textsSet;
mEmptyKeyStyle = new EmptyKeyStyle(textsSet);
mStyles.put(EMPTY_STYLE_NAME, mEmptyKeyStyle);
}
private static final class EmptyKeyStyle extends KeyStyle {
EmptyKeyStyle(@Nonnull final KeyboardTextsSet textsSet) {
super(textsSet);
}
@Override
@Nullable
public String[] getStringArray(final TypedArray a, final int index) {
return parseStringArray(a, index);
}
@Override
@Nullable
public String getString(final TypedArray a, final int index) {
return parseString(a, index);
}
@Override
public int getInt(final TypedArray a, final int index, final int defaultValue) {
return a.getInt(index, defaultValue);
}
@Override
public int getFlags(final TypedArray a, final int index) {
return a.getInt(index, 0);
}
}
private static final class DeclaredKeyStyle extends KeyStyle {
private final HashMap<String, KeyStyle> mStyles;
private final String mParentStyleName;
private final SparseArray<Object> mStyleAttributes = new SparseArray<>();
public DeclaredKeyStyle(@Nonnull final String parentStyleName,
@Nonnull final KeyboardTextsSet textsSet,
@Nonnull final HashMap<String, KeyStyle> styles) {
super(textsSet);
mParentStyleName = parentStyleName;
mStyles = styles;
}
@Override
@Nullable
public String[] getStringArray(final TypedArray a, final int index) {
if (a.hasValue(index)) {
return parseStringArray(a, index);
}
final Object value = mStyleAttributes.get(index);
if (value != null) {
final String[] array = (String[])value;
return Arrays.copyOf(array, array.length);
}
final KeyStyle parentStyle = mStyles.get(mParentStyleName);
return parentStyle.getStringArray(a, index);
}
@Override
@Nullable
public String getString(final TypedArray a, final int index) {
if (a.hasValue(index)) {
return parseString(a, index);
}
final Object value = mStyleAttributes.get(index);
if (value != null) {
return (String)value;
}
final KeyStyle parentStyle = mStyles.get(mParentStyleName);
return parentStyle.getString(a, index);
}
@Override
public int getInt(final TypedArray a, final int index, final int defaultValue) {
if (a.hasValue(index)) {
return a.getInt(index, defaultValue);
}
final Object value = mStyleAttributes.get(index);
if (value != null) {
return (Integer)value;
}
final KeyStyle parentStyle = mStyles.get(mParentStyleName);
return parentStyle.getInt(a, index, defaultValue);
}
@Override
public int getFlags(final TypedArray a, final int index) {
final int parentFlags = mStyles.get(mParentStyleName).getFlags(a, index);
final Integer value = (Integer)mStyleAttributes.get(index);
final int styleFlags = (value != null) ? value : 0;
final int flags = a.getInt(index, 0);
return flags | styleFlags | parentFlags;
}
public void readKeyAttributes(final TypedArray keyAttr) {
// TODO: Currently not all Key attributes can be declared as style.
readString(keyAttr, R.styleable.Keyboard_Key_altCode);
readString(keyAttr, R.styleable.Keyboard_Key_keySpec);
readString(keyAttr, R.styleable.Keyboard_Key_keyHintLabel);
readStringArray(keyAttr, R.styleable.Keyboard_Key_moreKeys);
readStringArray(keyAttr, R.styleable.Keyboard_Key_additionalMoreKeys);
readFlags(keyAttr, R.styleable.Keyboard_Key_keyLabelFlags);
readString(keyAttr, R.styleable.Keyboard_Key_keyIconDisabled);
readInt(keyAttr, R.styleable.Keyboard_Key_maxMoreKeysColumn);
readInt(keyAttr, R.styleable.Keyboard_Key_backgroundType);
readFlags(keyAttr, R.styleable.Keyboard_Key_keyActionFlags);
}
private void readString(final TypedArray a, final int index) {
if (a.hasValue(index)) {
mStyleAttributes.put(index, parseString(a, index));
}
}
private void readInt(final TypedArray a, final int index) {
if (a.hasValue(index)) {
mStyleAttributes.put(index, a.getInt(index, 0));
}
}
private void readFlags(final TypedArray a, final int index) {
if (a.hasValue(index)) {
final Integer value = (Integer)mStyleAttributes.get(index);
final int styleFlags = value != null ? value : 0;
mStyleAttributes.put(index, a.getInt(index, 0) | styleFlags);
}
}
private void readStringArray(final TypedArray a, final int index) {
if (a.hasValue(index)) {
mStyleAttributes.put(index, parseStringArray(a, index));
}
}
}
public void parseKeyStyleAttributes(final TypedArray keyStyleAttr, final TypedArray keyAttrs,
final XmlPullParser parser) throws XmlPullParserException {
final String styleName = keyStyleAttr.getString(R.styleable.Keyboard_KeyStyle_styleName);
if (styleName == null) {
throw new XmlParseUtils.ParseException(
KeyboardBuilder.TAG_KEY_STYLE + " has no styleName attribute", parser);
}
if (DEBUG) {
Log.d(TAG, String.format("<%s styleName=%s />",
KeyboardBuilder.TAG_KEY_STYLE, styleName));
if (mStyles.containsKey(styleName)) {
Log.d(TAG, KeyboardBuilder.TAG_KEY_STYLE + " " + styleName + " is overridden at "
+ parser.getPositionDescription());
}
}
final String parentStyleInAttr = keyStyleAttr.getString(
R.styleable.Keyboard_KeyStyle_parentStyle);
if (parentStyleInAttr != null && !mStyles.containsKey(parentStyleInAttr)) {
throw new XmlParseUtils.ParseException(
"Unknown parentStyle " + parentStyleInAttr, parser);
}
final String parentStyleName = (parentStyleInAttr == null) ? EMPTY_STYLE_NAME
: parentStyleInAttr;
final DeclaredKeyStyle style = new DeclaredKeyStyle(parentStyleName, mTextsSet, mStyles);
style.readKeyAttributes(keyAttrs);
mStyles.put(styleName, style);
}
@Nonnull
public KeyStyle getKeyStyle(final TypedArray keyAttr, final XmlPullParser parser)
throws XmlParseUtils.ParseException {
final String styleName = keyAttr.getString(R.styleable.Keyboard_Key_keyStyle);
if (styleName == null) {
return mEmptyKeyStyle;
}
final KeyStyle style = mStyles.get(styleName);
if (style == null) {
throw new XmlParseUtils.ParseException("Unknown key style: " + styleName, parser);
}
return style;
}
}