blob: be7809147d5a040f9c59af4893c30450066daef4 [file] [log] [blame]
/*
* Copyright (C) 2016 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 android.graphics.drawable;
import com.android.ide.common.rendering.api.LayoutLog;
import com.android.layoutlib.bridge.Bridge;
import com.android.layoutlib.bridge.impl.DelegateManager;
import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.graphics.animation.NativeInterpolatorFactory_Delegate;
import android.graphics.drawable.AnimatedVectorDrawable.VectorDrawableAnimatorRT;
import android.graphics.drawable.VectorDrawable_Delegate.VFullPath_Delegate;
import android.graphics.drawable.VectorDrawable_Delegate.VGroup_Delegate;
import android.graphics.drawable.VectorDrawable_Delegate.VNativeObject;
import android.graphics.drawable.VectorDrawable_Delegate.VPathRenderer_Delegate;
import java.util.ArrayList;
import java.util.function.Consumer;
/**
* Delegate used to provide new implementation of a select few methods of {@link
* AnimatedVectorDrawable}
* <p>
* Through the layoutlib_create tool, the original methods of AnimatedVectorDrawable have been
* replaced by calls to methods of the same name in this delegate class.
*/
@SuppressWarnings("unused")
public class AnimatedVectorDrawable_Delegate {
private static DelegateManager<AnimatorSetHolder> sAnimatorSets = new
DelegateManager<>(AnimatorSetHolder.class);
private static DelegateManager<PropertySetter> sHolders = new
DelegateManager<>(PropertySetter.class);
@LayoutlibDelegate
/*package*/ static long nCreateAnimatorSet() {
return sAnimatorSets.addNewDelegate(new AnimatorSetHolder());
}
@LayoutlibDelegate
/*package*/ static void nSetVectorDrawableTarget(long animatorPtr, long vectorDrawablePtr) {
// TODO: implement
}
@LayoutlibDelegate
/*package*/ static void nAddAnimator(long setPtr, long propertyValuesHolder,
long nativeInterpolator, long startDelay, long duration, int repeatCount,
int repeatMode) {
PropertySetter holder = sHolders.getDelegate(propertyValuesHolder);
if (holder == null || holder.getValues() == null) {
return;
}
ObjectAnimator animator = new ObjectAnimator();
animator.setValues(holder.getValues());
animator.setInterpolator(
NativeInterpolatorFactory_Delegate.getDelegate(nativeInterpolator));
animator.setStartDelay(startDelay);
animator.setDuration(duration);
animator.setRepeatCount(repeatCount);
animator.setRepeatMode(repeatMode);
animator.setTarget(holder);
animator.setPropertyName(holder.getValues().getPropertyName());
AnimatorSetHolder set = sAnimatorSets.getDelegate(setPtr);
assert set != null;
set.addAnimator(animator);
}
@LayoutlibDelegate
/*package*/ static long nCreateGroupPropertyHolder(long nativePtr, int propertyId,
float startValue, float endValue) {
VGroup_Delegate group = VNativeObject.getDelegate(nativePtr);
Consumer<Float> setter = group.getPropertySetter(propertyId);
return sHolders.addNewDelegate(FloatPropertySetter.of(setter, startValue,
endValue));
}
@LayoutlibDelegate
/*package*/ static long nCreatePathDataPropertyHolder(long nativePtr, long startValuePtr,
long endValuePtr) {
Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, "AnimatedVectorDrawable path " +
"animations are not supported.", null, null, null);
return 0;
}
@LayoutlibDelegate
/*package*/ static long nCreatePathColorPropertyHolder(long nativePtr, int propertyId,
int startValue, int endValue) {
VFullPath_Delegate path = VNativeObject.getDelegate(nativePtr);
Consumer<Integer> setter = path.getIntPropertySetter(propertyId);
return sHolders.addNewDelegate(IntPropertySetter.of(setter, startValue,
endValue));
}
@LayoutlibDelegate
/*package*/ static long nCreatePathPropertyHolder(long nativePtr, int propertyId,
float startValue, float endValue) {
VFullPath_Delegate path = VNativeObject.getDelegate(nativePtr);
Consumer<Float> setter = path.getFloatPropertySetter(propertyId);
return sHolders.addNewDelegate(FloatPropertySetter.of(setter, startValue,
endValue));
}
@LayoutlibDelegate
/*package*/ static long nCreateRootAlphaPropertyHolder(long nativePtr, float startValue,
float endValue) {
VPathRenderer_Delegate renderer = VNativeObject.getDelegate(nativePtr);
return sHolders.addNewDelegate(FloatPropertySetter.of(renderer::setRootAlpha,
startValue,
endValue));
}
@LayoutlibDelegate
/*package*/ static void nSetPropertyHolderData(long nativePtr, float[] data, int length) {
PropertySetter setter = sHolders.getDelegate(nativePtr);
assert setter != null;
setter.setValues(data);
}
@LayoutlibDelegate
/*package*/ static void nSetPropertyHolderData(long nativePtr, int[] data, int length) {
PropertySetter setter = sHolders.getDelegate(nativePtr);
assert setter != null;
setter.setValues(data);
}
@LayoutlibDelegate
/*package*/ static void nStart(long animatorSetPtr, VectorDrawableAnimatorRT set, int id) {
AnimatorSetHolder animatorSet = sAnimatorSets.getDelegate(animatorSetPtr);
assert animatorSet != null;
animatorSet.start();
}
@LayoutlibDelegate
/*package*/ static void nReverse(long animatorSetPtr, VectorDrawableAnimatorRT set, int id) {
AnimatorSetHolder animatorSet = sAnimatorSets.getDelegate(animatorSetPtr);
assert animatorSet != null;
animatorSet.reverse();
}
@LayoutlibDelegate
/*package*/ static void nEnd(long animatorSetPtr) {
AnimatorSetHolder animatorSet = sAnimatorSets.getDelegate(animatorSetPtr);
assert animatorSet != null;
animatorSet.end();
}
@LayoutlibDelegate
/*package*/ static void nReset(long animatorSetPtr) {
AnimatorSetHolder animatorSet = sAnimatorSets.getDelegate(animatorSetPtr);
assert animatorSet != null;
animatorSet.end();
animatorSet.start();
}
private static class AnimatorSetHolder {
private ArrayList<Animator> mAnimators = new ArrayList<>();
private AnimatorSet mAnimatorSet = null;
private void addAnimator(@NonNull Animator animator) {
mAnimators.add(animator);
}
private void ensureAnimatorSet() {
if (mAnimatorSet == null) {
mAnimatorSet = new AnimatorSet();
mAnimatorSet.playTogether(mAnimators);
}
}
private void start() {
ensureAnimatorSet();
mAnimatorSet.start();
}
private void end() {
mAnimatorSet.end();
}
private void reset() {
end();
start();
}
private void reverse() {
mAnimatorSet.reverse();
}
}
/**
* Class that allows setting a value and holds the range of values for the given property.
*
* @param <T> the type of the property
*/
private static class PropertySetter<T> {
final Consumer<T> mValueSetter;
private PropertyValuesHolder mValues;
private PropertySetter(@NonNull Consumer<T> valueSetter) {
mValueSetter = valueSetter;
}
/**
* Method to set an {@link Integer} value for this property. The default implementation of
* this method doesn't do anything. This method is accessed via reflection by the
* PropertyValuesHolder.
*/
public void setIntValue(Integer value) {
}
/**
* Method to set an {@link Integer} value for this property. The default implementation of
* this method doesn't do anything. This method is accessed via reflection by the
* PropertyValuesHolder.
*/
public void setFloatValue(Float value) {
}
void setValues(float... values) {
mValues = PropertyValuesHolder.ofFloat("floatValue", values);
}
@Nullable
PropertyValuesHolder getValues() {
return mValues;
}
void setValues(int... values) {
mValues = PropertyValuesHolder.ofInt("intValue", values);
}
}
private static class IntPropertySetter extends PropertySetter<Integer> {
private IntPropertySetter(Consumer<Integer> valueSetter) {
super(valueSetter);
}
private static PropertySetter of(Consumer<Integer> valueSetter, int... values) {
PropertySetter setter = new IntPropertySetter(valueSetter);
setter.setValues(values);
return setter;
}
public void setIntValue(Integer value) {
mValueSetter.accept(value);
}
}
private static class FloatPropertySetter extends PropertySetter<Float> {
private FloatPropertySetter(Consumer<Float> valueSetter) {
super(valueSetter);
}
private static PropertySetter of(Consumer<Float> valueSetter, float... values) {
PropertySetter setter = new FloatPropertySetter(valueSetter);
setter.setValues(values);
return setter;
}
public void setFloatValue(Float value) {
mValueSetter.accept(value);
}
}
}