co.fxl.gui.gwt.GWTDisplay.java Source code

Java tutorial

Introduction

Here is the source code for co.fxl.gui.gwt.GWTDisplay.java

Source

/**
 * Copyright (c) 2010-2015 Dangelmayr IT GmbH. All rights reserved.
 *  
 * This file is part of FXL GUI API.
 *  
 * FXL GUI API is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *  
 * FXL GUI API is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *  
 * You should have received a copy of the GNU General Public License
 * along with FXL GUI API.  If not, see <http://www.gnu.org/licenses/>.
 */
package co.fxl.gui.gwt;

import java.util.LinkedList;
import java.util.List;

import co.fxl.data.format.gwt.GWTFormat;
import co.fxl.gui.api.ICallback;
import co.fxl.gui.api.IContainer;
import co.fxl.gui.api.ICursor;
import co.fxl.gui.api.IDialog;
import co.fxl.gui.api.IDisplay;
import co.fxl.gui.api.IGridPanel;
import co.fxl.gui.api.IPopUp;
import co.fxl.gui.api.IScrollPane;
import co.fxl.gui.api.IWebsite;
import co.fxl.gui.api.IWidgetProvider;
import co.fxl.gui.api.WidgetProviderNotFoundException;
import co.fxl.gui.impl.CallbackTemplate;
import co.fxl.gui.impl.Constants;
import co.fxl.gui.impl.DialogImpl;
import co.fxl.gui.impl.Display;
import co.fxl.gui.impl.DisplayTemplate;
import co.fxl.gui.impl.ImagePathResolver;
import co.fxl.gui.impl.RuntimeTemplate;
import co.fxl.gui.impl.StatusDisplay;
import co.fxl.gui.impl.StatusDisplay.Fix;
import co.fxl.gui.impl.ToolbarImpl;
import co.fxl.gui.log.impl.Log;

import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.RepeatingCommand;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.core.client.impl.SchedulerImpl;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.dom.client.Style.Overflow;
import com.google.gwt.event.dom.client.DomEvent;
import com.google.gwt.event.dom.client.MouseWheelEvent;
import com.google.gwt.event.logical.shared.ResizeEvent;
import com.google.gwt.event.logical.shared.ResizeHandler;
import com.google.gwt.resources.client.ImageResource;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.Widget;

public class GWTDisplay extends DisplayTemplate implements IDisplay, WidgetParent {

    // TODO Look: Quirk: GWT: IE9: Hhe von ComboBox stimmt nicht (eventuell
    // in
    // Grid einbetten)
    // TODO Look: Quirk: GWT: Safari: Hhe von ComboBox stimmt nicht
    // (eventuell
    // in Grid einbetten)

    private static final String OPERA_PREFIX = "Opera/";
    private static final String FIREFOX = "Firefox/";
    private static final String CHROME = "Chrome/";
    public static final String BROWSER_WARNING_IE8 = "You are using an outdated browser with a slow javascript engine! If possible: Update to Internet Explorer 9+ or switch to another browser like Firefox or Chrome. This will significantly improve application response time.";
    public static final String BROWSER_WARNING_FIREFOX36 = "You are using an outdated browser! If possible: Update to Firefox 12+ or switch to another browser like Chrome. This will significantly improve application response time.";
    // public static final String BROWSER_WARNING_ZOOM_CHROME =
    // "You are using a zoom level other than 100%. Please switch to zoom level 100%, for example by clicking Ctrl+0, to avoid unexpected behaviour.";
    static GWTDisplay instance;
    private GWTContainer<Widget> container;
    private GWTUncaughtExceptionHandler uncaughtExceptionHandler;
    // waiting-delta public static boolean waiting = false;
    static int lastClickX = 0;
    static int lastClickY = 0;
    private Scheduler scheduler = new SchedulerImpl();
    private IRuntime runtime;
    private boolean scrolling = true;
    private List<Element> styles = new LinkedList<Element>();
    private boolean blocked;
    private boolean queueNotifyResizeListener;
    private static String USER_AGENT = Window.Navigator.getUserAgent();
    private static final String USER_AGENT_LOWER_CASE = USER_AGENT.toLowerCase();
    public static boolean isFirefox = USER_AGENT.contains("Gecko/") && USER_AGENT.contains("Firefox/");
    public static boolean isSafari = USER_AGENT.contains("Safari/") && !USER_AGENT.contains("Chrome/");
    public static boolean isFirefox3 = isFirefox && USER_AGENT.contains("Firefox/3.");
    static boolean isChrome = USER_AGENT.contains("Chrome/");
    public static boolean isInternetExplorer = !isFirefox
            && (USER_AGENT_LOWER_CASE.contains("msie") || USER_AGENT_LOWER_CASE.contains("rv:"));
    public static boolean isInternetExplorer8OrBelow = USER_AGENT_LOWER_CASE.contains("msie 8.0")
            || USER_AGENT_LOWER_CASE.contains("msie 7.0") || USER_AGENT_LOWER_CASE.contains("msie 6.0")
            || USER_AGENT_LOWER_CASE.contains("msie 5.0");
    public static boolean isOpera = USER_AGENT.startsWith(OPERA_PREFIX);
    static boolean isInternetExplorer9 = USER_AGENT_LOWER_CASE.contains("msie 9.0");
    static boolean isInternetExplorer11Plus = USER_AGENT_LOWER_CASE.contains("rv:")
            && !USER_AGENT_LOWER_CASE.contains(" firefox/");
    static boolean isInternetExplorer9OrBelow = isInternetExplorer9 || isInternetExplorer8OrBelow;

