package org.gwtoolbox.commons.ui.client.animation.fx;
import com.google.gwt.dom.client.Element;
import com.google.gwt.user.client.ui.Widget;
import org.gwtoolbox.commons.ui.client.animation.Animator;
import org.gwtoolbox.commons.ui.client.animation.Transition;
import org.gwtoolbox.commons.util.client.UIUtils;
/**
* @author Uri Boness
*/
public class Fx {
private final static int DEFAULT_DURATION = 300;
private Fx() {
}
public static void effect(Effect effect) {
effect(DEFAULT_DURATION, effect);
}
public static void effect(int duration, final Effect effect) {
if (!effect.init()) {
return;
}
new Animator(duration).start(new Animator.Callback() {
public void update(double progress) {
progress = effect.getTransition().translate(progress);
effect.update(progress);
}
public void finished() {
effect.finished();
}
});
}
public static void effects(Effect... effects) {
effects(DEFAULT_DURATION, new CompoundEffect(effects));
}
public static void effects(int duration, Effect... effects) {
effect(duration, new CompoundEffect(effects));
}
public static void effectChain(Effect... effects) {
effectChain(DEFAULT_DURATION, effects);
}
public static void effectChain(int duration, Effect... effects) {
for (Effect effect : effects) {
effect(duration, effect);
}
}
public static Effect fadeIn(Widget widget) {
return new FadeInWidgetEffect(widget);
}
public static Effect fadeIn(Element element) {
return new FadeInElementEffect(element);
}
public static Effect fadeOut(Widget widget) {
return new FadeOutWidgetEffect(widget);
}
public static Effect fadeOut(Element element) {
return new FadeOutElementEffect(element);
}
//================================================= Inner Classes ==================================================
private static class CompoundEffect implements Effect {
private final Effect[] effects;
private final boolean[] apply;
private CompoundEffect(Effect... effects) {
this.effects = effects;
apply = new boolean[effects.length];
}
public boolean init() {
int i = 0;
boolean applyOverall = true;
for (Effect effect : effects) {
boolean shouldApply = effect.init();
applyOverall = applyOverall & shouldApply;
apply[i++] = shouldApply;
}
return applyOverall;
}
public void update(double progress) {
int i = 0;
for (Effect effect : effects) {
if (apply[i++]) {
effect.update(progress);
}
}
}
public void finished() {
int i = 0;
for (Effect effect : effects) {
if (apply[i++]) {
effect.finished();
}
}
}
/**
* This effect has no one global transition. Each effect it contains has its own transition.
*
* @return {@code null}
*/
public Transition getTransition() {
return null;
}
}
private static class FadeInWidgetEffect extends AbstractWidgetEffect {
private FadeInWidgetEffect(Widget widget) {
super(widget);
}
public boolean init() {
if (widget.isVisible()) {
return false;
}
widget.getElement().getStyle().setOpacity(0);
widget.setVisible(true);
return true;
}
public void update(double progress) {
widget.getElement().getStyle().setOpacity(progress);
}
public void finished() {
widget.getElement().getStyle().clearOpacity();
}
}
private static class FadeInElementEffect extends AbstractElementEffect {
private FadeInElementEffect(Element element) {
super(element);
}
public boolean init() {
if (UIUtils.isVisible(element)) {
return false;
}
element.getStyle().setOpacity(0);
UIUtils.setVisible(element, (true));
return true;
}
public void update(double progress) {
element.getStyle().setOpacity(progress);
}
public void finished() {
element.getStyle().clearOpacity();
}
}
private static class FadeOutWidgetEffect extends AbstractWidgetEffect {
private FadeOutWidgetEffect(Widget widget) {
super(widget);
}
public boolean init() {
if (!widget.isVisible()) {
return false;
}
widget.getElement().getStyle().setOpacity(100);
widget.setVisible(true);
return true;
}
public void update(double progress) {
widget.getElement().getStyle().setOpacity(1 - progress);
}
public void finished() {
widget.setVisible(false);
widget.getElement().getStyle().clearOpacity();
}
}
private static class FadeOutElementEffect extends AbstractElementEffect {
private FadeOutElementEffect(Element element) {
super(element);
}
public boolean init() {
if (!UIUtils.isVisible(element)) {
return false;
}
element.getStyle().setOpacity(100);
UIUtils.setVisible(element, true);
return true;
}
public void update(double progress) {
element.getStyle().setOpacity(1 - progress);
}
public void finished() {
UIUtils.setVisible(element, false);
element.getStyle().clearOpacity();
}
}
}