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

Java tutorial

Introduction

Here is the source code for org.kaaproject.avro.ui.gwt.client.widget.BusyPopup.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 org.kaaproject.avro.ui.gwt.client.util.Utils;

import com.google.gwt.animation.client.Animation;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.Style;
import com.google.gwt.dom.client.Style.Display;
import com.google.gwt.dom.client.Style.Position;
import com.google.gwt.dom.client.Style.Unit;
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.Event;
import com.google.gwt.user.client.Event.NativePreviewEvent;
import com.google.gwt.user.client.Event.NativePreviewHandler;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.SimplePanel;

public class BusyPopup extends SimplePanel {

    private static BusyPopup instance;

    public static void showPopup() {
        if (instance == null) {
            instance = new BusyPopup();
        }
        instance.rollDown();
    }

    public static void hidePopup() {
        if (instance != null) {
            instance.hide();
        }
    }

    private static final int ANIMATION_DURATION = 300;

    private static final int GLASS_Z_INDEX = 32766;

    private static final int POPUP_Z_INDEX = 32767;

    private ResizeHandler glassResizer = new ResizeHandler() {
        public void onResize(ResizeEvent event) {
            Style style = glass.getStyle();

            int winWidth = Window.getClientWidth();
            int winHeight = Window.getClientHeight();

            style.setDisplay(Display.NONE);
            style.setWidth(0, Unit.PX);
            style.setHeight(0, Unit.PX);

            int width = Document.get().getScrollWidth();
            int height = Document.get().getScrollHeight();

            style.setWidth(Math.max(width, winWidth), Unit.PX);
            style.setHeight(Math.max(height, winHeight), Unit.PX);

            style.setDisplay(Display.BLOCK);
        }
    };

    private boolean showing;
    private boolean isAnimationEnabled = true;
    private Element glass;

    private HandlerRegistration nativePreviewHandlerRegistration;
    private int leftPosition = -1;
    private int topPosition = -1;
    private RollAnimation rollAnimation = new RollAnimation(this);

    public BusyPopup() {
        glass = Document.get().createDivElement();
        glass.setClassName(Utils.avroUiStyle.busyGlass());

        glass.getStyle().setPosition(Position.ABSOLUTE);
        glass.getStyle().setLeft(0, Unit.PX);
        glass.getStyle().setTop(0, Unit.PX);
        glass.getStyle().setZIndex(GLASS_Z_INDEX);

        getElement().getStyle().setZIndex(POPUP_Z_INDEX);

        HorizontalPanel panel = new HorizontalPanel();
        panel.setSize("320px", "70px");
        panel.addStyleName(Utils.avroUiStyle.busyPopup());
        Image image = new Image();
        image.setResource(Utils.resources.busyIndicator());
        panel.add(image);
        panel.setCellWidth(image, "60px");
        panel.setCellHorizontalAlignment(image, HasHorizontalAlignment.ALIGN_CENTER);
        panel.setCellVerticalAlignment(image, HasVerticalAlignment.ALIGN_MIDDLE);
        Label label = new Label();
        label.setText(Utils.constants.busyPopupText());
        label.getElement().getStyle().setPaddingRight(15, Unit.PX);
        panel.add(label);
        panel.setCellHorizontalAlignment(label, HasHorizontalAlignment.ALIGN_CENTER);
        panel.setCellVerticalAlignment(label, HasVerticalAlignment.ALIGN_MIDDLE);
        setWidget(panel);

    }

    public void setAnimationEnabled(boolean enable) {
        isAnimationEnabled = enable;
    }

    public void setPopupPosition(int left, int top) {
        leftPosition = left;
        topPosition = top;

        left -= Document.get().getBodyOffsetLeft();
        top -= Document.get().getBodyOffsetTop();

        Element elem = getElement();
        elem.getStyle().setPropertyPx("left", left);
        elem.getStyle().setPropertyPx("top", top);
    }

    public void rollDown() {
        boolean initiallyShowing = showing;
        boolean initiallyAnimated = isAnimationEnabled;

        if (!initiallyShowing) {
            setVisible(false);
            setAnimationEnabled(false);
            show();
        }

        Element elem = getElement();
        elem.getStyle().setPropertyPx("left", 0);
        elem.getStyle().setPropertyPx("top", 0);

        int left = (Window.getClientWidth() - getOffsetWidth()) >> 1;
        int top = -getOffsetHeight();

        setPopupPosition(Math.max(Window.getScrollLeft() + left, 0),
                Math.max(Window.getScrollTop() + top, -getOffsetHeight()));

        if (!initiallyShowing) {
            setAnimationEnabled(initiallyAnimated);
            if (initiallyAnimated) {
                setVisible(true);
                rollAnimation.run(ANIMATION_DURATION);
            } else {
                setVisible(true);
            }
        }
    }

