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
17package android.graphics.drawable;
18
19import com.android.ide.common.rendering.api.LayoutLog;
20import com.android.internal.view.animation.NativeInterpolatorFactoryHelper_Delegate;
21import com.android.layoutlib.bridge.Bridge;
22import com.android.layoutlib.bridge.impl.DelegateManager;
23import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
24
25import android.animation.Animator;
26import android.animation.AnimatorSet;
27import android.animation.ObjectAnimator;
28import android.animation.PropertyValuesHolder;
29import android.annotation.NonNull;
30import android.annotation.Nullable;
31import android.graphics.drawable.AnimatedVectorDrawable.VectorDrawableAnimatorRT;
32import android.graphics.drawable.VectorDrawable_Delegate.VFullPath_Delegate;
33import android.graphics.drawable.VectorDrawable_Delegate.VGroup_Delegate;
34import android.graphics.drawable.VectorDrawable_Delegate.VNativeObject;
35import android.graphics.drawable.VectorDrawable_Delegate.VPathRenderer_Delegate;
36
37import java.util.ArrayList;
38import 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")
48public 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
56    /*package*/ static long nCreateAnimatorSet() {
57        return sAnimatorSets.addNewDelegate(new AnimatorSetHolder());
58    }
59
60    @LayoutlibDelegate
61    /*package*/ static void nSetVectorDrawableTarget(long animatorPtr, long vectorDrawablePtr) {
62        // TODO: implement
63    }
64    @LayoutlibDelegate
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                NativeInterpolatorFactoryHelper_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
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
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);
104        return 0;
105    }
106
107    @LayoutlibDelegate
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
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
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
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
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
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
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
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
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
190        private void addAnimator(@NonNull Animator animator) {
191            mAnimators.add(animator);
192        }
193
194        private void ensureAnimatorSet() {
195            if (mAnimatorSet == null) {
196                mAnimatorSet = new AnimatorSet();
197                mAnimatorSet.playTogether(mAnimators);
198            }
199        }
200
201        private void start() {
202            ensureAnimatorSet();
203
204            mAnimatorSet.start();
205        }
206
207        private void end() {
208            mAnimatorSet.end();
209        }
210
211        private void reset() {
212            end();
213            start();
214        }
215
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
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         */
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         */
247        public void setFloatValue(Float value) {
248        }
249
250        void setValues(float... values) {
251            mValues = PropertyValuesHolder.ofFloat("floatValue", values);
252        }
253
254        @Nullable
255        PropertyValuesHolder getValues() {
256            return mValues;
257        }
258
259        void setValues(int... values) {
260            mValues = PropertyValuesHolder.ofInt("intValue", values);
261        }
262    }
263
264    private static class IntPropertySetter extends PropertySetter<Integer> {
265        private IntPropertySetter(Consumer<Integer> valueSetter) {
266            super(valueSetter);
267        }
268
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
276        public void setIntValue(Integer value) {
277            mValueSetter.accept(value);
278        }
279    }
280
281    private static class FloatPropertySetter extends PropertySetter<Float> {
282        private FloatPropertySetter(Consumer<Float> valueSetter) {
283            super(valueSetter);
284        }
285
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
293        public void setFloatValue(Float value) {
294            mValueSetter.accept(value);
295        }
296
297    }
298}
299