org.kaaproject.avro.ui.gwt.client.widget.FormPopup.java Source code

Java tutorial

Introduction

Here is the source code for org.kaaproject.avro.ui.gwt.client.widget.FormPopup.java

Source

/*
 * Copyright 2014-2015 CyberVision, Inc.
 *
 * 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 org.kaaproject.avro.ui.gwt.client.widget;

import java.util.Iterator;

import org.kaaproject.avro.ui.gwt.client.util.Utils;
import org.kaaproject.avro.ui.gwt.client.widget.dialog.AvroUiDialog;

import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.EventTarget;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
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.MouseOutEvent;
import com.google.gwt.event.dom.client.MouseOutHandler;
import com.google.gwt.event.dom.client.MouseOverEvent;
import com.google.gwt.event.dom.client.MouseOverHandler;
import com.google.gwt.event.dom.client.MouseUpEvent;
import com.google.gwt.event.dom.client.MouseUpHandler;
import com.google.gwt.event.logical.shared.AttachEvent;
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.Element;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.Event.NativePreviewEvent;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.DecoratorPanel;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.InlineLabel;
import com.google.gwt.user.client.ui.MouseListener;
import com.google.gwt.user.client.ui.PopupPanel;
import com.google.gwt.user.client.ui.Widget;

@SuppressWarnings("deprecation")
public class FormPopup extends PopupPanel implements MouseListener {

    public static class CloseWidget extends InlineLabel {

        public CloseWidget() {
            super();
            setStyleName(Utils.avroUiStyle.closeAction());
        }

        public void doAttach() {
            super.onAttach();
        }

        public void doDetach() {
            super.onDetach();
        }
    }

    private static class BottomPanel extends HorizontalPanel {

        public BottomPanel() {
            setHorizontalAlignment(HasHorizontalAlignment.ALIGN_RIGHT);
            setWidth("100%");
        }

        public void doAttach() {
            super.onAttach();
        }

        public void doDetach() {
            super.onDetach();
        }
    }

    public static class DecoratorPanelImpl extends DecoratorPanel {

        public DecoratorPanelImpl() {
            super();
        }

        public void doAttach() {
            super.onAttach();
        }

        public void doDetach() {
            super.onDetach();
        }

        protected Element getCellElement(int row, int cell) {
            return super.getCellElement(row, cell);
        }
    }

    private class MouseHandler
            implements MouseDownHandler, MouseUpHandler, MouseOutHandler, MouseOverHandler, MouseMoveHandler {

        public void onMouseDown(MouseDownEvent event) {
            beginDragging(event);
        }

        public void onMouseMove(MouseMoveEvent event) {
            continueDragging(event);
        }

        public void onMouseOut(MouseOutEvent event) {
            FormPopup.this.onMouseLeave(decPanel.asWidget());
        }

        public void onMouseOver(MouseOverEvent event) {
            FormPopup.this.onMouseEnter(decPanel.asWidget());
        }

        public void onMouseUp(MouseUpEvent event) {
            endDragging(event);
        }
    }

    private DecoratorPanelImpl decPanel;
    private CloseWidget closeWidget;
    private boolean dragging;
    private int dragStartX, dragStartY;
    private int windowWidth;
    private int clientLeft;
    private int clientTop;

    private String desiredHeight;

    private String desiredWidth;

    private HandlerRegistration resizeHandlerRegistration;

    private BottomPanel bottomPanel;
    private HorizontalPanel buttonsPanel;

    public FormPopup() {
        this(false);
    }

    public FormPopup(boolean autoHide) {
        this(autoHide, true, true, false);
    }

    public FormPopup(boolean autoHide, boolean modal, boolean showCloseButton, boolean autoHideOnHistoryEvents) {
        super(autoHide, modal);
        this.setAutoHideOnHistoryEventsEnabled(autoHideOnHistoryEvents);

        setGlassEnabled(true);
        setAnimationEnabled(true);

        if (showCloseButton) {
            closeWidget = new CloseWidget();
        }

        decPanel = new DecoratorPanelImpl();
        decPanel.setStyleName("");
        decPanel.setSize("100%", "100%");

        setStylePrimaryName(Utils.avroUiStyle.formPopup());
        super.setWidget(decPanel);
        setStyleName(getContainerElement(), "popupContent", false);

        if (showCloseButton) {
            Element td = getCellElement(1, 2);
            DOM.appendChild(td, closeWidget.asWidget().getElement());
            adopt(closeWidget.asWidget());
        }

        windowWidth = Window.getClientWidth();
        clientLeft = Document.get().getBodyOffsetLeft();
        clientTop = Document.get().getBodyOffsetTop();

        MouseHandler mouseHandler = new MouseHandler();
        addDomHandler(mouseHandler, MouseDownEvent.getType());
        addDomHandler(mouseHandler, MouseUpEvent.getType());
        addDomHandler(mouseHandler, MouseMoveEvent.getType());
        addDomHandler(mouseHandler, MouseOverEvent.getType());
        addDomHandler(mouseHandler, MouseOutEvent.getType());

        if (showCloseButton) {
            closeWidget.addClickHandler(new ClickHandler() {
                @Override
                public void onClick(ClickEvent event) {
                    hide();
                }
            });
        }

        addAttachHandler(new AttachEvent.Handler() {

            @Override
            public void onAttachOrDetach(AttachEvent event) {
                if (event.isAttached()) {
                    int popupWidth = getOffsetWidth();
                    int popupHeight = getOffsetHeight();

                    int deltaWidth = (Window.getClientWidth() - popupWidth);
                    int deltaHeight = (Window.getClientHeight() - popupHeight);
                    if (deltaWidth < 0 || deltaHeight < 0) {
                        if (deltaWidth < 0) {
                            popupWidth += deltaWidth;
                        } else {
                            deltaWidth = 0;
                        }
                        if (deltaHeight < 0) {
                            popupHeight += deltaHeight;
                        } else {
                            deltaHeight = 0;
                        }
                        getElement().getStyle().setWidth(popupWidth, Unit.PX);
                        getElement().getStyle().setHeight(popupHeight, Unit.PX);
                        onSizeOverflow(deltaWidth, deltaHeight);
                    }
                }

            }
        });

        getGlassElement().getStyle().setZIndex(AvroUiDialog.GLASS_Z_INDEX);
        getElement().getStyle().setZIndex(AvroUiDialog.DIALOG_Z_INDEX);
    }

    public void onSizeOverflow(int deltaWidth, int deltaHeight) {
    }

    private void initButtonsPanel() {
        buttonsPanel = new HorizontalPanel();
        buttonsPanel.setSpacing(5);

        buttonsPanel.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_RIGHT);

        bottomPanel = new BottomPanel();
        bottomPanel.add(buttonsPanel);

        Element td = getCellElement(2, 1);
        DOM.insertChild(td, bottomPanel.getElement(), 0);
        adopt(bottomPanel);
    }

    public void addButton(com.google.gwt.user.client.ui.Button button) {
        if (buttonsPanel == null)
            initButtonsPanel();
        button.getElement().getStyle().setMarginLeft(20, Unit.PX);
        buttonsPanel.add(button);
    }

    @Override
    public void hide() {
        if (resizeHandlerRegistration != null) {
            resizeHandlerRegistration.removeHandler();
            resizeHandlerRegistration = null;
        }
        super.hide();
    }

    @Override
    public void show() {
        if (resizeHandlerRegistration == null) {
            resizeHandlerRegistration = Window.addResizeHandler(new ResizeHandler() {
                public void onResize(ResizeEvent event) {
                    windowWidth = event.getWidth();
                }
            });
        }
        Timer timer = new Timer() {
            public void run() {
                getElement().getStyle().setProperty("clip", "auto");
            }
        };
        timer.schedule(300);

        super.show();
    }

    @Override
    public void onBrowserEvent(Event event) {
        switch (event.getTypeInt()) {
        case Event.ONMOUSEDOWN:
        case Event.ONMOUSEUP:
        case Event.ONMOUSEMOVE:
        case Event.ONMOUSEOVER:
        case Event.ONMOUSEOUT:
            if (!dragging && !isCaptionEvent(event)) {
                return;
            }
        }

        super.onBrowserEvent(event);
    }

    @Override
    public void clear() {
        decPanel.clear();
    }

    @Override
    public Widget getWidget() {
        return decPanel.getWidget();
    }

    @Override
    public Iterator<Widget> iterator() {
        return decPanel.iterator();
    }

    @Override
    public boolean remove(Widget w) {
        return decPanel.remove(w);
    }

    @Override
    public void setWidget(Widget w) {
        decPanel.setWidget(w);
        maybeUpdateSizeInternal();
    }

    void maybeUpdateSizeInternal() {
        Widget w = super.getWidget();
        if (w != null) {
            if (desiredHeight != null) {
                w.setHeight(desiredHeight);
            }
            if (desiredWidth != null) {
                w.setWidth(desiredWidth);
            }
        }
    }

    @Override
    public void setHeight(String height) {
        super.setHeight(height);
        desiredHeight = height;
        // If the user cleared the size, revert to not trying to control
        // children.
        if (height.length() == 0) {
            desiredHeight = null;
        }
    }

    @Override
    public void setWidth(String width) {
        super.setWidth(width);
        desiredWidth = width;
        // If the user cleared the size, revert to not trying to control
        // children.
        if (width.length() == 0) {
            desiredWidth = null;
        }
    }

    @Override
    protected void doAttachChildren() {
        try {
            decPanel.doAttach();
        } finally {
            if (closeWidget != null)
                closeWidget.doAttach();
            if (bottomPanel != null)
                bottomPanel.doAttach();
        }
    }

    @Override
    protected void doDetachChildren() {
        try {
            decPanel.doDetach();
        } finally {
            if (closeWidget != null)
                closeWidget.doDetach();
            if (bottomPanel != null)
                bottomPanel.doDetach();
        }
    }

    @Override
    public void onMouseDown(Widget sender, int x, int y) {
        if (DOM.getCaptureElement() == null) {
            /*
             * Need to check to make sure that we aren't already capturing an
             * element otherwise events will not fire as expected. If this check
             * isn't here, any class which extends custom button will not fire
             * its click event for example.
             */
            dragging = true;
            DOM.setCapture(getElement());
            dragStartX = x;
            dragStartY = y;
        }
    }

    @Override
    public void onMouseEnter(Widget sender) {
    }

    @Override
    public void onMouseLeave(Widget sender) {
    }

    @Override
    public void onMouseMove(Widget sender, int x, int y) {
        if (dragging) {
            int absX = x + getAbsoluteLeft();
            int absY = y + getAbsoluteTop();

            if (absX < clientLeft || absX >= windowWidth || absY < clientTop) {
                return;
            }

            setPopupPosition(absX - dragStartX, absY - dragStartY);
        }
    }

    @Override
    public void onMouseUp(Widget sender, int x, int y) {
        dragging = false;
        DOM.releaseCapture(getElement());
    }

    protected void beginDragging(MouseDownEvent event) {
        onMouseDown(decPanel.asWidget(), event.getX(), event.getY());
    }

    protected void continueDragging(MouseMoveEvent event) {
        onMouseMove(decPanel.asWidget(), event.getX(), event.getY());
    }

    protected void endDragging(MouseUpEvent event) {
        onMouseUp(decPanel.asWidget(), event.getX(), event.getY());
    }

    @Override
    protected void onPreviewNativeEvent(NativePreviewEvent event) {
        NativeEvent nativeEvent = event.getNativeEvent();

        if (!event.isCanceled() && (event.getTypeInt() == Event.ONMOUSEDOWN) && isCaptionEvent(nativeEvent)) {
            nativeEvent.preventDefault();
        }

        super.onPreviewNativeEvent(event);
    }

    private boolean isCaptionEvent(NativeEvent event) {
        EventTarget target = event.getEventTarget();
        if (Element.is(target)) {
            com.google.gwt.dom.client.Element element = Element.as(target);
            if (decPanel.getElement().isOrHasChild(element)) {
                String tag = element.getTagName();
                String className = element.getClassName();
                if (tag.equalsIgnoreCase("tr")) {
                    if ("top".equalsIgnoreCase(className)) {
                        return true;
                    }
                } else if (tag.equalsIgnoreCase("td")) {
                    if ("topLeft".equalsIgnoreCase(className) || "topCenter".equalsIgnoreCase(className)
                            || "topRight".equalsIgnoreCase(className)) {
                        return true;
                    }
                } else if (tag.equalsIgnoreCase("div")) {
                    if ("topLeftInner".equalsIgnoreCase(className) || "topCenterInner".equalsIgnoreCase(className)
                            || "topRightInner".equalsIgnoreCase(className)) {
                        return true;
                    }
                }
            }
        }
        return false;
    }

    public void setTitle(String title) {
        getCellElement(0, 1).setInnerText(title);
    }

    protected Element getCellElement(int row, int cell) {
        return decPanel.getCellElement(row, cell);
    }

    @Override
    protected void onEnsureDebugId(String baseID) {
        super.onEnsureDebugId(baseID);
        ensureDebugId(getCellElement(1, 1), baseID, "content");
    }

}