/**
     * Create a key with the given top-left coordinate and extract its attributes from the XML
     * parser.
     *
     * @param res resources associated with the caller's context
     * @param parent the row that this key belongs to. The row must already be attached to a {@link
     *     Keyboard}.
     * @param x the x coordinate of the top-left
     * @param y the y coordinate of the top-left
     * @param parser the XML parser containing the attributes for this key
     */
    public Key(
        Context askContext,
        Resources res,
        Row parent,
        KeyboardDimens keyboardDimens,
        int x,
        int y,
        XmlResourceParser parser) {
      this(parent, keyboardDimens);
      final Resources askResources = askContext.getResources();
      SparseIntArray attributeIdMap = parent.parent.attributeIdMap;
      this.x = x;
      this.y = y;

      // setting up some defaults
      width = Math.min(keyboardDimens.getKeyMaxWidth(), parent.defaultWidth);
      height =
          KeyboardSupport.getKeyHeightFromHeightCode(
              keyboardDimens,
              parent.defaultHeightCode,
              askResources.getConfiguration().orientation);
      gap = parent.defaultHorizontalGap;
      codes = null;
      iconPreview = null;
      popupCharacters = null;
      popupResId = 0;
      repeatable = false;
      showPreview = true;
      dynamicEmblem = KEY_EMBLEM_NONE;
      modifier = false;
      sticky = false;

      // loading data from XML
      int[] remoteKeyboardLayoutStyleable = parent.parent.remoteKeyboardLayoutStyleable;
      TypedArray a =
          res.obtainAttributes(Xml.asAttributeSet(parser), remoteKeyboardLayoutStyleable);
      int n = a.getIndexCount();
      for (int i = 0; i < n; i++) {
        final int remoteIndex = a.getIndex(i);
        final int localAttrId = attributeIdMap.get(remoteKeyboardLayoutStyleable[remoteIndex]);
        setDataFromTypedArray(parent, keyboardDimens, askResources, a, remoteIndex, localAttrId);
      }
      a.recycle();
      this.x += gap;

      int[] remoteKeyboardKeyLayoutStyleable = parent.parent.remoteKeyboardKeyLayoutStyleable;
      a = res.obtainAttributes(Xml.asAttributeSet(parser), remoteKeyboardKeyLayoutStyleable);
      n = a.getIndexCount();
      for (int i = 0; i < n; i++) {
        final int remoteIndex = a.getIndex(i);
        final int localAttrId = attributeIdMap.get(remoteKeyboardKeyLayoutStyleable[remoteIndex]);
        setDataFromTypedArray(parent, keyboardDimens, askResources, a, remoteIndex, localAttrId);
      }
      externalResourcePopupLayout = popupResId != 0;
      if (codes == null && !TextUtils.isEmpty(label)) {
        codes = new int[] {label.charAt(0)};
      }
      a.recycle();
    }
 /** Create an empty key with no attributes. */
 public Key(Row parent, KeyboardDimens keyboardDimens) {
   row = parent;
   keyboard = parent.parent;
   height =
       KeyboardSupport.getKeyHeightFromHeightCode(
           keyboardDimens,
           parent.defaultHeightCode,
           row.parent.mASKContext.getResources().getConfiguration().orientation);
   width = Math.min(keyboardDimens.getKeyMaxWidth(), parent.defaultWidth);
   gap = parent.defaultHorizontalGap;
   edgeFlags = parent.rowEdgeFlags;
 }
  /**
   * Creates a keyboard from the given xml key layout file. Weeds out rows that have a keyboard mode
   * defined but don't match the specified mode.
   *
   * @param context the application or service context
   * @param xmlLayoutResId the resource file that contains the keyboard layout and keys.
   * @param modeId keyboard mode identifier
   */
  public Keyboard(Context askContext, Context context, int xmlLayoutResId, int modeId) {
    attributeIdMap =
        new SparseIntArray(
            R.styleable.KeyboardLayout.length
                + R.styleable.KeyboardLayout_Row.length
                + R.styleable.KeyboardLayout_Key.length);
    remoteKeyboardLayoutStyleable =
        KeyboardSupport.createBackwardCompatibleStyleable(
            R.styleable.KeyboardLayout, askContext, context, attributeIdMap, true);
    remoteKeyboardRowLayoutStyleable =
        KeyboardSupport.createBackwardCompatibleStyleable(
            R.styleable.KeyboardLayout_Row, askContext, context, attributeIdMap, true);
    remoteKeyboardKeyLayoutStyleable =
        KeyboardSupport.createBackwardCompatibleStyleable(
            R.styleable.KeyboardLayout_Key, askContext, context, attributeIdMap, true);

    mASKContext = askContext;
    mKeyboardContext = context;
    mLayoutResId = xmlLayoutResId;
    mKeyboardMode = modeId;

    mKeys = new ArrayList<Key>();
    mModifierKeys = new ArrayList<Key>();
  }
 private void setDataFromTypedArray(
     Row parent,
     KeyboardDimens keyboardDimens,
     Resources askResources,
     TypedArray a,
     int remoteIndex,
     int localAttrId) {
   try {
     switch (localAttrId) {
       case android.R.attr.keyWidth:
         width =
             getDimensionOrFraction(a, remoteIndex, keyboard.mDisplayWidth, parent.defaultWidth);
         width = Math.min(keyboardDimens.getKeyMaxWidth(), width);
         break;
       case android.R.attr.keyHeight:
         int heightCode = getKeyHeightCode(a, remoteIndex, parent.defaultHeightCode);
         height =
             KeyboardSupport.getKeyHeightFromHeightCode(
                 keyboardDimens, heightCode, askResources.getConfiguration().orientation);
         break;
       case android.R.attr.horizontalGap:
         gap =
             getDimensionOrFraction(
                 a, remoteIndex, keyboard.mDisplayWidth, parent.defaultHorizontalGap);
         break;
       case android.R.attr.codes:
         codes = KeyboardSupport.getKeyCodesFromTypedArray(a, remoteIndex);
         break;
       case android.R.attr.iconPreview:
         iconPreview = a.getDrawable(remoteIndex);
         KeyboardSupport.updateDrawableBounds(iconPreview);
         break;
       case android.R.attr.popupCharacters:
         popupCharacters = a.getText(remoteIndex);
         break;
       case android.R.attr.popupKeyboard:
         popupResId = a.getResourceId(remoteIndex, 0);
         break;
       case android.R.attr.isRepeatable:
         repeatable = a.getBoolean(remoteIndex, false);
         break;
       case R.attr.showPreview:
         showPreview = a.getBoolean(remoteIndex, true);
         break;
       case R.attr.keyDynamicEmblem:
         dynamicEmblem = a.getInt(remoteIndex, KEY_EMBLEM_NONE);
         break;
       case android.R.attr.isModifier:
         modifier = a.getBoolean(remoteIndex, false);
         break;
       case android.R.attr.isSticky:
         sticky = a.getBoolean(remoteIndex, false);
         break;
       case android.R.attr.keyEdgeFlags:
         edgeFlags = a.getInt(remoteIndex, 0);
         edgeFlags |= parent.rowEdgeFlags;
         break;
       case android.R.attr.keyIcon:
         icon = a.getDrawable(remoteIndex);
         KeyboardSupport.updateDrawableBounds(icon);
         break;
       case android.R.attr.keyLabel:
         label = a.getText(remoteIndex);
         break;
       case android.R.attr.keyOutputText:
         text = a.getText(remoteIndex);
         break;
     }
   } catch (Exception e) {
     Log.w(TAG, "Failed to load keyboard layout! ", e);
   }
 }