Home | History | Annotate | Download | only in internal
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.inputmethod.keyboard.internal;
     18 
     19 import android.content.res.TypedArray;
     20 import android.util.Log;
     21 import android.util.SparseArray;
     22 
     23 import com.android.inputmethod.latin.R;
     24 import com.android.inputmethod.latin.utils.XmlParseUtils;
     25 
     26 import org.xmlpull.v1.XmlPullParser;
     27 import org.xmlpull.v1.XmlPullParserException;
     28 
     29 import java.util.Arrays;
     30 import java.util.HashMap;
     31 
     32 import javax.annotation.Nonnull;
     33 import javax.annotation.Nullable;
     34 
     35 public final class KeyStylesSet {
     36     private static final String TAG = KeyStylesSet.class.getSimpleName();
     37     private static final boolean DEBUG = false;
     38 
     39     @Nonnull
     40     private final HashMap<String, KeyStyle> mStyles = new HashMap<>();
     41 
     42     @Nonnull
     43     private final KeyboardTextsSet mTextsSet;
     44     @Nonnull
     45     private final KeyStyle mEmptyKeyStyle;
     46     @Nonnull
     47     private static final String EMPTY_STYLE_NAME = "<empty>";
     48 
     49     public KeyStylesSet(@Nonnull final KeyboardTextsSet textsSet) {
     50         mTextsSet = textsSet;
     51         mEmptyKeyStyle = new EmptyKeyStyle(textsSet);
     52         mStyles.put(EMPTY_STYLE_NAME, mEmptyKeyStyle);
     53     }
     54 
     55     private static final class EmptyKeyStyle extends KeyStyle {
     56         EmptyKeyStyle(@Nonnull final KeyboardTextsSet textsSet) {
     57             super(textsSet);
     58         }
     59 
     60         @Override
     61         @Nullable
     62         public String[] getStringArray(final TypedArray a, final int index) {
     63             return parseStringArray(a, index);
     64         }
     65 
     66         @Override
     67         @Nullable
     68         public String getString(final TypedArray a, final int index) {
     69             return parseString(a, index);
     70         }
     71 
     72         @Override
     73         public int getInt(final TypedArray a, final int index, final int defaultValue) {
     74             return a.getInt(index, defaultValue);
     75         }
     76 
     77         @Override
     78         public int getFlags(final TypedArray a, final int index) {
     79             return a.getInt(index, 0);
     80         }
     81     }
     82 
     83     private static final class DeclaredKeyStyle extends KeyStyle {
     84         private final HashMap<String, KeyStyle> mStyles;
     85         private final String mParentStyleName;
     86         private final SparseArray<Object> mStyleAttributes = new SparseArray<>();
     87 
     88         public DeclaredKeyStyle(@Nonnull final String parentStyleName,
     89                 @Nonnull final KeyboardTextsSet textsSet,
     90                 @Nonnull final HashMap<String, KeyStyle> styles) {
     91             super(textsSet);
     92             mParentStyleName = parentStyleName;
     93             mStyles = styles;
     94         }
     95 
     96         @Override
     97         @Nullable
     98         public String[] getStringArray(final TypedArray a, final int index) {
     99             if (a.hasValue(index)) {
    100                 return parseStringArray(a, index);
    101             }
    102             final Object value = mStyleAttributes.get(index);
    103             if (value != null) {
    104                 final String[] array = (String[])value;
    105                 return Arrays.copyOf(array, array.length);
    106             }
    107             final KeyStyle parentStyle = mStyles.get(mParentStyleName);
    108             return parentStyle.getStringArray(a, index);
    109         }
    110 
    111         @Override
    112         @Nullable
    113         public String getString(final TypedArray a, final int index) {
    114             if (a.hasValue(index)) {
    115                 return parseString(a, index);
    116             }
    117             final Object value = mStyleAttributes.get(index);
    118             if (value != null) {
    119                 return (String)value;
    120             }
    121             final KeyStyle parentStyle = mStyles.get(mParentStyleName);
    122             return parentStyle.getString(a, index);
    123         }
    124 
    125         @Override
    126         public int getInt(final TypedArray a, final int index, final int defaultValue) {
    127             if (a.hasValue(index)) {
    128                 return a.getInt(index, defaultValue);
    129             }
    130             final Object value = mStyleAttributes.get(index);
    131             if (value != null) {
    132                 return (Integer)value;
    133             }
    134             final KeyStyle parentStyle = mStyles.get(mParentStyleName);
    135             return parentStyle.getInt(a, index, defaultValue);
    136         }
    137 
    138         @Override
    139         public int getFlags(final TypedArray a, final int index) {
    140             final int parentFlags = mStyles.get(mParentStyleName).getFlags(a, index);
    141             final Integer value = (Integer)mStyleAttributes.get(index);
    142             final int styleFlags = (value != null) ? value : 0;
    143             final int flags = a.getInt(index, 0);
    144             return flags | styleFlags | parentFlags;
    145         }
    146 
    147         public void readKeyAttributes(final TypedArray keyAttr) {
    148             // TODO: Currently not all Key attributes can be declared as style.
    149             readString(keyAttr, R.styleable.Keyboard_Key_altCode);
    150             readString(keyAttr, R.styleable.Keyboard_Key_keySpec);
    151             readString(keyAttr, R.styleable.Keyboard_Key_keyHintLabel);
    152             readStringArray(keyAttr, R.styleable.Keyboard_Key_moreKeys);
    153             readStringArray(keyAttr, R.styleable.Keyboard_Key_additionalMoreKeys);
    154             readFlags(keyAttr, R.styleable.Keyboard_Key_keyLabelFlags);
    155             readString(keyAttr, R.styleable.Keyboard_Key_keyIconDisabled);
    156             readInt(keyAttr, R.styleable.Keyboard_Key_maxMoreKeysColumn);
    157             readInt(keyAttr, R.styleable.Keyboard_Key_backgroundType);
    158             readFlags(keyAttr, R.styleable.Keyboard_Key_keyActionFlags);
    159         }
    160 
    161         private void readString(final TypedArray a, final int index) {
    162             if (a.hasValue(index)) {
    163                 mStyleAttributes.put(index, parseString(a, index));
    164             }
    165         }
    166 
    167         private void readInt(final TypedArray a, final int index) {
    168             if (a.hasValue(index)) {
    169                 mStyleAttributes.put(index, a.getInt(index, 0));
    170             }
    171         }
    172 
    173         private void readFlags(final TypedArray a, final int index) {
    174             if (a.hasValue(index)) {
    175                 final Integer value = (Integer)mStyleAttributes.get(index);
    176                 final int styleFlags = value != null ? value : 0;
    177                 mStyleAttributes.put(index, a.getInt(index, 0) | styleFlags);
    178             }
    179         }
    180 
    181         private void readStringArray(final TypedArray a, final int index) {
    182             if (a.hasValue(index)) {
    183                 mStyleAttributes.put(index, parseStringArray(a, index));
    184             }
    185         }
    186     }
    187 
    188     public void parseKeyStyleAttributes(final TypedArray keyStyleAttr, final TypedArray keyAttrs,
    189             final XmlPullParser parser) throws XmlPullParserException {
    190         final String styleName = keyStyleAttr.getString(R.styleable.Keyboard_KeyStyle_styleName);
    191         if (styleName == null) {
    192             throw new XmlParseUtils.ParseException(
    193                     KeyboardBuilder.TAG_KEY_STYLE + " has no styleName attribute", parser);
    194         }
    195         if (DEBUG) {
    196             Log.d(TAG, String.format("<%s styleName=%s />",
    197                     KeyboardBuilder.TAG_KEY_STYLE, styleName));
    198             if (mStyles.containsKey(styleName)) {
    199                 Log.d(TAG, KeyboardBuilder.TAG_KEY_STYLE + " " + styleName + " is overridden at "
    200                         + parser.getPositionDescription());
    201             }
    202         }
    203 
    204         final String parentStyleInAttr = keyStyleAttr.getString(
    205                 R.styleable.Keyboard_KeyStyle_parentStyle);
    206         if (parentStyleInAttr != null && !mStyles.containsKey(parentStyleInAttr)) {
    207             throw new XmlParseUtils.ParseException(
    208                     "Unknown parentStyle " + parentStyleInAttr, parser);
    209         }
    210         final String parentStyleName = (parentStyleInAttr == null) ? EMPTY_STYLE_NAME
    211                 : parentStyleInAttr;
    212         final DeclaredKeyStyle style = new DeclaredKeyStyle(parentStyleName, mTextsSet, mStyles);
    213         style.readKeyAttributes(keyAttrs);
    214         mStyles.put(styleName, style);
    215     }
    216 
    217     @Nonnull
    218     public KeyStyle getKeyStyle(final TypedArray keyAttr, final XmlPullParser parser)
    219             throws XmlParseUtils.ParseException {
    220         final String styleName = keyAttr.getString(R.styleable.Keyboard_Key_keyStyle);
    221         if (styleName == null) {
    222             return mEmptyKeyStyle;
    223         }
    224         final KeyStyle style = mStyles.get(styleName);
    225         if (style == null) {
    226             throw new XmlParseUtils.ParseException("Unknown key style: " + styleName, parser);
    227         }
    228         return style;
    229     }
    230 }
    231