content: /*
   * 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.hx.curtain.drawer.nineoldandroids.animation;
  
  import android.content.Context;
  import android.content.res.TypedArray;
  import android.content.res.XmlResourceParser;
  import android.content.res.Resources.NotFoundException;
  import android.util.AttributeSet;
  import android.util.TypedValue;
  import android.util.Xml;
  import android.view.animation.AnimationUtils;
  import org.xmlpull.v1.XmlPullParser;
  import org.xmlpull.v1.XmlPullParserException;
  
  import java.io.IOException;
  import java.util.ArrayList;
  
  /**
   * This class is used to instantiate animator XML files into Animator objects.
   * <p>
   * For performance reasons, inflation relies heavily on pre-processing of
   * XML files that is done at build time. Therefore, it is not currently possible
   * to use this inflater with an XmlPullParser over a plain XML file at runtime;
   * it only works with an XmlPullParser returned from a compiled resource (R.
   * <em>something</em> file.)
   */
  public class AnimatorInflater {
      private static final int[] AnimatorSet = new int[] {
          /* 0 */ android.R.attr.ordering,
      };
      private static final int AnimatorSet_ordering = 0;
  
      private static final int[] PropertyAnimator = new int[] {
          /* 0 */ android.R.attr.propertyName,
      };
      private static final int PropertyAnimator_propertyName = 0;
  
      private static final int[] Animator = new int[] {
          /* 0 */ android.R.attr.interpolator,
          /* 1 */ android.R.attr.duration,
          /* 2 */ android.R.attr.startOffset,
          /* 3 */ android.R.attr.repeatCount,
          /* 4 */ android.R.attr.repeatMode,
          /* 5 */ android.R.attr.valueFrom,
          /* 6 */ android.R.attr.valueTo,
          /* 7 */ android.R.attr.valueType,
      };
      private static final int Animator_interpolator = 0;
      private static final int Animator_duration = 1;
      private static final int Animator_startOffset = 2;
      private static final int Animator_repeatCount = 3;
      private static final int Animator_repeatMode = 4;
      private static final int Animator_valueFrom = 5;
      private static final int Animator_valueTo = 6;
      private static final int Animator_valueType = 7;
  
      /**
       * These flags are used when parsing AnimatorSet objects
       */
      private static final int TOGETHER = 0;
      //private static final int SEQUENTIALLY = 1;
  
      /**
       * Enum values used in XML attributes to indicate the value for mValueType
       */
      private static final int VALUE_TYPE_FLOAT       = 0;
      //private static final int VALUE_TYPE_INT         = 1;
      //private static final int VALUE_TYPE_COLOR       = 4;
      //private static final int VALUE_TYPE_CUSTOM      = 5;
  
      /**
       * Loads an {@link Animator} object from a resource
       *
       * @param context Application context used to access resources
       * @param id The resource id of the animation to load
       * @return The animator object reference by the specified id
       * @throws NotFoundException when the animation cannot be loaded
       */
      public static Animator loadAnimator(Context context, int id)
              throws NotFoundException {
  
          XmlResourceParser parser = null;
          try {
              parser = context.getResources().getAnimation(id);
              return createAnimatorFromXml(context, parser);
          } catch (XmlPullParserException ex) {
              NotFoundException rnf =
                      new NotFoundException("Can't load animation resource ID #0x" +
                      Integer.toHexString(id));
              rnf.initCause(ex);
              throw rnf;
          } catch (IOException ex) {
              NotFoundException rnf =
                      new NotFoundException("Can't load animation resource ID #0x" +
                      Integer.toHexString(id));
              rnf.initCause(ex);
              throw rnf;
          } finally {
              if (parser != null) parser.close();
          }
      }
  
      private static Animator createAnimatorFromXml(Context c, XmlPullParser parser)
              throws XmlPullParserException, IOException {
  
          return createAnimatorFromXml(c, parser, Xml.asAttributeSet(parser), null, 0);
      }
  
      private static Animator createAnimatorFromXml(Context c, XmlPullParser parser,
              AttributeSet attrs, AnimatorSet parent, int sequenceOrdering)
              throws XmlPullParserException, IOException {
  
          Animator anim = null;
          ArrayList<Animator> childAnims = null;
  
          // Make sure we are on a start tag.
          int type;
          int depth = parser.getDepth();
  
          while (((type=parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth)
                 && type != XmlPullParser.END_DOCUMENT) {
  
              if (type != XmlPullParser.START_TAG) {
                  continue;
              }
  
              String  name = parser.getName();
  
              if (name.equals("objectAnimator")) {
                  anim = loadObjectAnimator(c, attrs);
              } else if (name.equals("animator")) {
                  anim = loadAnimator(c, attrs, null);
              } else if (name.equals("set")) {
                  anim = new AnimatorSet();
                  TypedArray a = c.obtainStyledAttributes(attrs,
                          /*com.android.internal.R.styleable.*/AnimatorSet);
  
                  TypedValue orderingValue = new TypedValue();
                  a.getValue(/*com.android.internal.R.styleable.*/AnimatorSet_ordering, orderingValue);
                  int ordering = orderingValue.type == TypedValue.TYPE_INT_DEC ? orderingValue.data : TOGETHER;
  
                  createAnimatorFromXml(c, parser, attrs, (AnimatorSet) anim,  ordering);
                  a.recycle();
              } else {
                  throw new RuntimeException("Unknown animator name: " + parser.getName());
              }
  
              if (parent != null) {
                  if (childAnims == null) {
                      childAnims = new ArrayList<Animator>();
                  }
                  childAnims.add(anim);
              }
          }
          if (parent != null && childAnims != null) {
              Animator[] animsArray = new Animator[childAnims.size()];
              int index = 0;
              for (Animator a : childAnims) {
                  animsArray[index++] = a;
              }
              if (sequenceOrdering == TOGETHER) {
                  parent.playTogether(animsArray);
              } else {
                  parent.playSequentially(animsArray);
              }
          }
  
          return anim;
  
      }
  
      private static ObjectAnimator loadObjectAnimator(Context context, AttributeSet attrs)
              throws NotFoundException {
  
          ObjectAnimator anim = new ObjectAnimator();
  
          loadAnimator(context, attrs, anim);
  
          TypedArray a =
                  context.obtainStyledAttributes(attrs, /*com.android.internal.R.styleable.*/PropertyAnimator);
  
          String propertyName = a.getString(/*com.android.internal.R.styleable.*/PropertyAnimator_propertyName);
  
          anim.setPropertyName(propertyName);
  
          a.recycle();
  
          return anim;
      }
  
      /**
       * Creates a new animation whose parameters come from the specified context and
       * attributes set.
       *
       * @param context the application environment
       * @param attrs the set of attributes holding the animation parameters
       */
      private static ValueAnimator loadAnimator(Context context, AttributeSet attrs, ValueAnimator anim)
              throws NotFoundException {
  
          TypedArray a =
                  context.obtainStyledAttributes(attrs, /*com.android.internal.R.styleable.*/Animator);
  
          long duration = a.getInt(/*com.android.internal.R.styleable.*/Animator_duration, 0);
  
          long startDelay = a.getInt(/*com.android.internal.R.styleable.*/Animator_startOffset, 0);
  
          int valueType = a.getInt(/*com.android.internal.R.styleable.*/Animator_valueType,
                  VALUE_TYPE_FLOAT);
  
          if (anim == null) {
              anim = new ValueAnimator();
          }
          //TypeEvaluator evaluator = null;
  
          int valueFromIndex = /*com.android.internal.R.styleable.*/Animator_valueFrom;
          int valueToIndex = /*com.android.internal.R.styleable.*/Animator_valueTo;
  
          boolean getFloats = (valueType == VALUE_TYPE_FLOAT);
  
          TypedValue tvFrom = a.peekValue(valueFromIndex);
          boolean hasFrom = (tvFrom != null);
          int fromType = hasFrom ? tvFrom.type : 0;
          TypedValue tvTo = a.peekValue(valueToIndex);
          boolean hasTo = (tvTo != null);
          int toType = hasTo ? tvTo.type : 0;
  
          if ((hasFrom && (fromType >= TypedValue.TYPE_FIRST_COLOR_INT) &&
                  (fromType <= TypedValue.TYPE_LAST_COLOR_INT)) ||
              (hasTo && (toType >= TypedValue.TYPE_FIRST_COLOR_INT) &&
                  (toType <= TypedValue.TYPE_LAST_COLOR_INT))) {
              // special case for colors: ignore valueType and get ints
              getFloats = false;
              anim.setEvaluator(new ArgbEvaluator());
          }
  
          if (getFloats) {
              float valueFrom;
              float valueTo;
              if (hasFrom) {
                  if (fromType == TypedValue.TYPE_DIMENSION) {
                      valueFrom = a.getDimension(valueFromIndex, 0f);
                  } else {
                      valueFrom = a.getFloat(valueFromIndex, 0f);
                  }
                  if (hasTo) {
                      if (toType == TypedValue.TYPE_DIMENSION) {
                          valueTo = a.getDimension(valueToIndex, 0f);
                      } else {
                          valueTo = a.getFloat(valueToIndex, 0f);
                      }
                      anim.setFloatValues(valueFrom, valueTo);
                  } else {
                      anim.setFloatValues(valueFrom);
                  }
              } else {
                  if (toType == TypedValue.TYPE_DIMENSION) {
                      valueTo = a.getDimension(valueToIndex, 0f);
                  } else {
                      valueTo = a.getFloat(valueToIndex, 0f);
                  }
                  anim.setFloatValues(valueTo);
              }
          } else {
              int valueFrom;
              int valueTo;
              if (hasFrom) {
                  if (fromType == TypedValue.TYPE_DIMENSION) {
                      valueFrom = (int) a.getDimension(valueFromIndex, 0f);
                  } else if ((fromType >= TypedValue.TYPE_FIRST_COLOR_INT) &&
                          (fromType <= TypedValue.TYPE_LAST_COLOR_INT)) {
                      valueFrom = a.getColor(valueFromIndex, 0);
                  } else {
                      valueFrom = a.getInt(valueFromIndex, 0);
                  }
                  if (hasTo) {
                      if (toType == TypedValue.TYPE_DIMENSION) {
                          valueTo = (int) a.getDimension(valueToIndex, 0f);
                      } else if ((toType >= TypedValue.TYPE_FIRST_COLOR_INT) &&
                              (toType <= TypedValue.TYPE_LAST_COLOR_INT)) {
                          valueTo = a.getColor(valueToIndex, 0);
                      } else {
                          valueTo = a.getInt(valueToIndex, 0);
                      }
                      anim.setIntValues(valueFrom, valueTo);
                  } else {
                      anim.setIntValues(valueFrom);
                  }
              } else {
                  if (hasTo) {
                      if (toType == TypedValue.TYPE_DIMENSION) {
                          valueTo = (int) a.getDimension(valueToIndex, 0f);
                      } else if ((toType >= TypedValue.TYPE_FIRST_COLOR_INT) &&
                          (toType <= TypedValue.TYPE_LAST_COLOR_INT)) {
                          valueTo = a.getColor(valueToIndex, 0);
                      } else {
                          valueTo = a.getInt(valueToIndex, 0);
                      }
                      anim.setIntValues(valueTo);
                  }
              }
          }
  
          anim.setDuration(duration);
          anim.setStartDelay(startDelay);
  
          if (a.hasValue(/*com.android.internal.R.styleable.*/Animator_repeatCount)) {
              anim.setRepeatCount(
                      a.getInt(/*com.android.internal.R.styleable.*/Animator_repeatCount, 0));
          }
          if (a.hasValue(/*com.android.internal.R.styleable.*/Animator_repeatMode)) {
              anim.setRepeatMode(
                      a.getInt(/*com.android.internal.R.styleable.*/Animator_repeatMode,
                              ValueAnimator.RESTART));
          }
          //if (evaluator != null) {
          //    anim.setEvaluator(evaluator);
          //}
  
          final int resID =
                  a.getResourceId(/*com.android.internal.R.styleable.*/Animator_interpolator, 0);
          if (resID > 0) {
              anim.setInterpolator(AnimationUtils.loadInterpolator(context, resID));
          }
          a.recycle();
  
          return anim;
      }
  }