com.eas.window.WindowPanel.java Source code

Java tutorial

Introduction

Here is the source code for com.eas.window.WindowPanel.java

Source

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.eas.window;

import com.eas.core.XElement;
import com.eas.window.events.ActivateEvent;
import com.eas.window.events.ActivateHandler;
import com.eas.window.events.BeforeCloseEvent;
import com.eas.window.events.BeforeCloseHandler;
import com.eas.window.events.ClosedEvent;
import com.eas.window.events.ClosedHandler;
import com.eas.window.events.DeactivateEvent;
import com.eas.window.events.DeactivateHandler;
import com.eas.window.events.MaximizeEvent;
import com.eas.window.events.MaximizeHandler;
import com.eas.window.events.MinimizeEvent;
import com.eas.window.events.MinimizeHandler;
import com.eas.window.events.MoveEvent;
import com.eas.window.events.MoveHandler;
import com.eas.window.events.RestoreEvent;
import com.eas.window.events.RestoreHandler;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.Node;
import com.google.gwt.dom.client.Style;
import com.google.gwt.event.dom.client.MouseDownEvent;
import com.google.gwt.event.dom.client.MouseDownHandler;
import com.google.gwt.event.dom.client.MouseMoveEvent;
import com.google.gwt.event.dom.client.MouseMoveHandler;
import com.google.gwt.event.dom.client.MouseUpEvent;
import com.google.gwt.event.dom.client.MouseUpHandler;
import com.google.gwt.event.logical.shared.OpenEvent;
import com.google.gwt.event.logical.shared.OpenHandler;
import com.google.gwt.event.logical.shared.ResizeEvent;
import com.google.gwt.event.logical.shared.ResizeHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HasAnimation;
import com.google.gwt.user.client.ui.HasHTML;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.dom.client.Document;

/**
 * 
 * @author mg
 */
public class WindowPanel extends DraggablePanel implements WindowUI, HasAnimation {

    protected static final String ACTIVE_SUFFIX_NAMNE = "active";

    public static class Caption extends HTML {

        public Caption(String aHtml) {
            super();
            setHTML(aHtml);
            setStyleName("window-caption");
        }
    }

    protected Widget captionWidget;
    protected VerticalPanel verticalPanel;
    protected JavaScriptObject transitionOnResizer;
    protected Widget verticalPanelContent;
    protected boolean animationEnabled = true;
    protected boolean movable = true;
    protected boolean maximized;
    protected boolean minimized;
    protected boolean active;
    protected boolean maximizable = true;
    protected boolean minimizable = true;
    protected boolean closable = true;

    public WindowPanel() {
        super(true);
        addDomHandler(new MouseDownHandler() {

            @Override
            public void onMouseDown(MouseDownEvent event) {
                focus();
            }
        }, MouseDownEvent.getType());
        verticalPanel = new VerticalPanel();
        super.setWidget(verticalPanel);
        setCaptionWidget(new Caption(""));
        setUndecorated(false);
        getElement().addClassName("window-panel");
        getElement().<XElement>cast().addResizingTransitionEnd(this);
        getMovableTarget().getElement().<XElement>cast().addResizingTransitionEnd(this);
    }

    @Override
    public HasHTML getCaptionWidget() {
        if (captionWidget instanceof HasHTML) {
            return (HasHTML) captionWidget;
        } else {
            return null;
        }
    }

    protected HandlerRegistration mdHandler;
    protected HandlerRegistration muHandler;
    protected HandlerRegistration mmHandler;

    protected int mouseScreenX;
    protected int mouseScreenY;
    protected int targetScrollLeft;
    protected int targetScrollTop;

    protected boolean dragged;

