/*
* Copyright 2011 Daniel Kurka
*
* 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 com.googlecode.mgwt.ui.client.widget.animation.impl;
import com.google.gwt.core.shared.GWT;
import com.google.gwt.dom.client.Style.Display;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.CssResource;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.IsWidget;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.Widget;
import com.googlecode.mgwt.dom.client.event.animation.AnimationEndEvent;
import com.googlecode.mgwt.dom.client.event.animation.AnimationEndHandler;
import com.googlecode.mgwt.ui.client.widget.animation.Animation;
import com.googlecode.mgwt.ui.client.widget.animation.AnimationEndCallback;
/**
* Considered internal
*
* @author Daniel Kurka
*/
public class AnimationWidgetKeyFrameImpl implements AnimationWidgetImpl {
static {
Bundle.INSTANCE.css().ensureInjected();
}
interface Bundle extends ClientBundle {
Bundle INSTANCE = GWT.create(Bundle.class);
@Source("animation-display.css")
DisplayCss css();
}
interface DisplayCss extends CssResource {
String display();
String displayContainer();
}
protected class AnimationEndListener implements AnimationEndHandler {
private Animation animation;
public AnimationEndListener(Animation animation) {
this.animation = animation;
}
@Override
public void onAnimationEnd(AnimationEndEvent event) {
AnimationWidgetKeyFrameImpl.this.onAnimationEnd(animation);
}
}
private boolean animationRunning;
private Animation currentAnimation;
private FlowPanel main;
private SimplePanel first;
private SimplePanel second;
private boolean lastDir;
private boolean showFirst;
private HandlerRegistration animationEnd;
private AnimationEndListener listener;
private AnimationEndCallback lastCallback;
public AnimationWidgetKeyFrameImpl() {
main = new FlowPanel() {
protected void onDetach() {
super.onDetach();
if (animationRunning) {
onAnimationEnd(currentAnimation);
}
};
};
main.setStylePrimaryName(Bundle.INSTANCE.css().display());
first = new SimplePanel();
first.addStyleName(Bundle.INSTANCE.css().displayContainer());
second = new SimplePanel();
second.addStyleName(Bundle.INSTANCE.css().displayContainer());
main.add(first);
main.add(second);
}
@Override
public void animate(Animation animation, boolean currentIsFirst, AnimationEndCallback callback) {
if (animationRunning) {
throw new RuntimeException("Animation is already running");
}
this.currentAnimation = animation;
lastCallback = callback;
blurBeforeAnimation();
showFirst = currentIsFirst;
if (animation == null) {
if (showFirst) {
first.getElement().getStyle().setDisplay(Display.BLOCK);
} else {
second.getElement().getStyle().setDisplay(Display.BLOCK);
}
onAnimationEnd(animation);
return;
}
animationRunning = true;
if (animationEnd != null) {
animationEnd.removeHandler();
animationEnd = null;
}
animationEnd =
main.addDomHandler(new AnimationEndListener(animation), AnimationEndEvent.getType());
lastDir = animation.isReversed();
// backwards
if (animation.isReversed()) {
first.addStyleName(animation.css().reverse());
second.addStyleName(animation.css().reverse());
}
if (currentIsFirst) {
first.addStyleName(animation.css().in());
second.addStyleName(animation.css().out());
} else {
first.addStyleName(animation.css().out());
second.addStyleName(animation.css().in());
}
first.getElement().getStyle().setDisplay(Display.BLOCK);
second.getElement().getStyle().setDisplay(Display.BLOCK);
}
@Override
public Widget asWidget() {
return main;
}
@Override
public void setFirstWidget(IsWidget w) {
first.setWidget(w);
}
@Override
public void setSecondWidget(IsWidget w) {
second.setWidget(w);
}
private native void blurBeforeAnimation() /*-{
var node = $doc.querySelector(":focus");
if (node != null) {
if (typeof (node.blur) == "function") {
node.blur();
}
}
}-*/;
private void onAnimationEnd(Animation animation) {
animationRunning = false;
if (showFirst) {
second.getElement().getStyle().setDisplay(Display.NONE);
second.clear();
} else {
first.getElement().getStyle().setDisplay(Display.NONE);
first.clear();
}
if(animation != null) {
removeAllStyles(animation);
}
if (animationEnd != null) {
animationEnd.removeHandler();
animationEnd = null;
}
if (lastCallback != null) {
lastCallback.onAnimationEnd();
lastCallback = null;
}
}
private void removeAllStyles(Animation animation) {
first.removeStyleName(animation.css().in());
first.removeStyleName(animation.css().out());
first.removeStyleName(animation.css().reverse());
second.removeStyleName(animation.css().in());
second.removeStyleName(animation.css().out());
second.removeStyleName(animation.css().reverse());
}
}