/*
* Copyright 2014 cruxframework.org.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.cruxframework.crux.core.client.css.animation;
import org.cruxframework.crux.core.client.Crux;
import org.cruxframework.crux.core.client.utils.DOMUtils;
import com.google.gwt.core.shared.GWT;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.resources.client.CssResource;
import com.google.gwt.user.client.ui.Widget;
/**
* Base class to create animations on top of CSS3 animations.
* @author Thiago da Rosa de Bustamante
*
*/
public abstract class Animation <T extends CssResource>
{
private static BrowserImpl browserImpl;
/**
* Constructor
*/
public Animation()
{
getCssResource().ensureInjected();
}
/**
* Run the animation on the given widget
* @param widget to be animated
*/
public void animate(Widget widget)
{
animate(widget.getElement(), null);
}
/**
* Run the animation on the given element
* @param el to be animated
*/
public void animate(final Element el)
{
animate(el, null);
}
/**
* Run the animation on the given widget
* @param widget to be animated
* @param callback called when animation is completed
*/
public void animate(Widget widget, final Callback callback)
{
animate(widget.getElement(), callback);
}
/**
* Run the animation on the given widget
* @param widget to be animated
* @param callback called when animation is completed
* @param duration animation duration in seconds
*/
public void animate(Widget widget, final Callback callback, double duration)
{
animate(widget.getElement(), callback, duration);
}
/**
* Run the animation on the given element
* @param el to be animated
* @param callback called when animation is completed
*/
public void animate(final Element el, final Callback callback)
{
animate(el, callback, -1);
}
/**
* Run the animation on the given element
* @param el to be animated
* @param callback called when animation is completed
* @param duration animation duration in seconds
*/
public void animate(final Element el, final Callback callback, double duration)
{
getBrowserImpl().animate(el, callback, getAnimationCssTrigger(), getAnimationName(), duration);
}
/**
* Retrieve the name of the css class used to trigger the animation
* @return
*/
protected String getAnimationCssTrigger()
{
return "animated";
}
/**
* Retrieve the name of the css animation rule used to animate the element
* @return
*/
protected abstract String getAnimationName();
/**
* Retrieve the CssResource that declare the animation rules used by this animation.
* @return
*/
protected abstract T getCssResource();
/**
* Callback used to monitor when the animation is completed
* @author Thiago da Rosa de Bustamante
*
*/
public static interface Callback
{
/**
* Called when the animation is completed
*/
void onAnimationCompleted();
}
static BrowserImpl getBrowserImpl()
{
if (browserImpl == null)
{
browserImpl = GWT.create(BrowserImpl.class);
}
return browserImpl;
}
static class BrowserImpl
{
public void animate(final Element el, final Callback callback,
final String animationCssTrigger, final String animationName,
final double duration)
{
DOMUtils.addOneTimeHandler(el, getAnimationEndFunctioName(), new DOMUtils.EvtHandler()
{
@Override
public void onEvent(NativeEvent evt)
{
if (callback != null)
{
try
{
callback.onAnimationCompleted();
}
catch(Exception e)
{
Crux.getErrorHandler().handleError(e);
}
}
el.removeClassName(animationCssTrigger+" "+animationName);
if (duration > 0)
{
el.getStyle().setProperty(getAnimationDurationName(), "");
}
}
});
if (duration > 0)
{
el.getStyle().setProperty(getAnimationDurationName(), duration+"s");
}
el.addClassName(animationCssTrigger+" "+animationName);
}
public String getAnimationDurationName()
{
return "animationDuration";
}
public String getAnimationEndFunctioName()
{
return "animationend";
}
}
static class WebkitBrowserImpl extends BrowserImpl
{
@Override
public String getAnimationEndFunctioName()
{
return "webkitAnimationEnd";
}
public String getAnimationDurationName()
{
return "webkitAnimationDuration";
}
}
static class MSIE9BrowserImpl extends BrowserImpl
{
@Override
public void animate(final Element el, final Callback callback,
final String animationCssTrigger, final String animationName,
final double duration)
{
if (callback != null)
{
try
{
callback.onAnimationCompleted();
} catch(Exception e)
{
Crux.getErrorHandler().handleError(e);
}
}
}
@Override
public String getAnimationEndFunctioName()
{
return null;
}
@Override
public String getAnimationDurationName()
{
return null;
}
}
}