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

Java tutorial

Introduction

Here is the source code for com.badlogic.gdx.backends.gwt.GwtApplicationCustom.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.soundmanager2.SoundManager;
import com.badlogic.gdx.graphics.Pixmap;
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.canvas.client.Canvas;
import com.google.gwt.canvas.dom.client.Context2d;
import com.google.gwt.canvas.dom.client.Context2d.TextAlign;
import com.google.gwt.canvas.dom.client.Context2d.TextBaseline;
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.Document;
import com.google.gwt.dom.client.Element;
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.Label;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.RootPanel;
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()},
 * {@link #getApplicationListener()} and {@link #getAssetsPath()}. Clients can override the default loading screen via
 * {@link #getPreloaderCallback()} and implement any loading screen drawing via GWT widgets.
 * @author mzechner */
public abstract class GwtApplicationCustom 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, lastHeight;
    private Preloader preloader;
    private static AgentInfo agentInfo;
    private ObjectMap<String, Preferences> prefs = new ObjectMap<String, Preferences>();

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

    /** @return the {@link ApplicationListener} to be run by the {@link GwtApplicationCustom}. */
    public abstract ApplicationListener getApplicationListener();

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

        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("100%");
                panel.setHeight("100%");
                //            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");
                RootPanel.get().setWidth("100%");
                RootPanel.get().setHeight("100%");
                this.root = panel;
            } else {
                VerticalPanel panel = new VerticalPanel();
                panel.setWidth("100%");
                panel.setHeight("100%");
                panel.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);
                panel.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE);
                element.appendChild(panel.getElement());
                root = panel;
            }
        }

        // initialize SoundManager2
        SoundManager.init(GWT.getModuleBaseURL(), 9);

        // wait for soundmanager to load, this is fugly, but for
        // some reason the ontimeout and onerror callbacks are never
        // called (function instanceof Function fails, wtf JS?).
        new Timer() {
            @Override
            public void run() {
                if (SoundManager.swfLoaded()) {
                    final PreloaderCallback callback = getPreloaderCallback();
                    preloader = new Preloader();
                    preloader.preload("assets.txt", new PreloaderCallback() {
                        @Override
                        public void loaded(String file, int loaded, int total) {
                            callback.loaded(file, loaded, total);
                        }

                        @Override
                        public void error(String file) {
                            callback.error(file);
                        }

                        @Override
                        public void done() {
                            callback.done();
                            root.clear();
                            setupLoop();
                        }
                    });
                    cancel();
                }
            }
        }.scheduleRepeating(100);
    }

    private void setupLoop() {
        // setup modules
        try {
            graphics = new GwtGraphics(root, config);
            graphics.setDisplayMode(480, 320, true);
        } 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 = graphics.getGLCommon();
        Gdx.files = new GwtFiles(preloader);
        this.input = new GwtInput(graphics.canvas);
        Gdx.input = this.input;
        this.net = new GwtNet();
        Gdx.net = this.net;

        // 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 {
                    graphics.update();
                    if (Gdx.graphics.getWidth() != lastWidth || Gdx.graphics.getHeight() != lastHeight) {
                        GwtApplicationCustom.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();
                    listener.render();
                    input.justTouched = false;
                } catch (Throwable t) {
                    error("GwtApplication", "exception: " + t.getMessage(), t);
                    throw new RuntimeException(t);
                }
            }
        }.scheduleRepeating((int) ((1f / config.fps) * 1000));
    }

    public Panel getRootPanel() {
        return root;
    }

    long loadStart = TimeUtils.nanoTime();

    public PreloaderCallback getPreloaderCallback() {
        final Canvas canvas = Canvas.createIfSupported();
        canvas.setWidth("100%");
        canvas.setHeight("100%");
        getRootPanel().add(canvas);
        final Context2d context = canvas.getContext2d();
        context.setTextAlign(TextAlign.CENTER);
        context.setTextBaseline(TextBaseline.MIDDLE);
        context.setFont("18pt Calibri");

        return new PreloaderCallback() {
            @Override
            public void done() {
                context.fillRect(0, 0, 300, 40);
            }

            @Override
            public void loaded(String file, int loaded, int total) {
                System.out.println("loaded " + file + "," + loaded + "/" + total);
                //            String color = Pixmap.make(30, 30, 30, 1);
                //            context.setFillStyle(color);
                //            context.setStrokeStyle(color);
                context.fillRect(0, 0, 300, 70);
                //            color = Pixmap.make(200, 200, 200, (((TimeUtils.nanoTime() - loadStart) % 1000000000) / 1000000000f));
                //            context.setFillStyle(color);
                //            context.setStrokeStyle(color);
                context.fillRect(0, 0, 300 * (loaded / (float) total) * 0.97f, 70);

                //            context.setFillStyle(Pixmap.make(50, 50, 50, 1));
                context.fillText("loading", 300 / 2, 70 / 2);
            }

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

    @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, Exception 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 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 new Clipboard() {
            @Override
            public String getContents() {
                return null;
            }

            @Override
            public void setContents(String content) {
            }
        };
    }

    @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;
    }

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

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