es.eucm.ead.editor.EditorDesktop.java Source code

Java tutorial

Introduction

Here is the source code for es.eucm.ead.editor.EditorDesktop.java

Source

/**
 * eAdventure is a research project of the
 *    e-UCM research group.
 *
 *    Copyright 2005-2014 e-UCM research group.
 *
 *    You can access a list of all the contributors to eAdventure at:
 *          http://e-adventure.e-ucm.es/contributors
 *
 *    e-UCM is a research group of the Department of Software Engineering
 *          and Artificial Intelligence at the Complutense University of Madrid
 *          (School of Computer Science).
 *
 *          CL Profesor Jose Garcia Santesmases 9,
 *          28040 Madrid (Madrid), Spain.
 *
 *          For more info please visit:  <http://e-adventure.e-ucm.es> or
 *          <http://www.e-ucm.es>
 *
 * ****************************************************************************
 *
 *  This file is part of eAdventure
 *
 *      eAdventure is free software: you can redistribute it and/or modify
 *      it under the terms of the GNU Lesser General Public License as published by
 *      the Free Software Foundation, either version 3 of the License, or
 *      (at your option) any later version.
 *
 *      eAdventure 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 Lesser General Public License for more details.
 *
 *      You should have received a copy of the GNU Lesser General Public License
 *      along with eAdventure.  If not, see <http://www.gnu.org/licenses/>.
 */
package es.eucm.ead.editor;

import com.badlogic.gdx.Application;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration;
import com.badlogic.gdx.backends.lwjgl.LwjglFrame;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.Group;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.InputListener;
import com.badlogic.gdx.scenes.scene2d.ui.Label.LabelStyle;
import es.eucm.ead.editor.control.Controller;
import es.eucm.ead.editor.control.Preferences;
import es.eucm.ead.editor.control.ShortcutsMap;
import es.eucm.ead.editor.control.actions.EditorActionException;
import es.eucm.ead.editor.control.actions.editor.Back;
import es.eucm.ead.editor.control.actions.editor.ChangeView;
import es.eucm.ead.editor.control.actions.editor.CheckUpdates;
import es.eucm.ead.editor.control.actions.editor.Copy;
import es.eucm.ead.editor.control.actions.editor.Cut;
import es.eucm.ead.editor.control.actions.editor.Exit;
import es.eucm.ead.editor.control.actions.editor.Next;
import es.eucm.ead.editor.control.actions.editor.OpenGame;
import es.eucm.ead.editor.control.actions.editor.Paste;
import es.eucm.ead.editor.control.actions.editor.Redo;
import es.eucm.ead.editor.control.actions.editor.Save;
import es.eucm.ead.editor.control.actions.editor.Undo;
import es.eucm.ead.editor.control.views.NoProjectView;
import es.eucm.ead.editor.model.Model.FieldListener;
import es.eucm.ead.editor.model.Model.ModelListener;
import es.eucm.ead.editor.model.Q;
import es.eucm.ead.editor.model.events.FieldEvent;
import es.eucm.ead.editor.model.events.LoadEvent;
import es.eucm.ead.editor.platform.Platform;
import es.eucm.ead.editor.ui.DesktopViewsRoot;
import es.eucm.ead.editor.ui.EditorWindow;
import es.eucm.ead.editor.view.tooltips.TooltipManager;
import es.eucm.ead.engine.I18N;
import es.eucm.ead.engine.utils.SwingEDTUtils;
import es.eucm.ead.schema.editor.components.Documentation;
import es.eucm.ead.schemax.FieldName;

import javax.swing.JFrame;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

public class EditorDesktop extends EditorApplicationListener {

    public boolean debug;

    private LwjglFrame frame;

    private Group viewsRoot;

    private I18N i18N;

    /**
     * EditorDesktop admits as optional parameter the absolute path of a
     * project. If that parameter is not null, it will try to open that project
     * once the editor has been initialized. This is needed to support platform
     * file extension bindings (to allow users double click project files to
     * open them on the editor).
     */
    private String projectToOpenPath;

