com.sencha.gxt.core.client.dom.Layer.java Source code

Java tutorial

Introduction

Here is the source code for com.sencha.gxt.core.client.dom.Layer.java

Source

/**
 * Sencha GXT 4.0.0 - Sencha for GWT
 * Copyright (c) 2006-2015, Sencha Inc.
 *
 * licensing@sencha.com
 * http://www.sencha.com/products/gxt/license/
 *
 * ================================================================================
 * Open Source License
 * ================================================================================
 * This version of Sencha GXT is licensed under the terms of the Open Source GPL v3
 * license. You may use this license only if you are prepared to distribute and
 * share the source code of your application under the GPL v3 license:
 * http://www.gnu.org/licenses/gpl.html
 *
 * If you are NOT prepared to distribute and share the source code of your
 * application under the GPL v3 license, other commercial and oem licenses
 * are available for an alternate download of Sencha GXT.
 *
 * Please see the Sencha GXT Licensing page at:
 * http://www.sencha.com/products/gxt/license/
 *
 * For clarification or additional options, please contact:
 * licensing@sencha.com
 * ================================================================================
 *
 *
 * ================================================================================
 * Disclaimer
 * ================================================================================
 * THIS SOFTWARE IS DISTRIBUTED "AS-IS" WITHOUT ANY WARRANTIES, CONDITIONS AND
 * REPRESENTATIONS WHETHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE
 * IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, MERCHANTABLE QUALITY,
 * FITNESS FOR A PARTICULAR PURPOSE, DURABILITY, NON-INFRINGEMENT, PERFORMANCE AND
 * THOSE ARISING BY STATUTE OR FROM CUSTOM OR USAGE OF TRADE OR COURSE OF DEALING.
 * ================================================================================
 */
package com.sencha.gxt.core.client.dom;

import java.util.Stack;

import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Style.Display;
import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.CssResource;
import com.google.gwt.resources.client.ImageResource;
import com.google.gwt.resources.client.ImageResource.ImageOptions;
import com.google.gwt.resources.client.ImageResource.RepeatStyle;
import com.google.gwt.safehtml.shared.SafeHtml;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.sencha.gxt.core.client.GXT;
import com.sencha.gxt.core.client.XTemplates;
import com.sencha.gxt.core.client.resources.CommonStyles;
import com.sencha.gxt.core.client.util.Rectangle;

/**
 * Wraps a <code>XElement</code> and provides support for shadows and shimming.
 */
public class Layer {

    public interface LayerAppearance {

        int getShadowOffset();

        void renderShadow(SafeHtmlBuilder sb);

        String shimClass();

    }

    public static class LayerBaseAppearance implements LayerAppearance {

        private final LayerStyle style;
        private final LayerTemplates templates;

        public LayerBaseAppearance() {
            this(GWT.<LayerResources>create(LayerResources.class),
                    GWT.<LayerTemplates>create(LayerTemplates.class));
        }

        public LayerBaseAppearance(LayerResources resources, LayerTemplates templates) {
            this.templates = templates;
            style = resources.style();
            style.ensureInjected();
        }

        @Override
        public int getShadowOffset() {
            return style.shadowOffset();
        }

        @Override
        public void renderShadow(SafeHtmlBuilder sb) {
            sb.append(templates.shadow(style, CommonStyles.get().ignore()));
        }

        @Override
        public String shimClass() {
            return style.shim();
        }

    }

    public static class LayerBaseAppearanceIe implements LayerAppearance {

        private LayerStyleIe style;
        private LayerTemplatesIe templates;

        public LayerBaseAppearanceIe() {
            this(GWT.<LayerResourcesIe>create(LayerResourcesIe.class),
                    GWT.<LayerTemplatesIe>create(LayerTemplatesIe.class));
        }

        public LayerBaseAppearanceIe(LayerResourcesIe resources, LayerTemplatesIe templates) {
            this.templates = templates;
            style = resources.style();
            style.ensureInjected();
        }

        @Override
        public int getShadowOffset() {
            return style.shadowOffset();
        }

        @Override
        public void renderShadow(SafeHtmlBuilder sb) {
            sb.append(templates.shadow(style, CommonStyles.get().ignore()));
        }

        @Override
        public String shimClass() {
            return style.shim();
        }

    }

    public interface LayerResources extends ClientBundle {

        @ImageOptions(repeatStyle = RepeatStyle.Horizontal)
        ImageResource bottomCenter();

        ImageResource bottomLeft();

        @ImageOptions(repeatStyle = RepeatStyle.Horizontal)
        ImageResource bottomRight();

        @ImageOptions(repeatStyle = RepeatStyle.Both)
        ImageResource middleCenter();

        @ImageOptions(repeatStyle = RepeatStyle.Vertical)
        ImageResource middleLeft();