    @Override
    public final void setCaptionWidget(HasHTML aCaptionWidget) {
        if (captionWidget != aCaptionWidget) {
            if (captionWidget != null) {
                captionWidget.removeFromParent();
            }
            if (mdHandler != null) {
                mdHandler.removeHandler();
            }
            if (muHandler != null) {
                muHandler.removeHandler();
            }
            if (mmHandler != null) {
                mmHandler.removeHandler();
            }
            if (aCaptionWidget instanceof Widget) {
                captionWidget = (Widget) aCaptionWidget;
            } else {
                captionWidget = new Caption(aCaptionWidget.getHTML());
            }
            if (captionWidget != null) {
                mdHandler = captionWidget.addDomHandler(new MouseDownHandler() {

                    @Override
                    public void onMouseDown(MouseDownEvent event) {
                        event.preventDefault();
                        event.stopPropagation();
                        focus();
                        if (movable && !maximized) {
                            DOM.setCapture(captionWidget.getElement());
                            mouseScreenX = event.getScreenX();
                            mouseScreenY = event.getScreenY();
                            String tLeft = getMovableTarget().getElement().getStyle().getLeft();
                            targetScrollLeft = Integer.parseInt(tLeft.substring(0, tLeft.length() - 2));
                            String tTop = getMovableTarget().getElement().getStyle().getTop();
                            targetScrollTop = Integer.parseInt(tTop.substring(0, tTop.length() - 2));
                        }
                    }

                }, MouseDownEvent.getType());
                muHandler = captionWidget.addDomHandler(new MouseUpHandler() {

                    @Override
                    public void onMouseUp(MouseUpEvent event) {
                        dragged = false;
                        event.preventDefault();
                        event.stopPropagation();
                        if (movable && !maximized) {
                            DOM.releaseCapture(captionWidget.getElement());
                            endMoving();
                        }
                    }

                }, MouseUpEvent.getType());
                mmHandler = captionWidget.addDomHandler(new MouseMoveHandler() {

                    @Override
                    public void onMouseMove(MouseMoveEvent event) {
                        if (movable && !maximized) {
                            if (DOM.getCaptureElement() == captionWidget.getElement()) {
                                event.preventDefault();
                                event.stopPropagation();
                                int dx = event.getScreenX() - mouseScreenX;
                                int dy = event.getScreenY() - mouseScreenY;
                                if (!dragged && (dx != 0 || dy != 0)) {
                                    dragged = true;
                                    beginMoving();
                                }
                                setPosition(targetScrollLeft + dx >= 0 ? targetScrollLeft + dx : 0,
                                        targetScrollTop + dy >= 0 ? targetScrollTop + dy : 0);
                            }
                        }
                    }

                }, MouseMoveEvent.getType());
                verticalPanel.insert(captionWidget, 0);
            }
        }
    }

    @Override
    protected void decorate() {
        super.decorate();
        content.setStyleName("content-decor");
        if (isActive()) {
            content.addStyleDependentName(ACTIVE_SUFFIX_NAMNE);
        } else {
            content.removeStyleDependentName(ACTIVE_SUFFIX_NAMNE);
        }
        if (captionWidget != null) {
            captionWidget.getElement().getStyle().clearDisplay();
        }
    }

    @Override
    protected void undecorate() {
        super.undecorate();
        content.getElement().removeClassName("content-decor");
        content.getElement().removeClassName("content-decor-active");
        if (captionWidget != null) {
            captionWidget.getElement().getStyle().setDisplay(Style.Display.NONE);
        }
    }

    @Override
    public void setWidget(Widget w) {
        if (verticalPanelContent != null) {
            verticalPanelContent.getElement().<XElement>cast().removeTransitionEndListener(transitionOnResizer);
            verticalPanelContent.getElement().removeClassName("window-content");
            verticalPanelContent.removeFromParent();
        }
        verticalPanelContent = w;
        if (verticalPanelContent != null) {
            transitionOnResizer = verticalPanelContent.getElement().<XElement>cast().addResizingTransitionEnd(this);
            verticalPanel.add(verticalPanelContent);
            verticalPanelContent.getElement().addClassName("window-content");
        }
        if (isAttached()) {
            onResize();
        }
    }

    @Override
    public Widget getWidget() {
        return verticalPanelContent;
    }

