package org.itsnat.droid.impl.xmlinflater.animator.classtree;
import android.animation.ArgbEvaluator;
import android.animation.TypeEvaluator;
import android.animation.ValueAnimator;
import android.content.Context;
import org.itsnat.droid.ItsNatDroidException;
import org.itsnat.droid.impl.dom.DOMAttr;
import org.itsnat.droid.impl.dom.DOMAttributeMap;
import org.itsnat.droid.impl.dom.DOMElement;
import org.itsnat.droid.impl.util.MapSmart;
import org.itsnat.droid.impl.util.NamespaceUtil;
import org.itsnat.droid.impl.xmlinflater.XMLInflaterContext;
import org.itsnat.droid.impl.xmlinflater.XMLInflaterRegistry;
import org.itsnat.droid.impl.xmlinflater.XMLInflaterResource;
import org.itsnat.droid.impl.xmlinflater.animator.AttrAnimatorContext;
import org.itsnat.droid.impl.xmlinflater.animator.ClassDescAnimatorMgr;
import org.itsnat.droid.impl.xmlinflater.animator.attr.AttrDescAnimator_animation_Animator_repeatCount;
import org.itsnat.droid.impl.xmlinflater.shared.attr.AttrDescReflecMethodNameSingle;
/**
* Created by Jose on 15/10/2015.
*/
public class ClassDescAnimatorValue extends ClassDescAnimatorBased<ValueAnimator>
{
public static final MapSmart<String,Integer> repeatModeMap = MapSmart.<String,Integer>create(2);
static
{
repeatModeMap.put("restart", ValueAnimator.RESTART); // En el tutorial oficial aparece "repeat", pero no es correcto
repeatModeMap.put("reverse", ValueAnimator.REVERSE);
}
public ClassDescAnimatorValue(ClassDescAnimatorMgr classMgr, ClassDescAnimator parentClass)
{
super(classMgr, "animator", parentClass);
}
@Override
public Class<ValueAnimator> getDeclaredClass()
{
return ValueAnimator.class;
}
@Override
protected ValueAnimator createResourceNative(Context ctx)
{
return new ValueAnimator();
}
@Override
public boolean isAttributeIgnored(ValueAnimator resource, String namespaceURI, String name)
{
if (super.isAttributeIgnored(resource,namespaceURI,name))
return true;
return NamespaceUtil.XMLNS_ANDROID.equals(namespaceURI) && ("valueType".equals(name) || "valueFrom".equals(name) || "valueTo".equals(name));
}
@Override
public void fillResourceAttributes(ValueAnimator animator, DOMElement domElement, AttrAnimatorContext attrCtx)
{
fillAnimatorValueConstructionAttributes(animator, domElement, attrCtx);
super.fillResourceAttributes(animator, domElement,attrCtx);
}
protected void fillAnimatorValueConstructionAttributes(ValueAnimator animator, DOMElement domElement, AttrAnimatorContext attrCtx)
{
/*
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;
*/
// http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.0.3_r1/android/animation/AnimatorInflater.java
DOMAttributeMap domAttributeMap = domElement.getDOMAttributeMap();
ValueAnimator valueAnimator = (ValueAnimator)animator;
int valueType; // En el caso de colores no se usa, se ignora
DOMAttr valueTypeAttr = findAttribute(NamespaceUtil.XMLNS_ANDROID, "valueType",domAttributeMap);
if (valueTypeAttr != null)
{
String value = valueTypeAttr.getValue();
if ("floatType".equals(value)) valueType = 0; // VALUE_TYPE_FLOAT;
else if ("intType".equals(value)) valueType = 1; // VALUE_TYPE_INT
else throw new ItsNatDroidException("Value of attribute valueType unrecognized: " + value);
}
else valueType = 0; // VALUE_TYPE_FLOAT
XMLInflaterResource xmlInflaterAnimator = attrCtx.getXMLInflaterResource();
XMLInflaterRegistry xmlInflaterRegistry = xmlInflaterAnimator.getInflatedXMLResource().getXMLInflaterRegistry();
boolean hasFrom = false;
boolean isDimensionFrom = false;
DOMAttr valueFromAttr = findAttribute(NamespaceUtil.XMLNS_ANDROID, "valueFrom",domAttributeMap);
if (valueFromAttr != null)
{
hasFrom = true;
if (xmlInflaterRegistry.isColor(valueFromAttr.getResourceDesc()))
{
valueType = 2; // Nos inventamos que el valor 2 es un posible VALUE_TYPE_COLOR
}
else
{
isDimensionFrom = xmlInflaterRegistry.isDimension(valueFromAttr.getResourceDesc());
}
}
boolean hasTo = false;
boolean isDimensionTo = false;
DOMAttr valueToAttr = findAttribute(NamespaceUtil.XMLNS_ANDROID, "valueTo",domAttributeMap);
if (valueToAttr != null)
{
hasTo = true;
if (xmlInflaterRegistry.isColor(valueToAttr.getResourceDesc()))
{
if (hasFrom && valueType != 2) throw new ItsNatDroidException("Attribute value of valueFrom has a different type than valueTo color value");
valueType = 2; // Nos inventamos que el valor 2 es un posible VALUE_TYPE_COLOR
}
else
{
isDimensionTo = xmlInflaterRegistry.isDimension(valueToAttr.getResourceDesc());
}
}
if (hasFrom || hasTo)
{
XMLInflaterContext xmlInflaterContext = attrCtx.getXMLInflaterContext();
TypeEvaluator evaluator = null;
if (valueType == 2) // Color
{
evaluator = new ArgbEvaluator(); // es mejor basarse en 5.0 http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/5.0.2_r1/android/animation/AnimatorInflater.java que en 4.0 que parece que tiene un bug (el setEvaluator DEBE llamarse DESPUES de definir el from y to )
int valueFrom = hasFrom ? xmlInflaterRegistry.getColor(valueFromAttr.getResourceDesc(), xmlInflaterContext) : 0;
int valueTo = hasTo ? xmlInflaterRegistry.getColor(valueToAttr.getResourceDesc(), xmlInflaterContext) : 0;
if (hasFrom)
{
if (hasTo) valueAnimator.setIntValues(valueFrom,valueTo);
else valueAnimator.setIntValues(valueFrom);
}
else
{
valueAnimator.setIntValues(valueTo);
}
}
else if (valueType == 1) // Integer
{
int valueFrom = 0;
int valueTo = 0;
if (hasFrom)
{
valueFrom = isDimensionFrom ? xmlInflaterRegistry.getDimensionIntFloor(valueFromAttr.getResourceDesc(), xmlInflaterContext) : xmlInflaterRegistry.getInteger(valueFromAttr.getResourceDesc(), xmlInflaterContext);
}
if (hasTo)
{
valueTo = isDimensionTo ? xmlInflaterRegistry.getDimensionIntFloor(valueToAttr.getResourceDesc(), xmlInflaterContext) : xmlInflaterRegistry.getInteger(valueToAttr.getResourceDesc(), xmlInflaterContext);
}
if (hasFrom)
{
if (hasTo) valueAnimator.setIntValues(valueFrom,valueTo);
else valueAnimator.setIntValues(valueFrom);
}
else
{
valueAnimator.setIntValues(valueTo);
}
}
else if (valueType == 0) // Float
{
float valueFrom = 0f;
float valueTo = 0f;
if (hasFrom)
{
valueFrom = isDimensionFrom ? xmlInflaterRegistry.getDimensionFloat(valueFromAttr.getResourceDesc(), xmlInflaterContext) : xmlInflaterRegistry.getFloat(valueFromAttr.getResourceDesc(), xmlInflaterContext);
}
if (hasTo)
{
valueTo = isDimensionTo ? xmlInflaterRegistry.getDimensionFloat(valueToAttr.getResourceDesc(), xmlInflaterContext) : xmlInflaterRegistry.getFloat(valueToAttr.getResourceDesc(), xmlInflaterContext);
}
if (hasFrom)
{
if (hasTo) valueAnimator.setFloatValues(valueFrom, valueTo);
else valueAnimator.setFloatValues(valueFrom);
}
else
{
valueAnimator.setFloatValues(valueTo);
}
}
if (evaluator != null)
valueAnimator.setEvaluator(evaluator);
}
}
@SuppressWarnings("unchecked")
protected void init()
{
super.init();
addAttrDescAN(new AttrDescAnimator_animation_Animator_repeatCount(this)); // Se puede llamar independientemente de valueFrom y valueTo
addAttrDescAN(new AttrDescReflecMethodNameSingle(this, "repeatMode", int.class, repeatModeMap, "restart")); // "
}
}