    @Override
    public void setVisible(boolean visible) {
        getElement().getStyle().setProperty("visibility", visible ? "visible" : "hidden");
        if (glass != null) {
            glass.getStyle().setProperty("visibility", visible ? "visible" : "hidden");
        }
    }

    public boolean isShowing() {
        return showing;
    }

    public void show() {
        if (showing) {
            return;
        } else if (isAttached()) {
            this.removeFromParent();
        }
        rollAnimation.setState(true, false);
    }

    public void hide() {
        if (!isShowing()) {
            return;
        }
        rollAnimation.setState(false, false);
    }

    private void previewNativeEvent(NativePreviewEvent event) {
        event.cancel();
        return;
    }

    private void updateHandlers() {
        if (nativePreviewHandlerRegistration != null) {
            nativePreviewHandlerRegistration.removeHandler();
            nativePreviewHandlerRegistration = null;
        }
        if (showing) {
            nativePreviewHandlerRegistration = Event.addNativePreviewHandler(new NativePreviewHandler() {
                public void onPreviewNativeEvent(NativePreviewEvent event) {
                    previewNativeEvent(event);
                }
            });
        }
    }

    static class RollAnimation extends Animation {

        private BusyPopup curPanel = null;
        private boolean isUnloading;
        private boolean showing;
        private Timer showTimer;
        private boolean glassShowing;
        private HandlerRegistration resizeRegistration;
        private int offsetHeight = -1;

        public RollAnimation(BusyPopup panel) {
            this.curPanel = panel;
        }

        public void setState(boolean showing, boolean isUnloading) {
            this.isUnloading = isUnloading;
            cancel();

            if (showTimer != null) {
                showTimer.cancel();
                showTimer = null;
                onComplete();
            }

            curPanel.showing = showing;
            curPanel.updateHandlers();

            boolean animate = !isUnloading && curPanel.isAnimationEnabled;
            this.showing = showing;
            if (animate) {
                if (showing) {
                    maybeShowGlass();
                    curPanel.getElement().getStyle().setProperty("position", "absolute");
                    if (curPanel.topPosition != -1) {
                        curPanel.setPopupPosition(curPanel.leftPosition, curPanel.topPosition);
                    }
                    RootPanel.get().add(curPanel);
                    showTimer = new Timer() {
                        @Override
                        public void run() {
                            showTimer = null;
                            RollAnimation.this.run(ANIMATION_DURATION);
                        }
                    };
                    showTimer.schedule(1);
                } else {
                    run(ANIMATION_DURATION);
                }
            } else {
                onInstantaneousRun();
            }
        }

        @Override
        protected void onComplete() {
            if (!showing) {
                maybeShowGlass();
                if (!isUnloading) {
                    RootPanel.get().remove(curPanel);
                }
            }
            curPanel.getElement().getStyle().setProperty("overflow", "visible");
        }

        @Override
        protected void onStart() {
            offsetHeight = curPanel.getOffsetHeight();
            super.onStart();
        }

        @Override
        protected void onUpdate(double progress) {
            if (!showing) {
                progress = 1.0 - progress;
            }

            int topPosition = (int) (progress * offsetHeight) - offsetHeight;

            curPanel.setPopupPosition(curPanel.leftPosition,
                    Math.max(Window.getScrollTop() + topPosition, -offsetHeight));
        }

        private void maybeShowGlass() {
            if (showing) {
                Document.get().getBody().appendChild(curPanel.glass);
                resizeRegistration = Window.addResizeHandler(curPanel.glassResizer);
                curPanel.glassResizer.onResize(null);
                glassShowing = true;
            } else if (glassShowing) {
                Document.get().getBody().removeChild(curPanel.glass);
                resizeRegistration.removeHandler();
                resizeRegistration = null;
                glassShowing = false;
            }
        }

        private void onInstantaneousRun() {
            maybeShowGlass();
            if (showing) {
                curPanel.getElement().getStyle().setProperty("position", "absolute");
                if (curPanel.topPosition != -1) {
                    curPanel.setPopupPosition(curPanel.leftPosition, curPanel.topPosition);
                }
                RootPanel.get().add(curPanel);
            } else {
                if (!isUnloading) {
                    RootPanel.get().remove(curPanel);
                }
            }
            curPanel.getElement().getStyle().setProperty("overflow", "visible");
        }

    }
}