    @Override
    protected boolean isNresizable() {
        return resizable && !maximized && !minimized;
    }

    @Override
    protected boolean isSresizable() {
        return resizable && !maximized && !minimized;
    }

    @Override
    protected boolean isWresizable() {
        return resizable && !maximized;
    }

    @Override
    protected boolean isEresizable() {
        return resizable && !maximized;
    }

    @Override
    public boolean isMinimized() {
        return minimized;
    }

    @Override
    public boolean isMaximized() {
        return maximized;
    }

    @Override
    public boolean isMinimizable() {
        return minimizable;
    }

    @Override
    public void setMinimizable(boolean minimizable) {
        this.minimizable = minimizable;
    }

    @Override
    public void setClosable(boolean closable) {
        this.closable = closable;
    }

    @Override
    public boolean isClosable() {
        return closable;
    }

    @Override
    public boolean isMaximizable() {
        return maximizable;
    }

    @Override
    public void setMaximizable(boolean maximizable) {
        this.maximizable = maximizable;
    }

    @Override
    public void maximize() {
        if (!maximized) {
            restoreSnapshot();
            maximized = true;
            updateDecorCursors();
            snapshotMetrics();
            // editing
            Element movableElement = getMovableTarget().getElement();
            Style targetStyle = getWidget().getElement().getStyle(); // content
            int leftInset = getWidget().getElement().getAbsoluteLeft() - movableElement.getAbsoluteLeft();
            int rightInset = movableElement.getAbsoluteRight() - getWidget().getElement().getAbsoluteRight();
            int hInsets = leftInset + rightInset;
            int topInset = getWidget().getElement().getAbsoluteTop() - movableElement.getAbsoluteTop();
            int bottomInset = movableElement.getAbsoluteBottom() - getWidget().getElement().getAbsoluteBottom();
            int vInsets = topInset + bottomInset;
            Element parentElement = getMovableTarget().getParent().getElement();
            int parentScrollWidth = parentElement.getScrollWidth();
            int parentScrollHeight;
            if (parentElement == Document.get().getBody())// Some browsers
                                                          // return incorrect
                                                          // height for body
                                                          // element
            {
                parentScrollHeight = Document.get().getClientHeight();
            } else {
                parentScrollHeight = parentElement.getScrollHeight();
            }
            targetStyle.setWidth(parentScrollWidth - hInsets, Style.Unit.PX);
            targetStyle.setHeight(parentScrollHeight - vInsets, Style.Unit.PX);
            // editing
            targetStyle = movableElement.getStyle(); // window
            targetStyle.setLeft(0, Style.Unit.PX);
            targetStyle.setTop(0, Style.Unit.PX);
            onResize();
            MaximizeEvent.<WindowUI>fire(this, this);
        }
    }

    @Override
    public void setPosition(double aLeft, double aTop) {
        super.setPosition(aLeft, aTop);
        MoveEvent.fire(this, this, aLeft, aTop);
    }

    @Override
    public void setSize(double aWidth, double aHeight) {
        super.setSize(aWidth, aHeight);
        ResizeEvent.<WindowPanel>fire(this, (int) aWidth, (int) aHeight);
    }

    private void snapshotMetrics() throws NumberFormatException {
        // measurement
        Style targetStyle = getWidget().getElement().getStyle(); // content
        String sHeight = targetStyle.getHeight();
        contentHeightToRestore = Double.parseDouble(sHeight.substring(0, sHeight.length() - 2));
        String sWidth = targetStyle.getWidth();
        contentWidthToRestore = Double.parseDouble(sWidth.substring(0, sWidth.length() - 2));
        targetStyle = getMovableTarget().getElement().getStyle(); // window
        String sLeft = targetStyle.getLeft();
        leftToRestore = Double.parseDouble(sLeft.substring(0, sLeft.length() - 2));
        String sTop = targetStyle.getTop();
        topToRestore = Double.parseDouble(sTop.substring(0, sTop.length() - 2));
    }