    public static int deltaY(MouseWheelEvent event) {
        return isInternetExplorer11Plus ? -eventGetMouseWheelVelocityY(event.getNativeEvent()) / 40
                : event.getDeltaY();
    }

    public native static int eventGetMouseWheelVelocityY(NativeEvent evt) /*-{
                                                                          return evt.wheelDelta;
                                                                          }-*/;

    public static void notifyEvent(DomEvent<?> event) {
        if (event != null) {
            final NativeEvent nativeEvent = event.getNativeEvent();
            notifyEvent(nativeEvent);
        }
    }

    public static void notifyEvent(NativeEvent nativeEvent) {
        lastClickX = nativeEvent.getClientX();
        lastClickY = nativeEvent.getClientY();
    }

    private GWTDisplay() {
        // GWTDisplayClientBundle.INSTANCE.css().ensureInjected();
        Display.instance(this);
        co.fxl.gui.style.impl.Style.instance();
        container = new GWTContainer<Widget>(this) {
            public void setComponent(Widget component) {
                widget = component;
                widget.setWidth("100%");
                RootPanel.get().add(component, 0, 0);
            }
        };
        // TODO AOPC: Aspect Log.instance(new GWTLog());
        ToolbarImpl.ALLOW_ALIGN_END_FOR_FLOW_PANEL = !isSafari && !(isChrome && getBrowserVersion() <= 13);
        Window.addResizeHandler(new ResizeHandler() {
            @Override
            public void onResize(ResizeEvent event) {
                if (!scrolling) {
                    RootPanel.get().setSize(width() + "px", height() + "px");
                }
                notifyResizeListeners();
            }
        });
        Log.instance().debug("User agent: " + Window.Navigator.getUserAgent());
        runtime = new RuntimeTemplate(getBrowserName(), getBrowserVersion());
        declareConstants();
        GWTFormat.setUp();
        // if (isChromeZoomActive()) {
        // Log.instance().debug(
        // "Zoom is active in Google Chrome: "
        // + Display.instance().width() + " inner-width vs "
        // + getOuterWidth() + " outer-width");
        // }
        StatusDisplay.FIX = new Fix() {

            @Override
            public void apply(IScrollPane p, boolean small) {
                ScrollPanel e = p.nativeElement();
                if (!small)
                    e.getElement().getStyle().setOverflowX(Overflow.HIDDEN);
                else
                    e.getElement().getStyle().setOverflowX(Overflow.AUTO);
            }
        };
        // if (Storage.isLocalStorageSupported()) {
        // register(new IServiceProvider<ILocalStorage>() {
        //
        // @Override
        // public Class<ILocalStorage> serviceType() {
        // return ILocalStorage.class;
        // }
        //
        // @Override
        // public ILocalStorage getService() {
        // return new GWTLocalStorage();
        // }
        // });
        // }
    }

    void addStyle(String text) {
        Element bodyElement = RootPanel.getBodyElement();
        Element newChild = DOM.createElement("style");
        newChild.setInnerText(text);
        com.google.gwt.dom.client.Element parentElement = bodyElement.getParentElement();
        parentElement.insertBefore(newChild, bodyElement);
        styles.add(newChild);
        Log.instance().debug("Adding style: " + text);
    }

    void clearStyles() {
        for (Element e : styles) {
            RootPanel.getBodyElement().getParentElement().removeChild(e);
        }
        styles.clear();
    }

