
org.ioc.commons.impl.gwt.client.ui.Css3Util Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ioc-commons-gwt-impl Show documentation
Show all versions of ioc-commons-gwt-impl Show documentation
GWT implementation for ioc-commons artifacts.
package org.ioc.commons.impl.gwt.client.ui;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import org.ioc.commons.impl.gwt.client.ui.Css3Util.Css3EffectQueue.AppearEffectType;
import org.ioc.commons.impl.gwt.client.ui.Css3Util.Css3EffectQueue.DisappearEffectType;
import org.ioc.commons.impl.gwt.client.ui.Css3Util.Css3EffectQueue.EffectHandler;
import org.ioc.commons.ui.HasStorage;
import org.ioc.commons.utils.Format;
import org.ioc.commons.utils.FormatterLogger;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.dom.client.Style;
import com.google.gwt.dom.client.Style.Display;
import com.google.gwt.dom.client.Style.Overflow;
import com.google.gwt.dom.client.Style.Position;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.logical.shared.AttachEvent;
import com.google.gwt.user.client.ui.Widget;
public class Css3Util {
/*
* TODO: Controlar en toda la aplicación el efecto si CSS3 no está
* soportado.
*/
private static FormatterLogger logger = FormatterLogger.getLogger(Css3Util.class);
public enum VisibilityModeStyle {
USE_DISPLAY_PROPERTY, USE_VISIBILITY_PROPERTY;
}
public static Css3Style getStyle(Element element) {
return new Css3Style(element);
}
public static Css3Toolkit getToolkit(Element element) {
return getToolkit(element, null);
}
private static class Key {
Element element;
Key(Element element) {
this.element = element;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((element == null) ? 0 : element.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (!(obj instanceof Key)) {
return false;
}
Key other = (Key) obj;
if (element == null) {
if (other.element != null) {
return false;
}
} else if (!element.equals(other.element)) {
return false;
}
return true;
}
}
public static Css3Toolkit getToolkit(Element element, HasStorage storage) {
Css3Toolkit css3Toolkit = null;
if (storage != null) {
Key key = new Key(element);
css3Toolkit = (Css3Toolkit) (storage != null ? storage.retrieve(key) : null);
if (css3Toolkit == null) {
css3Toolkit = new Css3Toolkit(element);
storage.store(key, css3Toolkit);
}
} else {
css3Toolkit = new Css3Toolkit(element);
}
return css3Toolkit;
}
public static Css3Toolkit getToolkit(final Widget w) {
return getToolkit(w, null);
}
public static Css3Toolkit getToolkit(final Widget w, HasStorage storage) {
Css3Toolkit tk = getToolkit(w.getElement(), storage);
if (!w.isAttached() && !tk.attachHandlerAdded) {
/**
* Si el widget no está attachado, los efectos no dispararán el
* TransactionListener. Por eso justo cuando se attache, se dispara
* y vamos al siguiente.
*/
w.addAttachHandler(new AttachEvent.Handler() {
@Override
public void onAttachOrDetach(AttachEvent event) {
getToolkit(w.getElement()).css3EffectQueue.resolvePendingEffects();
}
});
tk.attachHandlerAdded = true;
}
return tk;
}
protected static void getDefaultVisibleDisplay(Element elm) {
if (elm.getTagName().equalsIgnoreCase("table")) {
elm.getStyle().setProperty("display", "table");
} else if (elm.getTagName().equalsIgnoreCase("td")) {
elm.getStyle().setProperty("display", "table-cell");
} else if (elm.getTagName().equalsIgnoreCase("tr")) {
elm.getStyle().setProperty("display", "table-row");
} else {
elm.getStyle().setDisplay(Display.INLINE);
}
}
public static class Css3Style {
private static final String WEBKIT = "webkit";
private static final String MOZILLA = "moz";
private static final String OPERA = "o";
private static final String MICROSOFT = "ms";
private final Style style;
private final Element element;
Css3Style(Element element) {
if (element == null) {
throw new NullPointerException("Element cannot be null");
}
this.element = element;
this.style = element.getStyle();
}
protected int getIntProperty(String name) {
String value = getProperty(name);
if (value != null && !value.isEmpty()) {
double number = JsUtil.extractNumberValue(value);
if (value.endsWith("s") || !value.endsWith("ms")) {
number *= 1000.0;
}
return (int) number;
}
return 0;
}
protected String getProperty(String name) {
String result = null;
/**
* Camel case
*/
result = this.style.getProperty(name);
result = (result == null || result.isEmpty()) ? this.style.getProperty(WEBKIT + Format.capitalize(name))
: result;
result = (result == null || result.isEmpty()) ? this.style.getProperty(MOZILLA + Format.capitalize(name))
: result;
result = (result == null || result.isEmpty()) ? this.style.getProperty(OPERA + Format.capitalize(name))
: result;
result = (result == null || result.isEmpty()) ? this.style.getProperty(MICROSOFT + Format.capitalize(name))
: result;
// /**
// * No camel case
// */
//
// result = getRawProperty(this.style, name);
// result = (result == null || result.isEmpty()) ?
// this.style.getProperty(WEBKIT + Format.capitalize(name))
// : result;
// result = (result == null || result.isEmpty()) ?
// this.style.getProperty(MOZILLA + Format.capitalize(name))
// : result;
// result = (result == null || result.isEmpty()) ?
// this.style.getProperty(OPERA + Format.capitalize(name))
// : result;
// result = (result == null || result.isEmpty()) ?
// this.style.getProperty(MICROSOFT + Format.capitalize(name))
// : result;
return result;
}
protected void setProperty(String name, String value) {
this.style.setProperty(name, value);
this.style.setProperty(WEBKIT + Format.capitalize(name), value);
this.style.setProperty(MOZILLA + Format.capitalize(name), value);
this.style.setProperty(OPERA + Format.capitalize(name), value);
this.style.setProperty(MICROSOFT + Format.capitalize(name), value);
}
public void setTransform(String value) {
setProperty("transform", value);
}
public void setTransition(String value) {
setProperty("transition", value);
}
public void setTransitionDuration(String value) {
setProperty("transitionDuration", value);
}
public void setTransitionProperty(String value, boolean add) {
if (!add) {
setProperty("transitionProperty", value);
} else {
HashSet tpSet = new HashSet();
tpSet.add(value);
String tp = getProperty("transitionProperty");
String[] parts = (tp != null) ? tp.split(",") : null;
if (parts != null) {
List tpList = Arrays.asList(parts);
tpSet.addAll(tpList);
}
StringBuffer sb = new StringBuffer();
for (String newTps : tpSet) {
sb.append(newTps).append(',');
}
if (sb.charAt(sb.length() - 1) == ',') {
sb.deleteCharAt(sb.length() - 1);
}
setProperty("transitionProperty", sb.toString());
}
}
public void removeTransitionProperty(String property) {
HashSet tpSet = new HashSet();
String tp = getProperty("transitionProperty");
String[] parts = (tp != null) ? tp.split(",") : null;
String[] properties = property.split(",");
if (parts != null) {
for (String part : parts) {
boolean remove = false;
for (String prop : properties) {
if (part.trim().equalsIgnoreCase(prop.trim())) {
remove = true;
break;
}
}
if (!remove) {
tpSet.add(part);
}
}
}
StringBuffer sb = new StringBuffer();
if (!tpSet.isEmpty()) {
for (String newTps : tpSet) {
sb.append(newTps).append(',');
}
if (sb.charAt(sb.length() - 1) == ',') {
sb.deleteCharAt(sb.length() - 1);
}
}
setProperty("transitionProperty", sb.toString());
}
public int getTransitionDuration() {
int td = getIntProperty("transitionDuration");
return td;
}
public void setTransitionTimingFunction(String value) {
setProperty("transitionTimingFunction", value);
}
public void addTransitionEndListener(TransitionEndListener transitionEndListener) {
this.addTransitionEndListener(element, transitionEndListener);
}
public void removeTransitionEndListener(TransitionEndListener transitionEndListener) {
this.removeTransitionEndListener(element, transitionEndListener.callback);
}
protected native void addTransitionEndListener(Element element,
final TransitionEndListener transitionEndListener) /*-{
var callBack = function(e) {
transitionEndListener.@org.ioc.commons.impl.gwt.client.ui.Css3Util.TransitionEndListener::onTransitionEnd(Lcom/google/gwt/dom/client/NativeEvent;)(e);
}
//Chrome
element.addEventListener('webkitTransitionEnd', callBack, false);
//Firefox y estandar W3C
element.addEventListener('transitionend', callBack, false);
//IE10+
element.addEventListener('msTransitionEnd', callBack, false);
//Opera
element.addEventListener('oTransitionEnd', callBack, false);
//Standard
element.addEventListener('transitionEnd', callBack, false);
transitionEndListener.@org.ioc.commons.impl.gwt.client.ui.Css3Util.TransitionEndListener::setCallback(Lcom/google/gwt/core/client/JavaScriptObject;)(callBack);
}-*/;
protected native void removeTransitionEndListener(Element element, JavaScriptObject callBack) /*-{
//Chrome
element.removeEventListener('webkitTransitionEnd', callBack, false);
//Firefox y estandar W3C
element.removeEventListener('transitionend', callBack, false);
//IE10+
element.removeEventListener('msTransitionEnd', callBack, false);
//Opera
element.removeEventListener('oTransitionEnd', callBack, false);
//Standard
element.removeEventListener('transitionEnd', callBack, false);
}-*/;
}
public static class Css3Toolkit {
boolean attachHandlerAdded;
private Element theElement;
private Css3EffectQueue css3EffectQueue;
Css3Toolkit(Widget w) {
this(w.getElement());
}
Css3Toolkit(Element element) {
this.theElement = element;
this.css3EffectQueue = new Css3EffectQueue();
}
public static EffectHandler[] disappear(VisibilityModeStyle visibilityModeStyle, Widget... widgets) {
return disappear(DisappearEffectType.FADE_OUT, visibilityModeStyle, widgets);
}
public static EffectHandler[] disappear(DisappearEffectType disappearEffect,
VisibilityModeStyle visibilityModeStyle, Widget... widgets) {
EffectHandler[] ehs = new EffectHandler[widgets.length];
for (int i = 0; i < widgets.length; i++) {
Widget widget = widgets[i];
EffectHandler eh = Css3Util.getToolkit(widget).disappear(disappearEffect, visibilityModeStyle);
ehs[i] = eh;
}
return ehs;
}
public static EffectHandler[] appear(Widget... widgets) {
return appear(AppearEffectType.FADE_IN, widgets);
}
public static EffectHandler[] appear(AppearEffectType appearEffect, Widget... widgets) {
EffectHandler[] ehs = new EffectHandler[widgets.length];
for (int i = 0; i < widgets.length; i++) {
Widget widget = widgets[i];
EffectHandler eh = Css3Util.getToolkit(widget).appear(appearEffect);
ehs[i] = eh;
}
return ehs;
}
public EffectHandler disappear(VisibilityModeStyle visibilityModeStyle) {
return disappear(DisappearEffectType.FADE_OUT, visibilityModeStyle);
}
public EffectHandler disappear(final DisappearEffectType disappearEffect,
final VisibilityModeStyle visibilityModeStyle) {
return disappear(disappearEffect, visibilityModeStyle, 1000);
}
public EffectHandler disappear(final DisappearEffectType disappearEffect,
final VisibilityModeStyle visibilityModeStyle, int durationMs) {
return this.css3EffectQueue.disappear(theElement, disappearEffect, visibilityModeStyle, durationMs);
}
public EffectHandler appear() {
return appear(AppearEffectType.FADE_IN);
}
public EffectHandler appear(AppearEffectType appearEffect) {
return appear(appearEffect, 1000);
}
public EffectHandler appear(AppearEffectType appearEffect, int durationMs) {
return this.css3EffectQueue.appear(theElement, appearEffect, durationMs);
}
public EffectHandler resize(String width, String height) {
return resize(width, height, 1000);
}
public EffectHandler resize(String width, String height, int durationMs) {
return this.css3EffectQueue.resize(theElement, width, height, durationMs);
}
public boolean isAppeared() {
return this.css3EffectQueue.isAppeared(theElement);
}
public void disableTraceLog() {
this.css3EffectQueue.disableTraceLog();
}
public void enableTraceLog(String traceElementId) {
this.css3EffectQueue.enableTraceLog(traceElementId);
}
}
public static class Css3EffectQueue {
private boolean traceLog;
private enum EffectType {
APPEAR, DISAPPEAR, HIDE, RESIZE;
}
public class EffectHandler {
private Css3Effect pe;
protected EffectHandler(Css3Effect pe) {
this.pe = pe;
}
/*
* Esta clase está pensada para ir añadiendo métodos con los efectos
* y poder anexar efectos que en lugar de querer que se ejecuten en
* cascada, se ejecuten en paralelo.
*
* Estos método nunca llevaran el tiempo de duracción. Siempre se
* ejecutarán en el mismo que su "patrón" o efecto al que están
* enlazado y ejecutarán en paralelo. De esto modo no hay que
* complicar la lógica del evento de fin de transicción para saber
* cuando comenzar el siguiente en la cola.
*/
public EffectHandler appear(AppearEffectType appearEffect) {
Css3Effect attchFx = newAppearEffect(appearEffect, this.pe.duration, this.pe.cs);
if (this.pe.attachedEffects == null) {
this.pe.attachedEffects = new ArrayList();
}
this.pe.attachedEffects.add(attchFx);
return this;
}
public EffectHandler disappear(DisappearEffectType disappearEffect, VisibilityModeStyle visibilityModeStyle) {
Css3Effect attchFx = newDisappearEffect(disappearEffect, this.pe.duration, this.pe.cs);
if (this.pe.attachedEffects == null) {
this.pe.attachedEffects = new ArrayList();
}
this.pe.attachedEffects.add(attchFx);
return this;
}
public Css3Style getCss3Style() {
return pe.cs;
}
}
protected class Css3Effect {
protected EffectType et;
protected DisappearEffectType de;
protected AppearEffectType ae;
protected String width;
protected String height;
protected VisibilityModeStyle vms;
protected int duration = 1000;
protected Css3Style cs;
protected List attachedEffects;
}
private final List pendingEffects = new ArrayList();
private class ProcessNextPendingEffect extends TransitionEndListener {
private EffectType currentEffectType;
private boolean traceLog;
private String traceElementId;
public ProcessNextPendingEffect(EffectType currentEffectType, boolean traceLog, String traceElementId) {
this.currentEffectType = currentEffectType;
this.traceLog = traceLog;
this.traceElementId = traceElementId;
}
@Override
public void onTransitionEnd(NativeEvent e) {
logger.info(traceLog, "{0}: Resuelto efecto {1}", traceElementId, currentEffectType);
Element elm = (Element.is(e.getEventTarget()) ? Element.as(e.getEventTarget()) : null);
this.removeTransitionEndListener(elm);
resolvePendingEffects();
}
}
public enum DisappearEffectType {
FADE_OUT, MOVE_TO_LEFT_TOP, MOVE_TO_TOP, MOVE_TO_RIGHT_TOP, MOVE_TO_RIGHT, MOVE_TO_RIGHT_BOTTOM, MOVE_TO_BOTTOM, MOVE_TO_LEFT_BOTTOM, MOVE_TO_LEFT;
}
public enum AppearEffectType {
FADE_IN, MOVE_FROM_LEFT_TOP, MOVE_FROM_TOP, MOVE_FROM_RIGHT_TOP, MOVE_FROM_RIGHT, MOVE_FROM_RIGHT_BOTTOM, MOVE_FROM_BOTTOM, MOVE_FROM_LEFT_BOTTOM, MOVE_FROM_LEFT;
}
private boolean resolvingPendingEffects;
private Css3Effect resolvingThis;
private String traceElementId;
private TransitionEndListener lastTransitionEndListener;
private boolean autoRemoveLastTransitionEndListener;
public Css3EffectQueue() {
// Nada
}
protected void addPendingEffect(Css3Effect pedingEffect) {
logger.info(traceLog, "{0}: Añadiendo efecto {1}. Pendientes: {2}", this.traceElementId, pedingEffect.et,
this.pendingEffects.size());
this.pendingEffects.add(pedingEffect);
if (!this.resolvingPendingEffects) {
this.resolvingPendingEffects = true;
logger.info(traceLog, "{0}: Iniciando solucionador de efectos...", traceElementId);
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
@Override
public void execute() {
logger.info(traceLog, "{0}: Comenzando a resolver efectos...", traceElementId);
resolvePendingEffects();
}
});
} else {
logger.info(traceLog, "{0}: Esperamos. Actualmente resolviendo efecto pendiente: {1}...",
traceElementId, (this.resolvingThis != null) ? String.valueOf(this.resolvingThis.et)
: "-- ninguno --");
}
}
protected void resolvePendingEffects() {
if (!this.pendingEffects.isEmpty()) {
this.resolvingThis = this.pendingEffects.remove(0);
logger.info(traceLog, " {0}: Siguiente efecto a resolver {1}", traceElementId, this.resolvingThis.et);
resolveEffect(resolvingThis, true);
} else {
this.resolvingPendingEffects = false;
this.resolvingThis = null;
if (this.lastTransitionEndListener != null) {
this.lastTransitionEndListener.onTransitionEnd(null);
if (this.autoRemoveLastTransitionEndListener) {
this.lastTransitionEndListener = null;
}
}
logger.info(traceLog, " {0}: No hay más efectos pendientes", traceElementId);
}
}
protected void resolveEffect(Css3Effect pe, boolean proccessNext) {
logger.info(traceLog, "{0}: Resolviendo efecto {1}. Pendientes {2}", this.traceElementId, pe.et,
pendingEffects.size());
switch (pe.et) {
case APPEAR:
resolveAppear(pe.cs, pe.ae, pe.duration, proccessNext);
break;
case DISAPPEAR:
resolveDisappear(pe.cs, pe.de, pe.duration, proccessNext);
break;
case HIDE:
resolveHide(pe.cs, pe.vms, proccessNext);
break;
case RESIZE:
resolveResize(pe.cs, pe.width, pe.height, pe.duration, proccessNext);
break;
}
if (pe.attachedEffects != null) {
for (Css3Effect attchFx : pe.attachedEffects) {
resolveEffect(attchFx, false);
}
}
}
protected void resolveResize(final Css3Style css3Style, final String width, final String height, int duration,
final boolean proccessNext) {
final Style style = css3Style.element.getStyle();
getDefaultVisibleDisplay(css3Style.element);
style.setVisibility(com.google.gwt.dom.client.Style.Visibility.VISIBLE);
if (width != null) {
css3Style.setTransitionProperty("width", true);
css3Style.setTransitionDuration(duration + "ms");
css3Style.setTransitionTimingFunction("ease-in-out");
}
if (height != null) {
css3Style.setTransitionProperty("height", true);
css3Style.setTransitionDuration(duration + "ms");
css3Style.setTransitionTimingFunction("ease-in-out");
}
Scheduler.ScheduledCommand effectCommand = new Scheduler.ScheduledCommand() {
@Override
public void execute() {
boolean resolveWithListener = false;
/*
* Ancho
*/
if (width != null) {
String curWidth = style.getProperty("width");
int curOffsetWidth = css3Style.element.getOffsetWidth();
if (width.equals(curWidth)
|| (!width.contains("%") && JsUtil.extractNumberValue(width) == curOffsetWidth)) {
logger.info(traceLog, "{0}: Ancho {1}=={2} ó {1}=={3} (no se aplicarán cambios).",
traceElementId, width, curWidth, curOffsetWidth);
resolveWithListener |= false;
} else {
resolveWithListener |= true;
}
}
/*
* Alto
*/
if (height != null) {
String curHeight = style.getHeight();
int curOffsetHeight = css3Style.element.getOffsetHeight();
if (height.equals(curHeight)
|| (!height.contains("%") && JsUtil.extractNumberValue(height) == curOffsetHeight)) {
logger.info(traceLog, "{0}: Alto {1}=={2} ó {1}=={3} (no se aplicarán cambios).",
traceElementId, height, curHeight, curOffsetHeight);
resolveWithListener |= false;
} else {
resolveWithListener |= true;
}
}
/*
* Procesando
*/
if (proccessNext) {
if (!resolveWithListener) {
logger.info(traceLog, "{0}: Resuelto efecto {1} sin aplicar cambios.", traceElementId,
EffectType.RESIZE);
resolvePendingEffects();
} else {
css3Style.addTransitionEndListener(new ProcessNextPendingEffect(EffectType.RESIZE,
traceLog, traceElementId));
}
}
if (width != null) {
style.setProperty("width", width);
}
if (height != null) {
style.setProperty("height", height);
}
}
};
Scheduler.get().scheduleDeferred(effectCommand);
}
protected void resolveAppear(final Css3Style css3Style, final AppearEffectType appearEffect,
final int duration, final boolean mainEffect) {
Element parent = css3Style.element.getParentElement();
final Style style = css3Style.element.getStyle();
getDefaultVisibleDisplay(css3Style.element);
style.setVisibility(com.google.gwt.dom.client.Style.Visibility.VISIBLE);
Scheduler.ScheduledCommand effectCommand = null;
logger.info(traceLog, "{0}: Resolviendo appear: Efecto {1}; ¿Es principal? {2}", traceElementId,
appearEffect, mainEffect ? "SÍ" : "NO");
switch (appearEffect) {
case FADE_IN:
if (mainEffect) {
css3Style.setTransitionProperty("opacity", true);
css3Style.setTransitionDuration("0s");
style.setOpacity(0.0);
}
effectCommand = new Scheduler.ScheduledCommand() {
@Override
public void execute() {
css3Style.setTransitionProperty("opacity", true);
if (mainEffect) {
css3Style.setTransitionDuration(duration + "ms");
css3Style.setTransitionTimingFunction("ease-in-out");
css3Style.addTransitionEndListener(new ProcessNextPendingEffect(EffectType.APPEAR,
traceLog, traceElementId));
}
style.setOpacity(1.0);
}
};
break;
case MOVE_FROM_BOTTOM: {
if (mainEffect) {
css3Style.setTransitionProperty("left, top", true);
css3Style.setTransitionDuration("0s");
int top = (parent != null) ? parent.getClientHeight() : css3Style.element.getClientHeight();
style.setPosition(Position.RELATIVE);
if (parent != null) {
parent.getStyle().setOverflow(Overflow.HIDDEN);
}
style.setLeft(0.0, Unit.PX);
style.setTop(top, Unit.PX);
}
effectCommand = getAppearMoveEffectCommand(css3Style, style, duration, mainEffect);
break;
}
case MOVE_FROM_TOP: {
if (mainEffect) {
css3Style.setTransitionProperty("left, top", true);
css3Style.setTransitionDuration("0s");
int top = (parent != null) ? -parent.getClientHeight() : -css3Style.element.getClientHeight();
style.setPosition(Position.RELATIVE);
if (parent != null) {
parent.getStyle().setOverflow(Overflow.HIDDEN);
}
style.setLeft(0.0, Unit.PX);
style.setTop(top, Unit.PX);
}
effectCommand = getAppearMoveEffectCommand(css3Style, style, duration, mainEffect);
break;
}
case MOVE_FROM_LEFT: {
if (mainEffect) {
css3Style.setTransitionProperty("left, top", true);
css3Style.setTransitionDuration("0s");
int left = (parent != null) ? -parent.getClientWidth() : -css3Style.element.getClientWidth();
style.setPosition(Position.RELATIVE);
if (parent != null) {
parent.getStyle().setOverflow(Overflow.HIDDEN);
}
style.setLeft(left, Unit.PX);
style.setTop(0.0, Unit.PX);
}
effectCommand = getAppearMoveEffectCommand(css3Style, style, duration, mainEffect);
break;
}
case MOVE_FROM_RIGHT: {
if (mainEffect) {
css3Style.setTransitionProperty("left, top", true);
css3Style.setTransitionDuration("0s");
int left = (parent != null) ? parent.getClientWidth() : css3Style.element.getClientWidth();
style.setPosition(Position.RELATIVE);
if (parent != null) {
parent.getStyle().setOverflow(Overflow.HIDDEN);
}
style.setLeft(left, Unit.PX);
style.setTop(0.0, Unit.PX);
}
effectCommand = getAppearMoveEffectCommand(css3Style, style, duration, mainEffect);
break;
}
case MOVE_FROM_LEFT_BOTTOM: {
if (mainEffect) {
css3Style.setTransitionProperty("left, top", true);
css3Style.setTransitionDuration("0s");
int left = (parent != null) ? -parent.getClientWidth() : -css3Style.element.getClientWidth();
int top = (parent != null) ? parent.getClientHeight() : css3Style.element.getClientHeight();
style.setPosition(Position.RELATIVE);
if (parent != null) {
parent.getStyle().setOverflow(Overflow.HIDDEN);
}
style.setLeft(left, Unit.PX);
style.setTop(top, Unit.PX);
}
effectCommand = getAppearMoveEffectCommand(css3Style, style, duration, mainEffect);
break;
}
case MOVE_FROM_LEFT_TOP: {
if (mainEffect) {
css3Style.setTransitionProperty("left, top", true);
css3Style.setTransitionDuration("0s");
int left = (parent != null) ? -parent.getClientWidth() : -css3Style.element.getClientWidth();
int top = (parent != null) ? -parent.getClientHeight() : -css3Style.element.getClientHeight();
style.setPosition(Position.RELATIVE);
if (parent != null) {
parent.getStyle().setOverflow(Overflow.HIDDEN);
}
style.setLeft(left, Unit.PX);
style.setTop(top, Unit.PX);
}
effectCommand = getAppearMoveEffectCommand(css3Style, style, duration, mainEffect);
break;
}
case MOVE_FROM_RIGHT_BOTTOM: {
if (mainEffect) {
css3Style.setTransitionProperty("left, top", true);
css3Style.setTransitionDuration("0s");
int left = (parent != null) ? parent.getClientWidth() : css3Style.element.getClientWidth();
int top = (parent != null) ? parent.getClientHeight() : css3Style.element.getClientHeight();
style.setPosition(Position.RELATIVE);
if (parent != null) {
parent.getStyle().setOverflow(Overflow.HIDDEN);
}
style.setLeft(left, Unit.PX);
style.setTop(top, Unit.PX);
}
effectCommand = getAppearMoveEffectCommand(css3Style, style, duration, mainEffect);
break;
}
case MOVE_FROM_RIGHT_TOP: {
if (mainEffect) {
css3Style.setTransitionProperty("left, top", true);
css3Style.setTransitionDuration("0s");
int left = (parent != null) ? parent.getClientWidth() : css3Style.element.getClientWidth();
int top = (parent != null) ? -parent.getClientHeight() : -css3Style.element.getClientHeight();
style.setPosition(Position.RELATIVE);
if (parent != null) {
parent.getStyle().setOverflow(Overflow.HIDDEN);
}
style.setLeft(left, Unit.PX);
style.setTop(top, Unit.PX);
}
effectCommand = getAppearMoveEffectCommand(css3Style, style, duration, mainEffect);
break;
}
}
Scheduler.get().scheduleDeferred(effectCommand);
}
protected void resolveDisappear(final Css3Style css3Style, final DisappearEffectType disappearEffect,
final int duration, final boolean mainEffect) {
final Element parent = css3Style.element.getParentElement();
Scheduler.ScheduledCommand effectCommand = null;
switch (disappearEffect) {
case FADE_OUT:
if (mainEffect) {
css3Style.setTransitionTimingFunction("ease-in-out");
css3Style.setTransitionProperty("opacity", true);
css3Style.setTransitionDuration(duration + "ms");
}
effectCommand = new Scheduler.ScheduledCommand() {
@Override
public void execute() {
if (mainEffect) {
css3Style.setTransitionTimingFunction("ease-in-out");
css3Style.setTransitionProperty("opacity", true);
css3Style.setTransitionProperty("left, top", true);
}
double currentOpacity = JsUtil.extractNumberValue(getStyleProperty(css3Style.element, "opacity"));
/*
* Como no cambie nada el efecto el evento endTransition
* no se lanza y perdemos seguir con el siguiente efecto
*/
if (currentOpacity != 0.0) {
if (mainEffect) {
ProcessNextPendingEffect transitionEndListener = new ProcessNextPendingEffect(
EffectType.DISAPPEAR, traceLog, traceElementId);
css3Style.addTransitionEndListener(transitionEndListener);
}
css3Style.element.getStyle().setOpacity(0.0);
} else {
logger.info(traceLog, "{0}: Resuelto efecto {1} sin aplicar cambios.", traceElementId,
EffectType.DISAPPEAR);
resolvePendingEffects();
}
}
};
break;
case MOVE_TO_LEFT_BOTTOM:
configDisappearMoveProperties(css3Style, parent, mainEffect);
effectCommand = new Scheduler.ScheduledCommand() {
@Override
public void execute() {
if (mainEffect) {
css3Style.setTransitionDuration(duration + "ms");
css3Style.setTransitionTimingFunction("ease-in-out");
css3Style.setTransitionProperty("left, top", true);
}
double left = (parent != null) ? -parent.getOffsetWidth() : -css3Style.element.getOffsetWidth();
double top = (parent != null) ? parent.getOffsetHeight() : css3Style.element.getOffsetHeight();
double curLeft = css3Style.element.getOffsetLeft();
double curTop = css3Style.element.getOffsetTop();
if (curLeft == left && curTop == top) {
logger.info(traceLog, "{0}: Resuelto efecto {1} sin aplicar cambios.", traceElementId,
EffectType.DISAPPEAR);
resolvePendingEffects();
} else {
if (mainEffect) {
css3Style.addTransitionEndListener(new ProcessNextPendingEffect(EffectType.DISAPPEAR,
traceLog, traceElementId));
}
css3Style.element.getStyle().setLeft(left, Unit.PX);
css3Style.element.getStyle().setTop(top, Unit.PX);
}
}
};
break;
case MOVE_TO_BOTTOM:
configDisappearMoveProperties(css3Style, parent, mainEffect);
effectCommand = new Scheduler.ScheduledCommand() {
@Override
public void execute() {
if (mainEffect) {
css3Style.setTransitionDuration(duration + "ms");
css3Style.setTransitionTimingFunction("ease-in-out");
css3Style.setTransitionProperty("left, top", true);
}
int top = (parent != null) ? parent.getOffsetHeight() : css3Style.element.getOffsetHeight();
int curTop = css3Style.element.getOffsetTop();
if (curTop == top) {
logger.info(traceLog, "{0}: Resuelto efecto {1} sin aplicar cambios.", traceElementId,
EffectType.DISAPPEAR);
resolvePendingEffects();
} else {
if (mainEffect) {
css3Style.addTransitionEndListener(new ProcessNextPendingEffect(EffectType.DISAPPEAR,
traceLog, traceElementId));
}
css3Style.element.getStyle().setTop(top, Unit.PX);
}
}
};
break;
case MOVE_TO_LEFT:
configDisappearMoveProperties(css3Style, parent, mainEffect);
effectCommand = new Scheduler.ScheduledCommand() {
@Override
public void execute() {
if (mainEffect) {
css3Style.setTransitionDuration(duration + "ms");
css3Style.setTransitionTimingFunction("ease-in-out");
css3Style.setTransitionProperty("left, top", true);
}
int left = (parent != null) ? -parent.getOffsetWidth() : -css3Style.element.getOffsetWidth();
int curLeft = css3Style.element.getOffsetLeft();
if (curLeft == left) {
logger.info(traceLog, "{0}: Resuelto efecto {1} sin aplicar cambios.", traceElementId,
EffectType.DISAPPEAR);
resolvePendingEffects();
} else {
if (mainEffect) {
css3Style.addTransitionEndListener(new ProcessNextPendingEffect(EffectType.DISAPPEAR,
traceLog, traceElementId));
}
css3Style.element.getStyle().setLeft(left, Unit.PX);
}
}
};
break;
case MOVE_TO_LEFT_TOP:
configDisappearMoveProperties(css3Style, parent, mainEffect);
effectCommand = new Scheduler.ScheduledCommand() {
@Override
public void execute() {
if (mainEffect) {
css3Style.setTransitionDuration(duration + "ms");
css3Style.setTransitionTimingFunction("ease-in-out");
css3Style.setTransitionProperty("left, top", true);
}
int left = (parent != null) ? -parent.getOffsetWidth() : -css3Style.element.getOffsetWidth();
int top = (parent != null) ? -parent.getOffsetHeight() : -css3Style.element.getOffsetHeight();
int curLeft = css3Style.element.getOffsetLeft();
int curTop = css3Style.element.getOffsetTop();
if (curLeft == left && curTop == top) {
logger.info(traceLog, "{0}: Resuelto efecto {1} sin aplicar cambios.", traceElementId,
EffectType.DISAPPEAR);
resolvePendingEffects();
} else {
if (mainEffect) {
css3Style.addTransitionEndListener(new ProcessNextPendingEffect(EffectType.DISAPPEAR,
traceLog, traceElementId));
}
css3Style.element.getStyle().setLeft(left, Unit.PX);
css3Style.element.getStyle().setTop(top, Unit.PX);
}
}
};
break;
case MOVE_TO_RIGHT:
configDisappearMoveProperties(css3Style, parent, mainEffect);
effectCommand = new Scheduler.ScheduledCommand() {
@Override
public void execute() {
if (mainEffect) {
css3Style.setTransitionDuration(duration + "ms");
css3Style.setTransitionTimingFunction("ease-in-out");
css3Style.setTransitionProperty("left, top", true);
}
int left = (parent != null) ? parent.getOffsetWidth() : css3Style.element.getOffsetWidth();
int curLeft = css3Style.element.getOffsetLeft();
if (curLeft == left) {
logger.info(traceLog, "{0}: Resuelto efecto {1} sin aplicar cambios.", traceElementId,
EffectType.DISAPPEAR);
resolvePendingEffects();
} else {
if (mainEffect) {
css3Style.addTransitionEndListener(new ProcessNextPendingEffect(EffectType.DISAPPEAR,
traceLog, traceElementId));
}
css3Style.element.getStyle().setLeft(left, Unit.PX);
}
}
};
break;
case MOVE_TO_RIGHT_BOTTOM:
configDisappearMoveProperties(css3Style, parent, mainEffect);
effectCommand = new Scheduler.ScheduledCommand() {
@Override
public void execute() {
if (mainEffect) {
css3Style.setTransitionDuration(duration + "ms");
css3Style.setTransitionTimingFunction("ease-in-out");
css3Style.setTransitionProperty("left, top", true);
}
int left = (parent != null) ? parent.getOffsetWidth() : css3Style.element.getOffsetWidth();
int top = (parent != null) ? parent.getOffsetHeight() : css3Style.element.getOffsetHeight();
int curLeft = css3Style.element.getOffsetLeft();
int curTop = css3Style.element.getOffsetTop();
if (curLeft == left && curTop == top) {
logger.info(traceLog, "{0}: Resuelto efecto {1} sin aplicar cambios.", traceElementId,
EffectType.DISAPPEAR);
resolvePendingEffects();
} else {
if (mainEffect) {
css3Style.addTransitionEndListener(new ProcessNextPendingEffect(EffectType.DISAPPEAR,
traceLog, traceElementId));
}
css3Style.element.getStyle().setLeft(left, Unit.PX);
css3Style.element.getStyle().setTop(top, Unit.PX);
}
}
};
break;
case MOVE_TO_RIGHT_TOP:
configDisappearMoveProperties(css3Style, parent, mainEffect);
effectCommand = new Scheduler.ScheduledCommand() {
@Override
public void execute() {
if (mainEffect) {
css3Style.setTransitionDuration(duration + "ms");
css3Style.setTransitionTimingFunction("ease-in-out");
css3Style.setTransitionProperty("left, top", true);
}
int left = (parent != null) ? parent.getOffsetWidth() : css3Style.element.getOffsetWidth();
int top = (parent != null) ? -parent.getOffsetHeight() : -css3Style.element.getOffsetHeight();
int curLeft = css3Style.element.getOffsetLeft();
int curTop = css3Style.element.getOffsetTop();
if (curLeft == left && curTop == top) {
logger.info(traceLog, "{0}: Resuelto efecto {1} sin aplicar cambios.", traceElementId,
EffectType.DISAPPEAR);
resolvePendingEffects();
} else {
if (mainEffect) {
css3Style.addTransitionEndListener(new ProcessNextPendingEffect(EffectType.DISAPPEAR,
traceLog, traceElementId));
}
css3Style.element.getStyle().setLeft(left, Unit.PX);
css3Style.element.getStyle().setTop(top, Unit.PX);
}
}
};
break;
case MOVE_TO_TOP:
configDisappearMoveProperties(css3Style, parent, mainEffect);
effectCommand = new Scheduler.ScheduledCommand() {
@Override
public void execute() {
if (mainEffect) {
css3Style.setTransitionDuration(duration + "ms");
css3Style.setTransitionTimingFunction("ease-in-out");
css3Style.setTransitionProperty("left, top", true);
}
int top = (parent != null) ? -parent.getOffsetHeight() : -css3Style.element.getOffsetHeight();
int curTop = css3Style.element.getOffsetTop();
if (curTop == top) {
logger.info(traceLog, "{0}: Resuelto efecto {1} sin aplicar cambios.", traceElementId,
EffectType.DISAPPEAR);
resolvePendingEffects();
} else {
if (mainEffect) {
css3Style.addTransitionEndListener(new ProcessNextPendingEffect(EffectType.DISAPPEAR,
traceLog, traceElementId));
}
css3Style.element.getStyle().setTop(top, Unit.PX);
}
}
};
break;
default:
throw new IllegalArgumentException("Efecto de desaparición no entendido por el código: "
+ disappearEffect);
}
Scheduler.get().scheduleDeferred(effectCommand);
}
protected void resolveHide(final Css3Style css3Style, final VisibilityModeStyle visibilityModeStyle,
boolean proccessNext) {
if (visibilityModeStyle == VisibilityModeStyle.USE_DISPLAY_PROPERTY) {
css3Style.element.getStyle().setDisplay(Display.NONE);
} else {
css3Style.element.getStyle().setVisibility(com.google.gwt.dom.client.Style.Visibility.HIDDEN);
}
resolvePendingEffects();
}
private void configDisappearMoveProperties(final Css3Style css3Style, Element parent, boolean mainEffect) {
if (parent != null) {
parent.getStyle().setOverflow(Overflow.HIDDEN);
}
if (mainEffect) {
css3Style.setTransitionDuration("0s");
css3Style.element.getStyle().setLeft(0.0, Unit.PX);
css3Style.element.getStyle().setTop(0.0, Unit.PX);
}
css3Style.element.getStyle().setPosition(Position.RELATIVE);
}
private ScheduledCommand getAppearMoveEffectCommand(final Css3Style css3Style, final Style style,
final int duration, final boolean mainEffect) {
return new ScheduledCommand() {
@Override
public void execute() {
double left = JsUtil.extractNumberValue(style.getLeft());
double top = JsUtil.extractNumberValue(style.getTop());
if (left == 0.0 && top == 0.0) {
logger.info(traceLog, "{0}: Resuelto efecto {1} sin aplicar cambios.", traceElementId,
EffectType.APPEAR);
if (mainEffect) {
resolvePendingEffects();
}
} else {
css3Style.setTransitionProperty("left, top", true);
if (mainEffect) {
css3Style.setTransitionDuration(duration + "ms");
css3Style.setTransitionTimingFunction("ease-in-out");
css3Style.addTransitionEndListener(new ProcessNextPendingEffect(EffectType.APPEAR,
traceLog, traceElementId));
}
style.setLeft(0.0, Unit.PX);
style.setTop(0.0, Unit.PX);
}
}
};
}
public EffectHandler disappear(Widget widget, final DisappearEffectType disappearEffect,
final VisibilityModeStyle visibilityModeStyle, int durationMs) {
return disappear(widget.getElement(), disappearEffect, visibilityModeStyle, durationMs);
}
public EffectHandler disappear(Element theElement, final DisappearEffectType disappearEffect,
final VisibilityModeStyle visibilityModeStyle, int durationMs) {
Css3Style css3Style = Css3Util.getStyle(theElement);
Css3Effect disappear = newDisappearEffect(disappearEffect, durationMs, css3Style);
Css3Effect hide = newHideEffect(visibilityModeStyle, css3Style);
addPendingEffect(disappear);
addPendingEffect(hide);
return new EffectHandler(/* el último */hide);
}
public EffectHandler appear(Widget widget, AppearEffectType appearEffect, int durationMs) {
return this.appear(widget.getElement(), appearEffect, durationMs);
}
public EffectHandler appear(Element theElement, AppearEffectType appearEffect, int durationMs) {
Css3Style css3Style = Css3Util.getStyle(theElement);
Css3Effect appear = newAppearEffect(appearEffect, durationMs, css3Style);
addPendingEffect(appear);
return new EffectHandler(appear);
}
public EffectHandler resize(Widget widget, String width, String height, int durationMs) {
return resize(widget.getElement(), width, height, durationMs);
}
public EffectHandler resize(Element theElement, String width, String height, int durationMs) {
Css3Style css3Style = Css3Util.getStyle(theElement);
Css3Effect resize = newResizeEffect(width, height, durationMs, css3Style);
addPendingEffect(resize);
return new EffectHandler(resize);
}
public boolean isAppeared(Element theElement) {
for (int i = pendingEffects.size() - 1; i >= 0; i--) {
switch (pendingEffects.get(i).et) {
case APPEAR:
return true;
case DISAPPEAR:
return false;
case HIDE:
return false;
default:
// Sigue buscando
}
}
if (this.resolvingThis != null) {
switch (this.resolvingThis.et) {
case APPEAR:
return true;
case DISAPPEAR:
return false;
case HIDE:
return false;
default:
// Sigue buscando
}
}
Style style = theElement.getStyle();
String strOpacity = style.getOpacity();
double opacity = (strOpacity != null && !strOpacity.isEmpty()) ? JsUtil.extractNumberValue(strOpacity)
: 1.0;
String display = style.getDisplay();
String visibility = style.getVisibility();
boolean appeared = (opacity == 1.0) && !("none".equals(display)) && !("hidden".equals(visibility));
return appeared;
}
public boolean isTraceLog() {
return traceLog;
}
public void disableTraceLog() {
this.traceLog = false;
}
public void enableTraceLog(String traceElementId) {
this.traceLog = true;
this.traceElementId = traceElementId;
}
public void cancelPending() {
logger.info(traceLog, " {0}: Cancelando todos los efectos pendientes", traceElementId);
this.pendingEffects.clear();
this.resolvingPendingEffects = false;
this.resolvingThis = null;
}
public void setLastTransitionEndListener(boolean autoRemove, TransitionEndListener lastTransitionEndListener) {
this.lastTransitionEndListener = lastTransitionEndListener;
this.autoRemoveLastTransitionEndListener = autoRemove;
}
private Css3Effect newAppearEffect(AppearEffectType appearEffect, int durationMs, Css3Style css3Style) {
Css3Effect appear = new Css3Effect();
appear.et = EffectType.APPEAR;
appear.ae = appearEffect;
appear.cs = css3Style;
appear.duration = durationMs;
return appear;
}
private Css3Effect newResizeEffect(String width, String height, int durationMs, Css3Style css3Style) {
Css3Effect resize = new Css3Effect();
resize.et = EffectType.RESIZE;
resize.width = width;
resize.height = height;
resize.cs = css3Style;
resize.duration = durationMs;
return resize;
}
private Css3Effect newHideEffect(final VisibilityModeStyle visibilityModeStyle, Css3Style css3Style) {
Css3Effect hide = new Css3Effect();
hide.et = EffectType.HIDE;
hide.vms = visibilityModeStyle;
hide.cs = css3Style;
return hide;
}
private Css3Effect newDisappearEffect(final DisappearEffectType disappearEffect, int durationMs,
Css3Style css3Style) {
Css3Effect disappear = new Css3Effect();
disappear.et = EffectType.DISAPPEAR;
disappear.de = disappearEffect;
disappear.cs = css3Style;
disappear.duration = durationMs;
return disappear;
}
}
public static abstract class TransitionEndListener {
private JavaScriptObject callback;
public abstract void onTransitionEnd(NativeEvent e);
@SuppressWarnings("unused")
final private void setCallback(JavaScriptObject callback) {
this.callback = callback;
}
final public void removeTransitionEndListener(Element element) {
if (element != null) {
Css3Util.getStyle(element).removeTransitionEndListener(this);
}
}
}
public static native String getStyleProperty(Element el, String prop) /*-{
var computedStyle;
if (document.defaultView && document.defaultView.getComputedStyle) { // standard (includes ie9)
computedStyle = document.defaultView.getComputedStyle(el, null)[prop];
} else if (el.currentStyle) { // IE older
computedStyle = el.currentStyle[prop];
} else { // inline style
computedStyle = el.style[prop];
}
return computedStyle;
}-*/;
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy