package ilarkesto.gwt.client.animation;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.Widget;
public class AnimatingFlowPanel<W extends Widget> extends Composite implements HasWidgets {
private static boolean animationsDisabled = false;
private FlowPanel panel;
private boolean actionRunning;
private List<Runnable> actions = new LinkedList<Runnable>();
private double animationDelayFactor = 2;
public AnimatingFlowPanel() {
panel = new FlowPanel();
initWidget(panel);
}
public AnimatingFlowPanel(double animationDelayFactor) {
this();
this.animationDelayFactor = animationDelayFactor;
}
private void executeNextAction() {
if (actionRunning) return;
if (actions.isEmpty()) return;
Runnable action = actions.get(0);
actions.remove(action);
action.run();
}
private void execute(Runnable action) {
actions.add(action);
executeNextAction();
}
public void insertAnimated(int index, W widget, Integer height, Runnable runAfter) {
if (animationsDisabled) {
insert(index, widget);
return;
}
execute(new InsertAction(index, widget, height, runAfter));
}
public void insert(int index, W widget) {
if (actionRunning) {
execute(new InsertAction(index, widget));
} else {
if (index < 0) index = panel.getWidgetCount();
panel.insert(widget, index);
}
}
public boolean remove(final Widget widget) {
if (actionRunning) {
execute(new RemoveAction(widget));
} else {
panel.remove(widget);
}
return true;
}
public void removeAnimated(final W widget) {
if (animationsDisabled) {
remove(widget);
return;
}
execute(new RemoveAction(widget));
}
public void clear() {
panel.clear();
}
@Override
public Iterator<Widget> iterator() {
return panel.iterator();
}
@Override
public void add(Widget w) {
insertAnimated(-1, (W) w, null, null);
}
public void setAnimationDelayFactor(double animationDelayFactor) {
this.animationDelayFactor = animationDelayFactor;
}
private class RemoveAction implements Runnable {
private Widget widget;
private boolean animated;
public RemoveAction(Widget widget) {
this.widget = widget;
this.animated = true;
}
@Override
public void run() {
if (!animated) {
panel.remove(widget);
return;
}
actionRunning = true;
DisappearAnimation animation = new DisappearAnimation(widget, animationDelayFactor);
animation.addCompletionListener(new CompletionListener() {
@Override
public void completionEvent(AObservableAnimation source) {
panel.remove(widget);
actionRunning = false;
executeNextAction();
}
});
animation.run(250);
}
}
private class InsertAction implements Runnable {
private Widget widget;
private int index;
private boolean animated;
private Integer animationHeight;
private Runnable runAfter;
public InsertAction(int index, Widget widget, Integer animationHeight, Runnable runAfter) {
this.index = index;
this.widget = widget;
this.animationHeight = animationHeight;
this.runAfter = runAfter;
this.animated = true;
}
public InsertAction(int index, Widget widget) {
this.index = index;
this.widget = widget;
this.animated = false;
}
@Override
public void run() {
if (index < 0) index = panel.getWidgetCount();
if (!animated) {
panel.insert(widget, index);
return;
}
actionRunning = true;
AppearAnimation animation = new AppearAnimation(animationHeight, widget, animationDelayFactor);
panel.insert(widget, index);
animation.addCompletionListener(new CompletionListener() {
@Override
public void completionEvent(AObservableAnimation source) {
actionRunning = false;
if (runAfter != null) runAfter.run();
executeNextAction();
}
});
animation.run(250);
}
}
public static interface MoveObserver {
void onMoved();
}
}