    // public static boolean isChromeZoomActive() {
    // return CHROME
    // && Display.instance().width() < (getOuterWidth() / 1.05);
    // }

    private void declareConstants() {

        // TODO replace with Env.is(...) declarations in the respective widgets

        Constants.put("TableViewTemplate.CORRECT_HEIGHT", !isInternetExplorer);
        // if (isInternetExplorer()) {
        // Constants.put("DashboardPagePage.HEIGHT_DECREMENT", 3);
        // Constants.put("DashboardPagePage.HEIGHT_CONTENT_DECREMENT", 30);
        // }
        if (isFirefox) {
            Constants.put("ScrollTableWidgetImpl.ADD_TOP_PANEL_TOP_PADDING", true);
            if (isFirefox3) {
                Constants.put("FormWidgetImpl.FIXED_WIDTH", true);
                Constants.put("NavigationItemImpl.USE_TEMP_FLIP", false);
            }
        }
        if (isOpera)
            Constants.put("ScrollTableWidgetImpl.ADD_TOP_PANEL_SPACING", true);
        // if (isFirefox() || isOpera()) {
        // Constants.put("MiniFilterPanel.MODIFIED_TITLE_ADD", true);
        // }
        final boolean isChrome15Plus = isChrome && getBrowserVersion() >= 15;
        final String imagePath = Constants.get("GWTLazyTreeWidget.IMAGE_PATH",
                (isChrome15Plus ? "" : GWT.getModuleBaseURL()) + "images/");
        Constants.put("ImagePathResolver", new ImagePathResolver() {
            @Override
            public String resolve(String resource) {
                if (isChrome15Plus) {
                    ImageResource ir = GWTImage.resolve(resource);
                    if (ir != null)
                        return ir.getSafeUri().asString();
                }
                return imagePath + resource;
            }
        });
    }

    private String getBrowserName() {
        if (isChrome) {
            // assert !isSafari && !isInternetExplorer && !isOpera &&
            // !isFirefox;
            return co.fxl.gui.impl.Env.CHROME;
        } else if (isOpera) {
            // assert !isSafari && !isInternetExplorer && !isChrome &&
            // !isFirefox;
            return co.fxl.gui.impl.Env.OPERA;
        } else if (isInternetExplorer) {
            // assert !isSafari && !isChrome && !isOpera && !isFirefox;
            return co.fxl.gui.impl.Env.IE;
        } else if (isFirefox) {
            // assert !isSafari && !isChrome && !isOpera && !isInternetExplorer;
            return co.fxl.gui.impl.Env.FIREFOX;
        } else if (isSafari) {
            // assert !isInternetExplorer && !isChrome && !isOpera &&
            // !isFirefox;
            return co.fxl.gui.impl.Env.SAFARI;
        }
        return co.fxl.gui.impl.Env.OTHER_BROWSER;
    }

    public static int getBrowserVersion() {
        if (isFirefox) {
            return getBrowserVersionFirefox();
        }
        if (isChrome) {
            return getBrowserVersionChrome(USER_AGENT);
        }
        if (isInternetExplorer) {
            if (isInternetExplorer8OrBelow)
                return 8;
            else if (isInternetExplorer9)
                return 9;
            else if (isInternetExplorer11Plus)
                return 11;
            else
                return 10;
        }
        if (isOpera) {
            return getBrowserVersionOpera();
        }
        return -1;
    }

    private static int getBrowserVersionFirefox() {
        if (USER_AGENT.contains(FIREFOX)) {
            int index = USER_AGENT.indexOf(FIREFOX) + FIREFOX.length();
            int index2 = USER_AGENT.indexOf(".", index);
            String substring = USER_AGENT.substring(index, index2);
            return Integer.valueOf(substring);
        }
        return 4;
    }

    private static int getBrowserVersionOpera() {
        try {
            int index = OPERA_PREFIX.length();
            int index2 = OPERA_PREFIX.indexOf(".", index);
            String substring = USER_AGENT.substring(index, index2);
            return Integer.valueOf(substring);
        } catch (Exception e) {
            return -1;
        }
    }

    private static int getBrowserVersionChrome(String userAgent) {
        int index = userAgent.indexOf(CHROME) + CHROME.length();
        int lastIndex = userAgent.indexOf(".", index);
        if (index == -1 || lastIndex == -1 || index >= lastIndex)
            return -1;
        String number = userAgent.substring(index, lastIndex);
        try {
            return Integer.valueOf(number);
        } catch (Exception e) {
            return -1;
        }
    }

    @Override
    public IDisplay height(int pixel) {
        throw new UnsupportedOperationException();
    }

    @Override
    public IDisplay width(int pixel) {
        throw new UnsupportedOperationException();
    }

    static IWidgetProvider<?> lookupWidgetProvider(Class<?> interfaceClass) {
        IWidgetProvider<?> iWidgetProvider = instance.widgetProviders.get(interfaceClass);
        if (iWidgetProvider == null)
            throw new WidgetProviderNotFoundException(interfaceClass);
        return iWidgetProvider;
    }

    @Override
    public IDisplay title(String title) {
        Window.setTitle(title);
        return this;
    }

    @Override
    public IContainer container() {
        return container;
    }

    @Override
    public IDisplay visible(boolean visible) {
        if (container.widget != null)
            container.widget.setVisible(visible);
        return this;
    }

    @Override
    public IDisplay fullscreen() {
        return this;
    }

    public static IDisplay instance() {
        if (instance == null) {
            instance = new GWTDisplay();
        }
        return instance;
    }

    @Override
    public IDialog showDialog() {
        return new DialogImpl() {
            @Override
            protected void decorate(IGridPanel grid) {
                GWTGridPanel gridPanel = (GWTGridPanel) grid;
                Element element = gridPanel.container.widget.getElement();
                DOM.setStyleAttribute(element, "tableLayout", "fixed");
                element.getStyle().setOverflow(Overflow.HIDDEN);
                DOM.setStyleAttribute(element, "wordWrap", "break-word");
            }
        };
    }

    @Override
    public IWebsite showWebsite() {
        return new GWTWebsite();
    }

    @Override
    public IColor color() {
        return new GWTStyleColor(null) {
            @Override
            public void setColor(String color) {
                DOM.setStyleAttribute(RootPanel.getBodyElement(), "backgroundColor", color);
            }
        };
    }

    @Override
    public IDisplay addExceptionHandler(IExceptionHandler handler) {
        GWTUncaughtExceptionHandler h = setUpUncaughtExceptionHandler();
        h.add(handler);
        return this;
    }

    private GWTUncaughtExceptionHandler setUpUncaughtExceptionHandler() {
        if (uncaughtExceptionHandler == null) {
            uncaughtExceptionHandler = new GWTUncaughtExceptionHandler();
            GWT.setUncaughtExceptionHandler(uncaughtExceptionHandler);
        }
        return uncaughtExceptionHandler;
    }

    @Override
    public void add(Widget widget) {
        throw new UnsupportedOperationException();
    }

    // @Override
    // public GWTDisplay lookupDisplay() {
    // return this;
    // }

    @Override
    public void remove(Widget widget) {
        throw new UnsupportedOperationException();
    }

    @Override
    public int height() {
        return Window.getClientHeight();
    }

    @Override
    public int width() {
        return Window.getClientWidth();
    }

    @Override
    public ICursor<IDisplay> cursor() {
        return new GWTCursor<IDisplay>(this, RootPanel.get());
    }

    // public static native String getUserAgent()
    /*-{ return navigator.userAgent; }-*/;

    private static native int getOuterWidth()
    /*-{ return window.outerWidth; }-*/;

    @Override
    public IDisplay block(boolean waiting) {
        blocked = waiting;
        // waiting-delta waiting = waiting;
        DOM.setStyleAttribute(RootPanel.get().getElement(), "cursor", waiting ? "wait" : "default");
        if (!waiting && queueNotifyResizeListener) {
            notifyResizeListeners();
        }
        return this;
    }

    @Override
    public IDisplay notifyResizeListeners() {
        if (blocked) {
            queueNotifyResizeListener = true;
            return this;
        } else {
            queueNotifyResizeListener = false;
            return super.notifyResizeListeners();
        }
    }

    @Override
    public IDisplay invokeLater(final Runnable runnable) {
        scheduler.scheduleDeferred(new ScheduledCommand() {
            @Override
            public void execute() {
                runnable.run();
            }
        });
        return this;
    }

    @Override
    public IDisplay invokeLater(final Runnable runnable, long ms) {
        scheduler.scheduleFixedDelay(new RepeatingCommand() {
            @Override
            public boolean execute() {
                runnable.run();
                return false;
            }
        }, (int) ms);
        return this;
    }

    @Override
    public IPopUp showPopUp() {
        return new GWTPopUp();
    }

    @Override
    public IDisplay size(int width, int height) {
        return width(width).height(height);
    }

    // public IDisplay runAsync(final Runnable runnable) {
    // GWT.runAsync(new RunAsyncCallback() {
    //
    // @Override
    // public void onSuccess() {
    // runnable.run();
    // }
    //
    // @Override
    // public void onFailure(Throwable reason) {
    // throw new RuntimeException(reason);
    // }
    // });
    // return this;
    // }

    @Override
    public String title() {
        return Window.getTitle();
    }

    @Override
    public IDisplay clear() {
        RootPanel.get().clear();
        return this;
    }

    @SuppressWarnings({ "rawtypes", "unchecked" })
    void createWidget(final Class interfaceClass, final IContainer c, final ICallback widget) {
        ensure(interfaceClass, new CallbackTemplate<Void>(widget) {
            @Override
            public void onSuccess(Void result) {
                Object w = lookupWidgetProvider(interfaceClass).createWidget(container);
                widget.onSuccess(w);
            }
        });
    }

    @Override
    public IDisplay scrolling(boolean scrolling) {
        this.scrolling = scrolling;
        // Window.enableScrolling(scrolling);
        // if (isChrome()) {
        // Window.addWindowScrollHandler(new ScrollHandler() {
        //
        // private Long timeToRescroll = null;
        //
        // @Override
        // public void onWindowScroll(ScrollEvent arg0) {
        // boolean schedule = timeToRescroll == null;
        // timeToRescroll = System.currentTimeMillis() + 1000;
        // if (schedule)
        // schedule();
        // }
        //
        // private void schedule() {
        // int l = (int) Math.max(250,
        // timeToRescroll - System.currentTimeMillis());
        // invokeLater(new Runnable() {
        // @Override
        // public void run() {
        // if (System.currentTimeMillis() < timeToRescroll) {
        // schedule();
        // return;
        // }
        // if (Window.getScrollTop() != -1) {
        // Window.scrollTo(Window.getScrollLeft(), -1);
        // }
        // timeToRescroll = null;
        // }
        // }, l);
        // }
        // });
        // }
        return this;
    }

    void resetScrollPanelTop() {
        if (isChrome && !scrolling && Window.getScrollTop() != 0) {
            Window.scrollTo(Window.getScrollLeft(), 0);
        }
    }

    @Override
    public IRuntime runtime() {
        return runtime;
    }

    void notifyElement(GWTElement<?, ?> e) {

        // TODO ...

    }

    @Override
    public IDisplay font(String fontFamily, int fontSize) {
        clearStyles();
        if (!isInternetExplorer9OrBelow && !isOpera) {
            String font = "font-family: " + fontFamily + " !important; font-size: " + fontSize + "px;";
            addStyle("body, table td, select, input, button { " + font + "}");
            addStyle(".gwt-TextArea-FXL { height: 100px; padding: 3px; " + font + "}");
            addStyle(".gwt-TextBox-FXL { padding: 3px; " + font + "}");
            if (fontFamily.contains("'Open Sans'")) {
                addStyle(
                        "html, body { -webkit-font-smoothing: subpixel-antialiased !important; -webkit-backface-visibility: hidden; -moz-backface-visibility: hidden; -ms-backface-visibility:     hidden; }");
            }
        }
        if (!isInternetExplorer11Plus && !isInternetExplorer8OrBelow)
            addStyle("::selection { background-color:transparent; }");
        return this;
    }

    @SuppressWarnings("rawtypes")
    @Override
    public IContainer newContainer() {
        return new GWTContainer();
    }

    @Override
    public void reload() {
        Window.Location.reload();
    }

    // private int styleCounter = 0;
    //
    // @Override
    // public <T extends IElement<T>> IDecorator<T> adoptStyle(
    // final IDecorator<T> style) {
    // return new IDecorator<T>() {
    //
    // private String name;
    //
    // @Override
    // public void decorate(T element) {
    // @SuppressWarnings("unchecked")
    // Element e = ((GWTElement<?, T>) element).container.widget
    // .getElement();
    // if (name == null) {
    // // String before = getStyleString(e);
    // style.decorate(element);
    // String after = getStyleString(e);
    // // String delta = after.substring(before.length());
    // name = "S" + styleCounter++;
    // addStyle("." + name + " { " + after + "}");
    // } else {
    // e.setPropertyString("style", "");
    // element.addStyle(name);
    // }
    // }
    //
    // private String getStyleString(Element e) {
    // String t = e.toString();
    // int index = t.indexOf("style=\"") + "style=\"".length();
    // return t.substring(index, t.indexOf("\"", index));
    // }
    // };
    // }
}