/* * Ext GWT 2.2.4 - Ext for GWT * Copyright(c) 2007-2010, Ext JS, LLC. * licensing@extjs.com * * http://extjs.com/license */ package com.extjs.gxt.ui.client.widget; import java.util.Stack; import com.extjs.gxt.ui.client.GXT; import com.extjs.gxt.ui.client.core.El; import com.extjs.gxt.ui.client.util.Markup; import com.extjs.gxt.ui.client.util.Rectangle; import com.google.gwt.core.client.GWT; import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.Element; import com.google.gwt.user.client.ui.Accessibility; /** * An extended {@link El} object that supports a shadow and shim, constrain to * viewport and automatic maintaining of shadow/shim positions. */ public class Layer extends El { public enum ShadowPosition { DROP, FRAME, SIDES; } private static Stack<El> shadows = new Stack<El>(); private static Stack<El> shims = new Stack<El>(); private El shadow; private Rectangle shadowAdjusts; private boolean shadowEnabled; private int shadowOffset = 4; private ShadowPosition shadowPosition; private El shim; private boolean shimEnabled; /** * Creates a new layer instance. */ public Layer() { super(DOM.createDiv()); setShadowPosition(ShadowPosition.SIDES); } /** * Creates a new layer instance wrapping the specified element. * * @param element the element */ public Layer(Element element) { super(element); makePositionable(); setShadowPosition(ShadowPosition.SIDES); } /** * Disables the shadow. */ public void disableShadow() { shadowEnabled = false; hideShadow(); } /** * Disables the shim. */ public void disableShim() { shimEnabled = false; hideShim(); } /** * Disables the shim and the shadow. */ public void disableUnders() { disableShadow(); disableShim(); } /** * Enables the shadow. */ public void enableShadow() { shadowEnabled = true; } /** * Enables the shim. */ public void enableShim() { shimEnabled = true; } /** * Returns the layer's shadow. * * @return the shadow or null */ public El getShadow() { El pn = getParent(); if (pn == null || !shadowEnabled) { hideShadow(); return null; } if (shadow != null) { return shadow; } shadow = shadows.size() > 0 ? shadows.pop() : null; if (shadow == null) { shadow = createShadow(); } pn.insertBefore(shadow.dom, dom); shadow.setZIndex(getZIndex() - 1); return shadow; } /** * Returns the shadow offset. * * @return the shadow offset */ public int getShadowOffset() { return shadowOffset; } /** * Returns the shadow position. * * @return the shadow position */ public ShadowPosition getShadowPosition() { return shadowPosition; } /** * Returns the layer's shim. * * @return the shim */ public El getShim() { El pn = getParent(); if (pn == null || !shimEnabled) { hideShim(); return null; } if (shim != null) { return shim; } shim = shims.size() > 0 ? shims.pop() : null; if (shim == null) { shim = createShim(); } pn.insertBefore(shim.dom, dom); shim.setZIndex(getZIndex() - 2); return shim; } /** * Hides the layer's shadow. */ public void hideShadow() { if (shadow != null) { shadow.hide(); shadow.removeFromParent(); shadows.push(shadow); shadow = null; } } /** * Hides the shim. */ public void hideShim() { if (shim != null) { shim.hide(); shim.removeFromParent(); shims.push(shim); shim = null; } } /** * Hides the shim and the shadow. */ public void hideUnders() { hideShadow(); hideShim(); } public boolean isShadow() { return shadowEnabled; } public boolean isShim() { return shimEnabled; } @Override public El remove() { super.remove(); hideUnders(); return this; } @Override public El setHeight(int height, boolean adjust) { super.setHeight(height, adjust); sync(true); return this; } @Override public El setHeight(String height) { super.setHeight(height); sync(true); return this; } @Override public El setLeft(int left) { super.setLeft(left); sync(true); return this; } /** * Sets the shadow offset (defaults to 4). * * @param shadowOffset the offset */ public void setShadowOffset(int shadowOffset) { this.shadowOffset = shadowOffset; setShadowPosition(shadowPosition); } /** * Sets the shadow position (defaults to SIDES). * * @param shadowPosition the position */ public void setShadowPosition(ShadowPosition shadowPosition) { this.shadowPosition = shadowPosition; int radius = shadowOffset / 2; shadowAdjusts = new Rectangle(); switch (shadowPosition) { case SIDES: shadowAdjusts.width = shadowOffset * 2; shadowAdjusts.x = -shadowOffset; shadowAdjusts.y = shadowOffset - 1; if (GXT.isIE) { shadowAdjusts.x -= (shadowOffset - radius); shadowAdjusts.y -= (shadowOffset + radius); shadowAdjusts.x += 1; shadowAdjusts.width -= (shadowOffset - radius) * 2; shadowAdjusts.width -= radius + 1; shadowAdjusts.height -= 1; } break; case FRAME: shadowAdjusts.width = shadowAdjusts.height = (shadowOffset * 2); shadowAdjusts.x = shadowAdjusts.y = -shadowOffset; shadowAdjusts.y += 1; shadowAdjusts.height -= 2; if (GXT.isIE) { shadowAdjusts.x -= (shadowOffset - radius); shadowAdjusts.y -= (shadowOffset - radius); shadowAdjusts.width -= (shadowOffset + radius); shadowAdjusts.width += 1; shadowAdjusts.height -= (shadowOffset + radius); shadowAdjusts.height += 3; } break; default: shadowAdjusts.width = 0; shadowAdjusts.x = shadowAdjusts.y = shadowOffset; shadowAdjusts.y -= 1; if (GXT.isIE) { shadowAdjusts.x -= shadowOffset + radius; shadowAdjusts.y -= shadowOffset + radius; shadowAdjusts.width -= radius; shadowAdjusts.height -= radius; shadowAdjusts.y += 1; } break; } } @Override public El setTop(int top) { super.setTop(top); sync(true); return this; } @Override public El setVisibility(boolean visible) { super.setVisibility(visible); if (!visible) { hideUnders(); } else { sync(true); } return this; } @Override public El setVisible(boolean visible) { super.setVisible(visible); if (!visible) { hideUnders(); } else { sync(true); } return this; } @Override public El setWidth(int width, boolean adjust) { super.setWidth(width, adjust); sync(true); return this; } @Override public El setWidth(String width) { super.setWidth(width); sync(true); return this; } @Override public El setZIndex(int zIndex) { super.setZIndex(zIndex); if (shadow != null) { shadow.setZIndex(zIndex - 1); } if (shim != null) { shim.setZIndex(zIndex - 2); } return this; } /** * Syncs the shadow and shim. * * @param show true to show */ @Override public El sync(boolean show) { super.sync(show); if (isVisible() && (shadowEnabled || shimEnabled)) { int w = getWidth(); int h = getHeight(); int l = getLeft(); int t = getTop(); if (shadowEnabled && getParent() != null) { if (shadow == null) { shadow = getShadow(); } if (show) { shadow.show(); } shadow.setLeft(l + shadowAdjusts.x); shadow.setTop(t + shadowAdjusts.y); int sw = w + shadowAdjusts.width; int sh = h + shadowAdjusts.height; if (shadow.getWidth() != sw || shadow.getHeight() != sh) { shadow.setSize(sw, sh); if (!GXT.isIE) { int width = Math.max(0, sw - 12); fly((Element) shadow.dom.getChildNodes().getItem(0).getChildNodes().getItem(1)).setWidth(width); fly((Element) shadow.dom.getChildNodes().getItem(1).getChildNodes().getItem(1)).setWidth(width); fly((Element) shadow.dom.getChildNodes().getItem(2).getChildNodes().getItem(1)).setWidth(width); int height = Math.max(0, sh - 12); fly((Element) shadow.dom.getChildNodes().getItem(1)).setHeight(height); } } } if (shimEnabled) { if (shim == null) { shim = getShim(); } if (show) { shim.show(); } Rectangle a = shadow == null ? new Rectangle(0, 0, 0, 0) : shadowAdjusts; if (GXT.isIE && shadow != null && shadow.isVisible()) { w += shadowOffset * 2; l -= shadowOffset; t -= shadowOffset; h += shadowOffset * 2; } try { shim.setLeft(l + a.x); shim.setTop(t + a.y); shim.setWidth(w + a.width); shim.setHeight(h + a.height); } catch (Exception e) { GWT.log("shim error", e); } } } return this; } private El createShadow() { El el; if (GXT.isIE) { el = new El(DOM.createDiv()); el.setStyleName("x-ie-shadow"); el.setStyleAttribute("filter", "progid:DXImageTransform.Microsoft.alpha(" + "opacity=50) progid:DXImageTransform.Microsoft.Blur(pixelradius=" + shadowOffset + ")"); } else { el = new El(Markup.SHADOW); } el.addStyleName("x-ignore"); el.hide(); return el; } /** * Creates an iframe shim for this element to keep selects and other windowed * objects from showing through. * * @return the new shim element */ private El createShim() { El el = new El(DOM.createIFrame()); el.dom.setPropertyString("frameborder", "no"); el.dom.setPropertyString("frameBorder", "no"); el.dom.setClassName("ext-shim"); el.setTabIndex(-1); el.setVisibility(true); el.setVisible(false); el.addStyleName("x-ignore"); if (GXT.isIE && GXT.isSecure) { el.dom.setPropertyString("src", GXT.SSL_SECURE_URL); } Accessibility.setRole(el.dom, "presentation"); return el; } }