    protected boolean preMinimizedStateMaximized;
    protected boolean preMinimzedStateNormal;

    /**
     * Minimizes the window. Minimize here is setting zero as height.
     * Descendants may decide to do something else. minimize does a snapshot of
     * all window's metrics. So subsequent restore or restoreSnapshot calls will
     * lead to correct restoration of the window.
     */
    @Override
    public void minimize() {
        if (!minimized) {
            preMinimizedStateMaximized = maximized;
            preMinimzedStateNormal = !maximized && !minimized;
            restoreSnapshot();
            minimized = true;
            updateDecorCursors();
            // measure
            snapshotMetrics();
            // edit
            Style targetStyle = getWidget().getElement().getStyle(); // content
            targetStyle.setHeight(0, Style.Unit.PX);
            onResize();
            MinimizeEvent.<WindowUI>fire(this, this);
        }
    }

    protected Double leftToRestore;
    protected Double topToRestore;
    protected Double contentWidthToRestore;
    protected Double contentHeightToRestore;

    @Override
    public void restoreSnapshot() {
        if (minimized || maximized) {
            minimized = false;
            maximized = false;
            if (leftToRestore != null) {
                getMovableTarget().getElement().getStyle().setLeft(leftToRestore, Style.Unit.PX);
            }
            leftToRestore = null;
            if (topToRestore != null) {
                getMovableTarget().getElement().getStyle().setTop(topToRestore, Style.Unit.PX);
            }
            topToRestore = null;
            if (contentWidthToRestore != null) {
                getWidget().getElement().getStyle().setWidth(contentWidthToRestore, Style.Unit.PX);
            }
            contentWidthToRestore = null;
            if (contentHeightToRestore != null) {
                getWidget().getElement().getStyle().setHeight(contentHeightToRestore, Style.Unit.PX);
            }
            contentHeightToRestore = null;
            onResize();
            RestoreEvent.<WindowUI>fire(this, this);
        }
    }

    @Override
    public void restore() {
        if (minimized || maximized) {
            if (maximized || preMinimzedStateNormal) {
                restoreSnapshot();
                updateDecorCursors();
            } else if (preMinimizedStateMaximized) {
                maximize();
            }
        }
    }

    @Override
    public boolean isActive() {
        return active;
    }

    @Override
    public void activate() {
        if (!active) {
            active = true;
            if (captionWidget != null) {
                captionWidget.addStyleDependentName(ACTIVE_SUFFIX_NAMNE);
            }
            Widget[] widgets = new Widget[] { n, s, w, e, ne, nw, se, sw, content };
            for (Widget _w : widgets) {
                _w.addStyleDependentName(ACTIVE_SUFFIX_NAMNE);
            }
            ActivateEvent.<WindowUI>fire(this, this);
        }
    }

    @Override
    public void deactivate() {
        if (active) {
            active = false;
            if (captionWidget != null) {
                captionWidget.removeStyleDependentName(ACTIVE_SUFFIX_NAMNE);
            }
            Widget[] widgets = new Widget[] { n, s, w, e, ne, nw, se, sw, content };
            for (Widget _w : widgets) {
                _w.removeStyleDependentName(ACTIVE_SUFFIX_NAMNE);
            }
            DeactivateEvent.<WindowUI>fire(this, this);
        }
    }

    public void toFront() {
        Element selfEl = getMovableTarget().getElement();
        Element parentEl = selfEl.getParentElement();
        if (parentEl != null) {
            Node lastChildNode = parentEl.getLastChild();
            if (lastChildNode instanceof Element && lastChildNode != selfEl) {
                parentEl.insertAfter(selfEl, lastChildNode);
            }
        }
    }

    /**
     * Activates and brings the window to front. Descandants may focus default
     * widget in this method.
     */
    @Override
    public void focus() {
        activate();
        toFront();
    }

    @Override
    protected void onAttach() {
        super.onAttach();
        onResize();
        OpenEvent.<WindowUI>fire(this, this);
    }

    protected void fireCloseEvent() {
        ClosedEvent.<WindowUI>fire(this, this);
    }

    @Override
    public void close() {
        if (!BeforeCloseEvent.<WindowUI>fire(this, this)) {
            getMovableTarget().removeFromParent();
            fireCloseEvent();
        }
    }

    @Override
    public boolean isMovable() {
        return movable;
    }

    @Override
    public void setMovable(boolean aValue) {
        movable = aValue;
        updateCaptionCursor();
    }

    @Override
    public boolean isAnimationEnabled() {
        return animationEnabled;
    }

    @Override
    public void setAnimationEnabled(boolean aValue) {
        if (animationEnabled != aValue) {
            animationEnabled = aValue;
            verticalPanelContent.getElement().getStyle().clearProperty("transition");
            if (!animationEnabled) {
                verticalPanelContent.getElement().getStyle().setProperty("transition", "none");
            }
        }
    }

    @Override
    protected void beginResizing() {
        super.beginResizing();
        verticalPanelContent.getElement().getStyle().setProperty("transition", "none");
        getMovableTarget().getElement().getStyle().setProperty("transition", "none");
        getWidget().getElement().getStyle().setVisibility(Style.Visibility.HIDDEN);
    }

    @Override
    protected void endResizing() {
        super.endResizing();
        getWidget().getElement().getStyle().clearVisibility();
        if (animationEnabled) {
            verticalPanelContent.getElement().getStyle().clearProperty("transition");
            getMovableTarget().getElement().getStyle().clearProperty("transition");
        }
    }

    protected void beginMoving() {
        getMovableTarget().getElement().getStyle().setProperty("transition", "none");
        getWidget().getElement().getStyle().setVisibility(Style.Visibility.HIDDEN);
    }

    protected void endMoving() {
        getWidget().getElement().getStyle().clearVisibility();
        if (animationEnabled) {
            getMovableTarget().getElement().getStyle().clearProperty("transition");
        }
    }

    protected void updateCaptionCursor() {
        if (captionWidget != null) {
            if (movable) {
                captionWidget.getElement().getStyle().clearCursor();
            } else {
                captionWidget.getElement().getStyle().setCursor(Style.Cursor.DEFAULT);
            }
        }
    }

    @Override
    public HandlerRegistration addOpenHandler(OpenHandler<WindowUI> handler) {
        return addHandler(handler, OpenEvent.getType());
    }

    @Override
    public HandlerRegistration addClosedHandler(ClosedHandler<WindowUI> handler) {
        return addHandler(handler, ClosedEvent.getType());
    }

    @Override
    public HandlerRegistration addBeforeCloseHandler(BeforeCloseHandler<WindowUI> handler) {
        return addHandler(handler, BeforeCloseEvent.getType());
    }

    @Override
    public HandlerRegistration addActivateHandler(ActivateHandler<WindowUI> handler) {
        return addHandler(handler, ActivateEvent.getType());
    }

    @Override
    public HandlerRegistration addDeactivateHandler(DeactivateHandler<WindowUI> handler) {
        return addHandler(handler, DeactivateEvent.getType());
    }

    @Override
    public HandlerRegistration addMinimizeHandler(MinimizeHandler<WindowUI> handler) {
        return addHandler(handler, MinimizeEvent.getType());
    }

    @Override
    public HandlerRegistration addMaximizeHandler(MaximizeHandler<WindowUI> handler) {
        return addHandler(handler, MaximizeEvent.getType());
    }

    @Override
    public HandlerRegistration addRestoreHandler(RestoreHandler<WindowUI> handler) {
        return addHandler(handler, RestoreEvent.getType());
    }

    @Override
    public HandlerRegistration addMoveHandler(MoveHandler<WindowUI> handler) {
        return addHandler(handler, MoveEvent.getType());
    }

    @Override
    public HandlerRegistration addResizeHandler(ResizeHandler handler) {
        return addHandler(handler, ResizeEvent.getType());
    }
}