        @ImageOptions(repeatStyle = RepeatStyle.Vertical)
        ImageResource middleRight();

        @Source("Layer.gss")
        LayerStyle style();

        @ImageOptions(repeatStyle = RepeatStyle.Horizontal)
        ImageResource topCenter();

        ImageResource topLeft();

        ImageResource topRight();

    }

    public interface LayerResourcesIe extends ClientBundle {

        @Source("LayerIe.gss")
        LayerStyleIe style();

    }

    public interface LayerStyle extends CssResource {

        String bottom();

        String bottomCenter();

        String bottomLeft();

        String bottomRight();

        String middle();

        String middleCenter();

        String middleLeft();

        String middleRight();

        String shadow();

        int shadowOffset();

        String shim();

        String top();

        String topCenter();

        String topLeft();

        String topRight();

    }

    public interface LayerStyleIe extends CssResource {

        String shadow();

        int shadowOffset();

        String shim();

    }

    public interface LayerTemplates extends XTemplates {

        @XTemplate(source = "Layer.html")
        SafeHtml shadow(LayerStyle style, String ignoreClass);

    }

    public interface LayerTemplatesIe extends XTemplates {

        @XTemplate("<div class=\"{style.shadow} {ignoreClass}\"></div>")
        SafeHtml shadow(LayerStyleIe style, String ignoreClass);

    }

    /**
     * Shadow position enumeration.
     */
    public enum ShadowPosition {
        DROP, FRAME, SIDES
    }

    public interface ShimTemplates extends XTemplates {

        @XTemplate("<iframe frameborder=\"no\" frameBorder=\"no\" class=\"{shimClass} {ignoreClass}\" tabIndex=\"-1\" style=\"visibility:hidden;display:none\" role=\"presentation\"></iframe>")
        SafeHtml template(String shimClass, String ignoreClass);

    }

    private static Stack<XElement> shadows = new Stack<XElement>();

    private static Stack<XElement> shims = new Stack<XElement>();

    private final LayerAppearance appearance;
    private XElement elem;
    private XElement shadow;
    private Rectangle shadowAdjusts;
    private boolean shadowEnabled;
    private ShadowPosition shadowPosition;
    private XElement shim;

    private boolean shimEnabled;
    private boolean isLegacyIELayer = GXT.isIE8() || GXT.isIE9();

    public Layer(XElement elem) {
        this(elem, GWT.<LayerAppearance>create(LayerAppearance.class));
    }

    public Layer(XElement elem, LayerAppearance appearance) {
        this.elem = elem;
        this.appearance = appearance;
        bind(elem);
        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;
    }

    public LayerAppearance getAppearance() {
        return appearance;
    }

    public XElement getElement() {
        return elem;
    }

