/*
* Copyright (c) 2017-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
package com.facebook.litho.animation;
import java.util.concurrent.CopyOnWriteArrayList;
import android.support.v4.util.SimpleArrayMap;
import com.facebook.litho.internal.ArraySet;
/**
* An {@link AnimationBinding} that's a sequence of other {@link AnimationBinding}s.
*/
public class SequenceBinding implements AnimationBinding {
private final CopyOnWriteArrayList<AnimationBindingListener> mListeners =
new CopyOnWriteArrayList<>();
private final AnimationBinding[] mBindings;
private final AnimationBindingListener mChildListener;
private Resolver mResolver;
private int mCurrentIndex = 0;
private boolean mIsActive = false;
public SequenceBinding(AnimationBinding... bindings) {
mBindings = bindings;
if (mBindings.length == 0) {
throw new IllegalArgumentException("Empty binding sequence");
}
mChildListener = new AnimationBindingListener() {
@Override
public void onStart(AnimationBinding binding) {
}
@Override
public void onFinish(AnimationBinding binding) {
SequenceBinding.this.onBindingFinished(binding);
}
};
}
private void onBindingFinished(AnimationBinding binding) {
if (binding != mBindings[mCurrentIndex]) {
throw new RuntimeException("Unexpected Binding completed");
}
binding.removeListener(mChildListener);
mCurrentIndex++;
if (mCurrentIndex >= mBindings.length) {
finish();
} else {
AnimationBinding next = mBindings[mCurrentIndex];
next.addListener(mChildListener);
next.start(mResolver);
}
}
private void finish() {
for (AnimationBindingListener listener : mListeners) {
listener.onFinish(this);
}
mIsActive = false;
mResolver = null;
}
@Override
public void start(Resolver resolver) {
if (mIsActive) {
throw new RuntimeException("Already started");
}
mIsActive = true;
for (AnimationBindingListener listener : mListeners) {
listener.onStart(this);
}
mResolver = resolver;
mBindings[0].addListener(mChildListener);
mBindings[0].start(mResolver);
}
@Override
public void stop() {
if (!mIsActive) {
return;
}
mIsActive = false;
mBindings[mCurrentIndex].stop();
}
@Override
public boolean isActive() {
return mIsActive;
}
@Override
public void collectTransitioningProperties(ArraySet<ComponentProperty> outSet) {
for (int i = 0; i < mBindings.length; i++) {
mBindings[i].collectTransitioningProperties(outSet);
}
}
@Override
public void collectAppearFromValues(SimpleArrayMap<ComponentProperty, RuntimeValue> outMap) {
for (int i = 0; i < mBindings.length; i++) {
mBindings[i].collectAppearFromValues(outMap);
}
}
@Override
public void collectDisappearToValues(SimpleArrayMap<ComponentProperty, RuntimeValue> outMap) {
for (int i = 0; i < mBindings.length; i++) {
mBindings[i].collectDisappearToValues(outMap);
}
}
@Override
public void addListener(AnimationBindingListener animationBindingListener) {
mListeners.add(animationBindingListener);
}
@Override
public void removeListener(AnimationBindingListener animationBindingListener) {
mListeners.remove(animationBindingListener);
}
}