1 /*
2  * Copyright (C) 2016 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 android.graphics.drawable;
18 
19 import com.android.ide.common.rendering.api.LayoutLog;
20 import com.android.layoutlib.bridge.Bridge;
21 import com.android.layoutlib.bridge.impl.DelegateManager;
22 import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
23 
24 import android.animation.Animator;
25 import android.animation.AnimatorSet;
26 import android.animation.ObjectAnimator;
27 import android.animation.PropertyValuesHolder;
28 import android.annotation.NonNull;
29 import android.annotation.Nullable;
30 import android.graphics.animation.NativeInterpolatorFactory_Delegate;
31 import android.graphics.drawable.AnimatedVectorDrawable.VectorDrawableAnimatorRT;
32 import android.graphics.drawable.VectorDrawable_Delegate.VFullPath_Delegate;
33 import android.graphics.drawable.VectorDrawable_Delegate.VGroup_Delegate;
34 import android.graphics.drawable.VectorDrawable_Delegate.VNativeObject;
35 import android.graphics.drawable.VectorDrawable_Delegate.VPathRenderer_Delegate;
36 
37 import java.util.ArrayList;
38 import java.util.function.Consumer;
39 
40 /**
41  * Delegate used to provide new implementation of a select few methods of {@link
42  * AnimatedVectorDrawable}
43  * <p>
44  * Through the layoutlib_create tool, the original  methods of AnimatedVectorDrawable have been
45  * replaced by calls to methods of the same name in this delegate class.
46  */
47 @SuppressWarnings("unused")
48 public class AnimatedVectorDrawable_Delegate {
49     private static DelegateManager<AnimatorSetHolder> sAnimatorSets = new
50             DelegateManager<>(AnimatorSetHolder.class);
51     private static DelegateManager<PropertySetter> sHolders = new
52             DelegateManager<>(PropertySetter.class);
53 
54 
55     @LayoutlibDelegate
nCreateAnimatorSet()56     /*package*/ static long nCreateAnimatorSet() {
57         return sAnimatorSets.addNewDelegate(new AnimatorSetHolder());
58     }
59 
60     @LayoutlibDelegate
nSetVectorDrawableTarget(long animatorPtr, long vectorDrawablePtr)61     /*package*/ static void nSetVectorDrawableTarget(long animatorPtr, long vectorDrawablePtr) {
62         // TODO: implement
63     }
64     @LayoutlibDelegate
nAddAnimator(long setPtr, long propertyValuesHolder, long nativeInterpolator, long startDelay, long duration, int repeatCount, int repeatMode)65     /*package*/ static void nAddAnimator(long setPtr, long propertyValuesHolder,
66             long nativeInterpolator, long startDelay, long duration, int repeatCount,
67             int repeatMode) {
68         PropertySetter holder = sHolders.getDelegate(propertyValuesHolder);
69         if (holder == null || holder.getValues() == null) {
70             return;
71         }
72 
73         ObjectAnimator animator = new ObjectAnimator();
74         animator.setValues(holder.getValues());
75         animator.setInterpolator(
76                 NativeInterpolatorFactory_Delegate.getDelegate(nativeInterpolator));
77         animator.setStartDelay(startDelay);
78         animator.setDuration(duration);
79         animator.setRepeatCount(repeatCount);
80         animator.setRepeatMode(repeatMode);
81         animator.setTarget(holder);
82         animator.setPropertyName(holder.getValues().getPropertyName());
83 
84         AnimatorSetHolder set = sAnimatorSets.getDelegate(setPtr);
85         assert set != null;
86         set.addAnimator(animator);
87     }
88 
89     @LayoutlibDelegate
nCreateGroupPropertyHolder(long nativePtr, int propertyId, float startValue, float endValue)90     /*package*/ static long nCreateGroupPropertyHolder(long nativePtr, int propertyId,
91             float startValue, float endValue) {
92         VGroup_Delegate group = VNativeObject.getDelegate(nativePtr);
93         Consumer<Float> setter = group.getPropertySetter(propertyId);
94 
95         return sHolders.addNewDelegate(FloatPropertySetter.of(setter, startValue,
96                 endValue));
97     }
98 
99     @LayoutlibDelegate
nCreatePathDataPropertyHolder(long nativePtr, long startValuePtr, long endValuePtr)100     /*package*/ static long nCreatePathDataPropertyHolder(long nativePtr, long startValuePtr,
101             long endValuePtr) {
102         Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, "AnimatedVectorDrawable path " +
103                 "animations are not supported.", null, null, null);
104         return 0;
105     }
106 
107     @LayoutlibDelegate
nCreatePathColorPropertyHolder(long nativePtr, int propertyId, int startValue, int endValue)108     /*package*/ static long nCreatePathColorPropertyHolder(long nativePtr, int propertyId,
109             int startValue, int endValue) {
110         VFullPath_Delegate path = VNativeObject.getDelegate(nativePtr);
111         Consumer<Integer> setter = path.getIntPropertySetter(propertyId);
112 
113         return sHolders.addNewDelegate(IntPropertySetter.of(setter, startValue,
114                 endValue));
115     }
116 
117     @LayoutlibDelegate
nCreatePathPropertyHolder(long nativePtr, int propertyId, float startValue, float endValue)118     /*package*/ static long nCreatePathPropertyHolder(long nativePtr, int propertyId,
119             float startValue, float endValue) {
120         VFullPath_Delegate path = VNativeObject.getDelegate(nativePtr);
121         Consumer<Float> setter = path.getFloatPropertySetter(propertyId);
122 
123         return sHolders.addNewDelegate(FloatPropertySetter.of(setter, startValue,
124                 endValue));
125     }
126 
127     @LayoutlibDelegate
nCreateRootAlphaPropertyHolder(long nativePtr, float startValue, float endValue)128     /*package*/ static long nCreateRootAlphaPropertyHolder(long nativePtr, float startValue,
129             float endValue) {
130         VPathRenderer_Delegate renderer = VNativeObject.getDelegate(nativePtr);
131 
132         return sHolders.addNewDelegate(FloatPropertySetter.of(renderer::setRootAlpha,
133                 startValue,
134                 endValue));
135     }
136 
137     @LayoutlibDelegate
nSetPropertyHolderData(long nativePtr, float[] data, int length)138     /*package*/ static void nSetPropertyHolderData(long nativePtr, float[] data, int length) {
139         PropertySetter setter = sHolders.getDelegate(nativePtr);
140         assert setter != null;
141 
142         setter.setValues(data);
143     }
144 
145     @LayoutlibDelegate
nSetPropertyHolderData(long nativePtr, int[] data, int length)146     /*package*/ static void nSetPropertyHolderData(long nativePtr, int[] data, int length) {
147         PropertySetter setter = sHolders.getDelegate(nativePtr);
148         assert setter != null;
149 
150         setter.setValues(data);
151     }
152 
153     @LayoutlibDelegate
nStart(long animatorSetPtr, VectorDrawableAnimatorRT set, int id)154     /*package*/ static void nStart(long animatorSetPtr, VectorDrawableAnimatorRT set, int id) {
155         AnimatorSetHolder animatorSet = sAnimatorSets.getDelegate(animatorSetPtr);
156         assert animatorSet != null;
157 
158         animatorSet.start();
159     }
160 
161     @LayoutlibDelegate
nReverse(long animatorSetPtr, VectorDrawableAnimatorRT set, int id)162     /*package*/ static void nReverse(long animatorSetPtr, VectorDrawableAnimatorRT set, int id) {
163         AnimatorSetHolder animatorSet = sAnimatorSets.getDelegate(animatorSetPtr);
164         assert animatorSet != null;
165 
166         animatorSet.reverse();
167     }
168 
169     @LayoutlibDelegate
nEnd(long animatorSetPtr)170     /*package*/ static void nEnd(long animatorSetPtr) {
171         AnimatorSetHolder animatorSet = sAnimatorSets.getDelegate(animatorSetPtr);
172         assert animatorSet != null;
173 
174         animatorSet.end();
175     }
176 
177     @LayoutlibDelegate
nReset(long animatorSetPtr)178     /*package*/ static void nReset(long animatorSetPtr) {
179         AnimatorSetHolder animatorSet = sAnimatorSets.getDelegate(animatorSetPtr);
180         assert animatorSet != null;
181 
182         animatorSet.end();
183         animatorSet.start();
184     }
185 
186     private static class AnimatorSetHolder {
187         private ArrayList<Animator> mAnimators = new ArrayList<>();
188         private AnimatorSet mAnimatorSet = null;
189 
addAnimator(@onNull Animator animator)190         private void addAnimator(@NonNull Animator animator) {
191             mAnimators.add(animator);
192         }
193 
ensureAnimatorSet()194         private void ensureAnimatorSet() {
195             if (mAnimatorSet == null) {
196                 mAnimatorSet = new AnimatorSet();
197                 mAnimatorSet.playTogether(mAnimators);
198             }
199         }
200 
start()201         private void start() {
202             ensureAnimatorSet();
203 
204             mAnimatorSet.start();
205         }
206 
end()207         private void end() {
208             mAnimatorSet.end();
209         }
210 
reset()211         private void reset() {
212             end();
213             start();
214         }
215 
reverse()216         private void reverse() {
217             mAnimatorSet.reverse();
218         }
219     }
220 
221     /**
222      * Class that allows setting a value and holds the range of values for the given property.
223      *
224      * @param <T> the type of the property
225      */
226     private static class PropertySetter<T> {
227         final Consumer<T> mValueSetter;
228         private PropertyValuesHolder mValues;
229 
PropertySetter(@onNull Consumer<T> valueSetter)230         private PropertySetter(@NonNull Consumer<T> valueSetter) {
231             mValueSetter = valueSetter;
232         }
233 
234         /**
235          * Method to set an {@link Integer} value for this property. The default implementation of
236          * this method doesn't do anything. This method is accessed via reflection by the
237          * PropertyValuesHolder.
238          */
setIntValue(Integer value)239         public void setIntValue(Integer value) {
240         }
241 
242         /**
243          * Method to set an {@link Integer} value for this property. The default implementation of
244          * this method doesn't do anything. This method is accessed via reflection by the
245          * PropertyValuesHolder.
246          */
setFloatValue(Float value)247         public void setFloatValue(Float value) {
248         }
249 
setValues(float... values)250         void setValues(float... values) {
251             mValues = PropertyValuesHolder.ofFloat("floatValue", values);
252         }
253 
254         @Nullable
getValues()255         PropertyValuesHolder getValues() {
256             return mValues;
257         }
258 
setValues(int... values)259         void setValues(int... values) {
260             mValues = PropertyValuesHolder.ofInt("intValue", values);
261         }
262     }
263 
264     private static class IntPropertySetter extends PropertySetter<Integer> {
IntPropertySetter(Consumer<Integer> valueSetter)265         private IntPropertySetter(Consumer<Integer> valueSetter) {
266             super(valueSetter);
267         }
268 
of(Consumer<Integer> valueSetter, int... values)269         private static PropertySetter of(Consumer<Integer> valueSetter, int... values) {
270             PropertySetter setter = new IntPropertySetter(valueSetter);
271             setter.setValues(values);
272 
273             return setter;
274         }
275 
setIntValue(Integer value)276         public void setIntValue(Integer value) {
277             mValueSetter.accept(value);
278         }
279     }
280 
281     private static class FloatPropertySetter extends PropertySetter<Float> {
FloatPropertySetter(Consumer<Float> valueSetter)282         private FloatPropertySetter(Consumer<Float> valueSetter) {
283             super(valueSetter);
284         }
285 
of(Consumer<Float> valueSetter, float... values)286         private static PropertySetter of(Consumer<Float> valueSetter, float... values) {
287             PropertySetter setter = new FloatPropertySetter(valueSetter);
288             setter.setValues(values);
289 
290             return setter;
291         }
292 
setFloatValue(Float value)293         public void setFloatValue(Float value) {
294             mValueSetter.accept(value);
295         }
296 
297     }
298 }
299