    /**
     * Returns the layer's shadow.
     *
     * @return the shadow or null
     */
    public XElement getShadow() {
        XElement pn = elem.getParentElement().<XElement>cast();
        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, elem);
        shadow.setZIndex(elem.getZIndex() - 1);
        return shadow;
    }

    /**
     * Returns the shadow offset.
     *
     * @return the shadow offset
     */
    public int getShadowOffset() {
        return appearance.getShadowOffset();
    }

    /**
     * Returns the shadow position.
     *
     * @return the shadow position
     */
    public ShadowPosition getShadowPosition() {
        return shadowPosition;
    }

    /**
     * Returns the layer's shim.
     *
     * @return the shim
     */
    public XElement getShim() {
        XElement pn = elem.getParentElement().<XElement>cast();
        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, elem);
        shim.getStyle().setZIndex(elem.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;
    }

    /**
     * Sets the shadow position (defaults to SIDES).
     *
     * @param shadowPosition the position
     */
    public void setShadowPosition(ShadowPosition shadowPosition) {
        this.shadowPosition = shadowPosition;
        int shadowOffset = appearance.getShadowOffset();
        int radius = shadowOffset / 2;
        shadowAdjusts = new Rectangle();
        switch (shadowPosition) {
        case SIDES:
            shadowAdjusts.setWidth(shadowOffset * 2);
            shadowAdjusts.setX(-shadowOffset);
            shadowAdjusts.setY(shadowOffset - 1);
            if (isLegacyIELayer) {
                shadowAdjusts.setX(shadowAdjusts.getX() - (shadowOffset - radius));
                shadowAdjusts.setY(shadowAdjusts.getY() - (shadowOffset + radius));
                shadowAdjusts.setX(shadowAdjusts.getX() + 1);
                shadowAdjusts.setWidth(shadowAdjusts.getWidth() - (shadowOffset - radius) * 2);
                shadowAdjusts.setWidth(shadowAdjusts.getWidth() - (radius + 1));
                shadowAdjusts.setHeight(shadowAdjusts.getHeight() - 1);
            }
            break;
        case FRAME:
            shadowAdjusts.setWidth(shadowOffset * 2);
            shadowAdjusts.setHeight(shadowOffset * 2);
            shadowAdjusts.setX(-shadowOffset);
            shadowAdjusts.setY(-shadowOffset);
            shadowAdjusts.setY(shadowAdjusts.getY() + 1);

            shadowAdjusts.setHeight(shadowAdjusts.getHeight() - 2);

            if (isLegacyIELayer) {
                shadowAdjusts.setX(shadowAdjusts.getX() - (shadowOffset - radius));
                shadowAdjusts.setY(shadowAdjusts.getY() - (shadowOffset - radius));
                shadowAdjusts.setWidth(shadowAdjusts.getWidth() - (shadowOffset + radius) + 1);
                shadowAdjusts.setHeight(shadowAdjusts.getHeight() - (shadowOffset + radius) + 3);
            }
            break;
        default:
            shadowAdjusts.setWidth(0);
            shadowAdjusts.setY(shadowOffset);
            shadowAdjusts.setX(shadowAdjusts.getY());
            shadowAdjusts.setY(shadowAdjusts.getY() - 1);

            if (isLegacyIELayer) {
                shadowAdjusts.setX(shadowAdjusts.getX() - (shadowOffset + radius));
                shadowAdjusts.setY(shadowAdjusts.getX());
                shadowAdjusts.setWidth(shadowAdjusts.getWidth() - radius);
                shadowAdjusts.setHeight(shadowAdjusts.getWidth());
                shadowAdjusts.setY(shadowAdjusts.getY() + 1);
            }
            break;
        }
    }

    /**
     * Syncs the layer with its element.
     *
     * @param show true to show the layer
     */
    public void sync(boolean show) {
        if (elem.isVisible() && (shadowEnabled || shimEnabled)) {
            int w = elem.getOffsetWidth();
            int h = elem.getOffsetHeight();
            int l = elem.getLeft();
            int t = elem.getTop();

            if (shadowEnabled && elem.getParentElement() != null) {
                if (shadow == null) {
                    shadow = getShadow();
                }
                if (show) {
                    shadow.show();
                    shadow.getStyle().setDisplay(Display.BLOCK);
                }
                shadow.setLeft(l + shadowAdjusts.getX());
                shadow.setTop(t + shadowAdjusts.getY());

                int sw = w + shadowAdjusts.getWidth();
                int sh = h + shadowAdjusts.getHeight();
                if (shadow.getOffsetWidth() != sw || shadow.getOffsetHeight() != sh) {
                    shadow.setSize(sw, sh);
                    if (!isLegacyIELayer) {
                        int width = Math.max(0, sw - 12);
                        XElement.as(shadow.getChildNodes().getItem(0).getChildNodes().getItem(1)).setWidth(width);
                        XElement.as(shadow.getChildNodes().getItem(1).getChildNodes().getItem(1)).setWidth(width);
                        XElement.as(shadow.getChildNodes().getItem(2).getChildNodes().getItem(1)).setWidth(width);
                        int height = Math.max(0, sh - 12);
                        XElement.as(shadow.getChildNodes().getItem(1)).setHeight(height);
                    }
                }
            }
            if (shimEnabled) {
                if (show) {
                    if (shim == null) {
                        shim = getShim();
                    }
                    shim.show();
                } else {
                    if (shim == null) {
                        return;
                    }
                }
                Rectangle a = shadow == null ? new Rectangle(0, 0, 0, 0) : shadowAdjusts;

                if (isLegacyIELayer && shadow != null && shadow.isVisible()) {
                    int shadowOffset = appearance.getShadowOffset();
                    w += shadowOffset * 2;
                    l -= shadowOffset;
                    t -= shadowOffset;
                    h += shadowOffset * 2;
                }

                try {
                    shim.setLeft(l + a.getX());
                    shim.setTop(t + a.getY());
                    shim.setWidth(w + a.getWidth());
                    shim.setHeight(h + a.getHeight());
                } catch (Exception e) {
                    GWT.log("shim error", e);
                }

            }
        }
    }

    private final native void bind(XElement elem) /*-{
                                                  elem.layer = this;
                                                  }-*/;

    private XElement createShadow() {
        XElement el;
        SafeHtmlBuilder sb = new SafeHtmlBuilder();
        appearance.renderShadow(sb);
        el = XDOM.create(sb.toSafeHtml()).cast();
        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 XElement createShim() {
        ShimTemplates shimTemplates = GWT.create(ShimTemplates.class);
        XElement shimElement = XDOM
                .create(shimTemplates.template(appearance.shimClass(), CommonStyles.get().ignore())).cast();
        if (GXT.isIE() && GXT.isSecure()) {
            shimElement.setPropertyString("src", GXT.getSslSecureUrl());
        }
        return shimElement;
    }

}