com.badlogic.gdx.backends.gwt.GwtApplication.java Source code

Java tutorial

Introduction

Here is the source code for com.badlogic.gdx.backends.gwt.GwtApplication.java

Source

/*******************************************************************************
 * Copyright 2011 See AUTHORS file.
 * 
 * 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 com.badlogic.gdx.backends.gwt;

import com.badlogic.gdx.Application;
import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Audio;
import com.badlogic.gdx.Files;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Graphics;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.LifecycleListener;
import com.badlogic.gdx.Net;
import com.badlogic.gdx.Preferences;
import com.badlogic.gdx.backends.gwt.preloader.Preloader;
import com.badlogic.gdx.backends.gwt.preloader.Preloader.PreloaderCallback;
import com.badlogic.gdx.backends.gwt.preloader.Preloader.PreloaderState;
import com.badlogic.gdx.backends.gwt.soundmanager2.SoundManager;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.Clipboard;
import com.badlogic.gdx.utils.ObjectMap;
import com.badlogic.gdx.utils.TimeUtils;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.dom.client.CanvasElement;
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.Unit;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.InlineHTML;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.TextArea;
import com.google.gwt.user.client.ui.VerticalPanel;

/** Implementation of an {@link Application} based on GWT. Clients have to override {@link #getConfig()} and
 * {@link #getApplicationListener()}. Clients can override the default loading screen via
 * {@link #getPreloaderCallback()} and implement any loading screen drawing via GWT widgets.
 * @author mzechner */
public abstract class GwtApplication implements EntryPoint, Application {
    private ApplicationListener listener;
    private GwtApplicationConfiguration config;
    private GwtGraphics graphics;
    private GwtInput input;
    private GwtNet net;
    private Panel root = null;
    private TextArea log = null;
    private int logLevel = LOG_ERROR;
    private Array<Runnable> runnables = new Array<Runnable>();
    private Array<Runnable> runnablesHelper = new Array<Runnable>();
    private Array<LifecycleListener> lifecycleListeners = new Array<LifecycleListener>();
    private int lastWidth;
    private int lastHeight;
    Preloader preloader;
    private static AgentInfo agentInfo;
    private ObjectMap<String, Preferences> prefs = new ObjectMap<String, Preferences>();
    private Clipboard clipboard;
    LoadingListener loadingListener;

    /** @return the configuration for the {@link GwtApplication}. */
    public abstract GwtApplicationConfiguration getConfig();

    public String getPreloaderBaseURL() {
        return GWT.getHostPageBaseURL() + "assets/";
    }

    @Override
    public void onModuleLoad() {
        GwtApplication.agentInfo = computeAgentInfo();
        this.listener = getApplicationListener();
        this.config = getConfig();
        this.log = config.log;

        if (config.rootPanel != null) {
            this.root = config.rootPanel;
        } else {
            Element element = Document.get().getElementById("embed-" + GWT.getModuleName());
            if (element == null) {
                VerticalPanel panel = new VerticalPanel();
                panel.setWidth("" + config.width + "px");
                panel.setHeight("" + config.height + "px");
                panel.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);
                panel.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE);
                RootPanel.get().add(panel);
                RootPanel.get().setWidth("" + config.width + "px");
                RootPanel.get().setHeight("" + config.height + "px");
                this.root = panel;
            } else {
                VerticalPanel panel = new VerticalPanel();
                panel.setWidth("" + config.width + "px");
                panel.setHeight("" + config.height + "px");
                panel.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);
                panel.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE);
                element.appendChild(panel.getElement());
                root = panel;
            }
        }

        // initialize SoundManager2
        SoundManager.init(GWT.getModuleBaseURL(), 9, config.preferFlash, new SoundManager.SoundManagerCallback() {

            @Override
            public void onready() {
                final PreloaderCallback callback = getPreloaderCallback();
                preloader = createPreloader();
                preloader.preload("assets.txt", new PreloaderCallback() {
                    @Override
                    public void error(String file) {
                        callback.error(file);
                    }

                    @Override
                    public void update(PreloaderState state) {
                        callback.update(state);
                        if (state.hasEnded()) {
                            getRootPanel().clear();
                            if (loadingListener != null)
                                loadingListener.beforeSetup();
                            setupLoop();
                            if (loadingListener != null)
                                loadingListener.afterSetup();
                        }
                    }
                });
            }

            @Override
            public void ontimeout(String status, String errorType) {
                error("SoundManager", status + " " + errorType);
            }

        });
    }

    void setupLoop() {
        // setup modules
        try {
            graphics = new GwtGraphics(root, config);
        } catch (Throwable e) {
            root.clear();
            root.add(new Label("Sorry, your browser doesn't seem to support WebGL"));
            return;
        }
        lastWidth = graphics.getWidth();
        lastHeight = graphics.getHeight();
        Gdx.app = this;
        Gdx.audio = new GwtAudio();
        Gdx.graphics = graphics;
        Gdx.gl20 = graphics.getGL20();
        Gdx.gl = Gdx.gl20;
        Gdx.files = new GwtFiles(preloader);
        this.input = new GwtInput(graphics.canvas);
        Gdx.input = this.input;
        this.net = new GwtNet();
        Gdx.net = this.net;
        this.clipboard = new GwtClipboard();

        // tell listener about app creation
        try {
            listener.create();
            listener.resize(graphics.getWidth(), graphics.getHeight());
        } catch (Throwable t) {
            error("GwtApplication", "exception: " + t.getMessage(), t);
            t.printStackTrace();
            throw new RuntimeException(t);
        }

        // setup rendering timer
        new Timer() {
            @Override
            public void run() {
                try {
                    mainLoop();
                } catch (Throwable t) {
                    error("GwtApplication", "exception: " + t.getMessage(), t);
                    throw new RuntimeException(t);
                }
            }
        }.scheduleRepeating((int) ((1f / config.fps) * 1000));
    }

    void mainLoop() {
        graphics.update();
        if (Gdx.graphics.getWidth() != lastWidth || Gdx.graphics.getHeight() != lastHeight) {
            GwtApplication.this.listener.resize(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
            lastWidth = graphics.getWidth();
            lastHeight = graphics.getHeight();
            Gdx.gl.glViewport(0, 0, lastWidth, lastHeight);
        }
        runnablesHelper.addAll(runnables);
        runnables.clear();
        for (int i = 0; i < runnablesHelper.size; i++) {
            runnablesHelper.get(i).run();
        }
        runnablesHelper.clear();
        graphics.frameId++;
        listener.render();
        input.reset();
    }

    public Panel getRootPanel() {
        return root;
    }

    long loadStart = TimeUtils.nanoTime();

    public Preloader createPreloader() {
        return new Preloader(getPreloaderBaseURL());
    }

    public PreloaderCallback getPreloaderCallback() {
        final Panel preloaderPanel = new VerticalPanel();
        preloaderPanel.setStyleName("gdx-preloader");
        final Image logo = new Image(GWT.getModuleBaseURL() + "logo.png");
        logo.setStyleName("logo");
        preloaderPanel.add(logo);
        final Panel meterPanel = new SimplePanel();
        meterPanel.setStyleName("gdx-meter");
        meterPanel.addStyleName("red");
        final InlineHTML meter = new InlineHTML();
        final Style meterStyle = meter.getElement().getStyle();
        meterStyle.setWidth(0, Unit.PCT);
        meterPanel.add(meter);
        preloaderPanel.add(meterPanel);
        getRootPanel().add(preloaderPanel);
        return new PreloaderCallback() {

            @Override
            public void error(String file) {
                System.out.println("error: " + file);
            }

            @Override
            public void update(PreloaderState state) {
                meterStyle.setWidth(100f * state.getProgress(), Unit.PCT);
            }

        };
    }

    @Override
    public Graphics getGraphics() {
        return graphics;
    }

    @Override
    public Audio getAudio() {
        return Gdx.audio;
    }

    @Override
    public Input getInput() {
        return Gdx.input;
    }

    @Override
    public Files getFiles() {
        return Gdx.files;
    }

    @Override
    public Net getNet() {
        return Gdx.net;
    }

    private void checkLogLabel() {
        if (log == null) {
            log = new TextArea();
            log.setSize(graphics.getWidth() + "px", "200px");
            log.setReadOnly(true);
            root.add(log);
        }
    }

    @Override
    public void log(String tag, String message) {
        if (logLevel >= LOG_INFO) {
            checkLogLabel();
            log.setText(log.getText() + "\n" + tag + ": " + message);
            log.setCursorPos(log.getText().length() - 1);
            System.out.println(tag + ": " + message);
        }
    }

    @Override
    public void log(String tag, String message, Throwable exception) {
        if (logLevel >= LOG_INFO) {
            checkLogLabel();
            log.setText(log.getText() + "\n" + tag + ": " + message + "\n" + exception.getMessage() + "\n");
            log.setCursorPos(log.getText().length() - 1);
            System.out.println(tag + ": " + message + "\n" + exception.getMessage());
            System.out.println(getStackTrace(exception));
        }
    }

    @Override
    public void error(String tag, String message) {
        if (logLevel >= LOG_ERROR) {
            checkLogLabel();
            log.setText(log.getText() + "\n" + tag + ": " + message);
            log.setCursorPos(log.getText().length() - 1);
            System.err.println(tag + ": " + message);
        }
    }

    @Override
    public void error(String tag, String message, Throwable exception) {
        if (logLevel >= LOG_ERROR) {
            checkLogLabel();
            log.setText(log.getText() + "\n" + tag + ": " + message + "\n" + exception.getMessage());
            log.setCursorPos(log.getText().length() - 1);
            System.err.println(tag + ": " + message + "\n" + exception.getMessage() + "\n");
            System.out.println(getStackTrace(exception));
        }
    }

    @Override
    public void debug(String tag, String message) {
        if (logLevel >= LOG_DEBUG) {
            checkLogLabel();
            log.setText(log.getText() + "\n" + tag + ": " + message + "\n");
            log.setCursorPos(log.getText().length() - 1);
            System.out.println(tag + ": " + message + "\n");
        }
    }

    @Override
    public void debug(String tag, String message, Throwable exception) {
        if (logLevel >= LOG_DEBUG) {
            checkLogLabel();
            log.setText(log.getText() + "\n" + tag + ": " + message + "\n" + exception.getMessage() + "\n");
            log.setCursorPos(log.getText().length() - 1);
            System.out.println(tag + ": " + message + "\n" + exception.getMessage());
            System.out.println(getStackTrace(exception));
        }
    }

    private String getStackTrace(Throwable e) {
        StringBuffer buffer = new StringBuffer();
        for (StackTraceElement trace : e.getStackTrace()) {
            buffer.append(trace.toString() + "\n");
        }
        return buffer.toString();
    }

    @Override
    public void setLogLevel(int logLevel) {
        this.logLevel = logLevel;
    }

    @Override
    public int getLogLevel() {
        return logLevel;
    }

    @Override
    public ApplicationType getType() {
        return ApplicationType.WebGL;
    }

    @Override
    public int getVersion() {
        return 0;
    }

    @Override
    public long getJavaHeap() {
        return 0;
    }

    @Override
    public long getNativeHeap() {
        return 0;
    }

    @Override
    public Preferences getPreferences(String name) {
        Preferences pref = prefs.get(name);
        if (pref == null) {
            pref = new GwtPreferences(name);
            prefs.put(name, pref);
        }
        return pref;
    }

    @Override
    public Clipboard getClipboard() {
        return clipboard;
    }

    @Override
    public void postRunnable(Runnable runnable) {
        runnables.add(runnable);
    }

    @Override
    public void exit() {
    }

    /** Contains precomputed information on the user-agent. Useful for dealing with browser and OS behavioral differences. Kindly
     * borrowed from PlayN */
    public static AgentInfo agentInfo() {
        return agentInfo;
    }

    /** kindly borrowed from PlayN **/
    private static native AgentInfo computeAgentInfo() /*-{
                                                         var userAgent = navigator.userAgent.toLowerCase();
                                                         return {
                                                         // browser type flags
                                                         isFirefox : userAgent.indexOf("firefox") != -1,
                                                         isChrome : userAgent.indexOf("chrome") != -1,
                                                         isSafari : userAgent.indexOf("safari") != -1,
                                                         isOpera : userAgent.indexOf("opera") != -1,
                                                         isIE : userAgent.indexOf("msie") != -1,
                                                         // OS type flags
                                                         isMacOS : userAgent.indexOf("mac") != -1,
                                                         isLinux : userAgent.indexOf("linux") != -1,
                                                         isWindows : userAgent.indexOf("win") != -1
                                                         };
                                                         }-*/;

    /** Returned by {@link #agentInfo}. Kindly borrowed from PlayN. */
    public static class AgentInfo extends JavaScriptObject {
        public final native boolean isFirefox() /*-{
                                                 return this.isFirefox;
                                                 }-*/;

        public final native boolean isChrome() /*-{
                                                 return this.isChrome;
                                                 }-*/;

        public final native boolean isSafari() /*-{
                                                 return this.isSafari;
                                                 }-*/;

        public final native boolean isOpera() /*-{
                                              return this.isOpera;
                                              }-*/;

        public final native boolean isIE() /*-{
                                           return this.isIE;
                                           }-*/;

        public final native boolean isMacOS() /*-{
                                              return this.isMacOS;
                                              }-*/;

        public final native boolean isLinux() /*-{
                                              return this.isLinux;
                                              }-*/;

        public final native boolean isWindows() /*-{
                                                 return this.isWindows;
                                                 }-*/;

        protected AgentInfo() {
        }
    }

    public String getBaseUrl() {
        return preloader.baseUrl;
    }

    public Preloader getPreloader() {
        return preloader;
    }

    public CanvasElement getCanvasElement() {
        return graphics.canvas;
    }

    public LoadingListener getLoadingListener() {
        return loadingListener;
    }

    public void setLoadingListener(LoadingListener loadingListener) {
        this.loadingListener = loadingListener;
    }

    @Override
    public void addLifecycleListener(LifecycleListener listener) {
        synchronized (lifecycleListeners) {
            lifecycleListeners.add(listener);
        }
    }

    @Override
    public void removeLifecycleListener(LifecycleListener listener) {
        synchronized (lifecycleListeners) {
            lifecycleListeners.removeValue(listener, true);
        }
    }

    native static public void consoleLog(String message) /*-{
                                                         console.log( "GWT: " + message );
                                                         }-*/;

    /**
     * LoadingListener interface main purpose is to do some things before or after {@link GwtApplication#setupLoop()}
     */
    public interface LoadingListener {
        /**
         * Method called before the setup
         */
        public void beforeSetup();

        /**
         * Method called after the setup
         */
        public void afterSetup();
    }
}