    protected TooltipManager tooltipManager;

    /**
     * The editor desktop requires a {@link Platform}, that will be typically
     * {@link DesktopPlatform}. It also can get the absolute path of a project
     * directory to be loaded with.
     * 
     * @param platform
     *            The platform object
     * @param projectToOpenPath
     *            The full path of a project that has to be loaded upon startup
     *            (e.g. C:/Users/A user/eadgames/testgame/). If null, the editor
     *            opens the default view. (see {@link #initialize()} for more
     *            details).
     * @param debug
     *            True if the editor has to be launched in debug mode, false
     *            otherwise
     */
    public EditorDesktop(Platform platform, String projectToOpenPath, boolean debug) {
        super(platform);
        this.projectToOpenPath = projectToOpenPath;
        this.debug = debug;
    }

    @Override
    public void create() {
        // Setting debug ASAP
        if (debug) {
            Gdx.app.setLogLevel(Application.LOG_DEBUG);
        }
        super.create();
    }

    @Override
    protected void initialize() {
        super.initialize();
        Gdx.gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
        i18N = controller.getApplicationAssets().getI18N();
        stage.addActor(buildRootView());
        registerShortcuts();
        initFrame();
        addTitleListener();
        openLastProject();
        tooltipManager = new TooltipManager(stage.getRoot(),
                controller.getApplicationAssets().getSkin().get("tooltip", LabelStyle.class));
        controller.action(CheckUpdates.class, controller.getReleaseInfo(), false);
    }

    @Override
    protected Controller buildController() {
        this.viewsRoot = buildViewsRoot();
        return new Controller(platform, Gdx.files, viewsRoot, buildModalsContainer());
    }

    protected Group buildViewsRoot() {
        return new DesktopViewsRoot();
    }

    protected Group buildModalsContainer() {
        return stage.getRoot();
    }

    protected Actor buildRootView() {
        return new EditorWindow(viewsRoot, controller);
    }

    private void addTitleListener() {
        controller.getModel().addLoadListener(new ModelListener<LoadEvent>() {

            private FieldListener titleListener = new FieldListener() {
                @Override
                public boolean listenToField(String fieldName) {
                    return FieldName.NAME.equals(fieldName);
                }

                @Override
                public void modelChanged(FieldEvent event) {
                    platform.setTitle(i18N.m("application.title", event.getValue() + "",
                            controller.getEditorGameAssets().getLoadingPath()));
                }
            };

            @Override
            public void modelChanged(LoadEvent event) {
                switch (event.getType()) {
                case LOADED:
                    Documentation documentation = Q.getComponent(event.getModel().getGame(), Documentation.class);
                    String title = Q.getTitle(event.getModel().getGame());
                    platform.setTitle(i18N.m("application.title", title == null ? "" : title,
                            controller.getEditorGameAssets().getLoadingPath()));
                    event.getModel().addFieldListener(documentation, titleListener);
                    break;
                case UNLOADED:
                    platform.setTitle(i18N.m("application.title.noproject"));
                    break;
                }
            }
        });
        platform.setTitle(i18N.m("application.title.noproject"));
    }

    private void openLastProject() {
        if (projectToOpenPath == null) {
            projectToOpenPath = controller.getPreferences().getString(Preferences.LAST_OPENED_GAME);
        }

        if (projectToOpenPath != null && !"".equals(projectToOpenPath)) {
            try {
                controller.action(OpenGame.class, projectToOpenPath);
            } catch (EditorActionException eae) {
                // the project is probably corrupt; complain but continue
                Gdx.app.log("OpenLastProject", "Error opening '" + projectToOpenPath + "'; ignoring request");
                controller.action(ChangeView.class, NoProjectView.class);
            }
        } else {
            controller.action(ChangeView.class, NoProjectView.class);
        }
    }

    protected void initFrame() {
        // Load some desktop preferences
        final Preferences preferences = controller.getPreferences();
        // Frame size
        ((DesktopPlatform) platform).initFileChooser(controller, stage);
        frame = ((DesktopPlatform) platform).getFrame();
        frame.addComponentListener(new ComponentAdapter() {
            @Override
            public void componentMoved(ComponentEvent e) {
                Preferences preferences = controller.getPreferences();
                preferences.putInteger(Preferences.WINDOW_X, frame.getLocation().x);
                preferences.putInteger(Preferences.WINDOW_Y, frame.getLocation().y);
            }

            @Override
            public void componentResized(ComponentEvent e) {
                Preferences preferences = controller.getPreferences();
                preferences.putInteger(Preferences.WINDOW_WIDTH, frame.getWidth());
                preferences.putInteger(Preferences.WINDOW_HEIGHT, frame.getHeight());
                preferences.putBoolean(Preferences.WINDOW_MAXIMIZED,
                        frame.getExtendedState() == JFrame.MAXIMIZED_BOTH);
            }
        });

        frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
        frame.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                controller.action(Exit.class);
            }
        });

        if (preferences.getBoolean(Preferences.WINDOW_MAXIMIZED)) {
            frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
        } else {
            int x = preferences.getInteger(Preferences.WINDOW_X, 0);
            int y = preferences.getInteger(Preferences.WINDOW_Y, 0);
            Dimension dimension = Toolkit.getDefaultToolkit().getScreenSize();
            int width = preferences.getInteger(Preferences.WINDOW_WIDTH, dimension.width);
            int height = preferences.getInteger(Preferences.WINDOW_HEIGHT, dimension.height);
            frame.setLocation(x, y);
            frame.setSize(width, height);
        }
    }

    @Override
    public void render() {
        super.render();
        tooltipManager.update(Gdx.graphics.getDeltaTime());
    }

    private void registerShortcuts() {
        final ShortcutsMap shortcutsMap = controller.getShortcutsMap();
        stage.addListener(new InputListener() {
            @Override
            public boolean keyDown(InputEvent event, int keycode) {
                return !event.isHandled() && shortcutsMap.shortcut(keycode);
            }
        });
        shortcutsMap.registerShortcutCtrl(Keys.O, OpenGame.class);
        shortcutsMap.registerShortcutCtrl(Keys.S, Save.class);

        shortcutsMap.registerShortcutCtrl(Keys.X, Cut.class);
        shortcutsMap.registerShortcutCtrl(Keys.C, Copy.class);
        shortcutsMap.registerShortcutCtrl(Keys.V, Paste.class);

        shortcutsMap.registerShortcutCtrl(Keys.Z, Undo.class);
        shortcutsMap.registerShortcutCtrl(Keys.Y, Redo.class);

        shortcutsMap.registerShortcutKey(Keys.BACKSPACE, Back.class);
        shortcutsMap.registerShortcutAlt(Keys.BACKSPACE, Next.class);

    }

    /**
     * {@link EditorDesktop} admits two optional arguments: args[0] The full
     * path of a project.json file to open the editor with args[1] "debug" to
     * launch the editor in debug mode. Question: What does this actually do?
     */
    public static void main(String[] args) {
        boolean debug = false;
        if (args != null) {
            for (String arg : args) {
                if ("debug".equals(arg.toLowerCase())) {
                    debug = true;
                    break;
                }
            }
        }
        LwjglApplicationConfiguration config = new LwjglApplicationConfiguration();
        config.forceExit = true;
        DesktopPlatform platform = new DesktopPlatform();
        final LwjglFrame frame = new LwjglFrame(
                new EditorDesktop(platform, (args.length > 0 && !"debug".equals(args[0])) ? args[0] : null, debug),
                config);
        frame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
        platform.setFrame(frame);
        // set visible calls create()

        SwingEDTUtils.invokeLater(new Runnable() {

            @Override
            public void run() {
                frame.setVisible(true);
            }
        });

    }
}