VASSAL.launch.EditorWindow.java Source code

Java tutorial

Introduction

Here is the source code for VASSAL.launch.EditorWindow.java

Source

/*
 * $Id$
 *
 * Copyright (c) 2000-2008 by Brent Easton, Rodney Kinney, Joel Uckelman
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License (LGPL) as published by the Free Software Foundation.
 *
 * This library 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, copies are available
 * at http://www.opensource.org.
 */

package VASSAL.launch;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JFrame;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JToolBar;
import javax.swing.KeyStroke;

import org.apache.commons.lang.SystemUtils;

import VASSAL.build.GameModule;
import VASSAL.build.module.Documentation;
import VASSAL.build.module.documentation.HelpWindow;
import VASSAL.configure.ConfigureTree;
import VASSAL.configure.ModuleUpdaterDialog;
import VASSAL.configure.SaveAction;
import VASSAL.configure.SaveAsAction;
import VASSAL.configure.ShowHelpAction;
import VASSAL.configure.ValidationReport;
import VASSAL.configure.ValidationReportDialog;
import VASSAL.i18n.Resources;
import VASSAL.tools.ApplicationIcons;
import VASSAL.tools.ErrorDialog;
import VASSAL.tools.URLUtils;
import VASSAL.tools.menu.ChildProxy;
import VASSAL.tools.menu.MenuBarProxy;
import VASSAL.tools.menu.MenuManager;
import VASSAL.tools.menu.MenuProxy;

/**
 * EditorWindow is the base class for the three top-level component
 * editors :- ModuleEditorWindow, ExtensionEditorWindow, PluginEditorWindow
 *
 * @author Brent Easton
 */
public abstract class EditorWindow extends JFrame {
    private static final long serialVersionUID = 1L;

    protected SaveAction saveAction;
    protected SaveAsAction saveAsAction;
    protected JMenuItem componentHelpItem;
    protected Action createUpdater;

    protected final HelpWindow helpWindow = new HelpWindow(
            Resources.getString("Editor.ModuleEditor.reference_manual"), //$NON-NLS-1$
            null);

    protected ConfigureTree tree;

    public abstract String getEditorType();

    protected final JToolBar toolBar = new JToolBar();

    protected final JScrollPane scrollPane;

    protected EditorWindow() {
        setTitle("VASSAL " + getEditorType() + " Editor");
        setLayout(new BorderLayout());

        ApplicationIcons.setFor(this);

        setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
        addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
                close();
            }
        });

        toolBar.setFloatable(false);
        add(toolBar, BorderLayout.NORTH);

        // setup menubar and actions
        final MenuManager mm = MenuManager.getInstance();
        final MenuBarProxy mb = mm.getMenuBarProxyFor(this);

        // file menu
        if (SystemUtils.IS_OS_MAC_OSX) {
            mm.addToSection("Editor.File", mm.addKey("Editor.save"));
            mm.addToSection("Editor.File", mm.addKey("Editor.save_as"));
        } else {
            final MenuProxy fileMenu = new MenuProxy(Resources.getString("General.file"));

            // FIMXE: setting nmemonic from first letter could cause collisions in
            // some languages
            fileMenu.setMnemonic(Resources.getString("General.file.shortcut").charAt(0));

            fileMenu.add(mm.addKey("Editor.save"));
            fileMenu.add(mm.addKey("Editor.save_as"));
            fileMenu.addSeparator();
            fileMenu.add(mm.addKey("General.quit"));
            mb.add(fileMenu);
        }

        // edit menu
        final MenuProxy editMenu = new MenuProxy(Resources.getString("General.edit"));
        editMenu.setMnemonic(Resources.getString("General.edit.shortcut").charAt(0));

        editMenu.add(mm.addKey("Editor.cut"));
        editMenu.add(mm.addKey("Editor.copy"));
        editMenu.add(mm.addKey("Editor.paste"));
        editMenu.add(mm.addKey("Editor.move"));
        editMenu.addSeparator();
        editMenu.add(mm.addKey("Editor.ModuleEditor.properties"));
        editMenu.add(mm.addKey("Editor.ModuleEditor.translate"));

        // tools menu
        final MenuProxy toolsMenu = new MenuProxy(Resources.getString("General.tools"));
        toolsMenu.setMnemonic(Resources.getString("General.tools.shortcut").charAt(0));

        toolsMenu.add(mm.addKey("create_module_updater"));
        toolsMenu.add(mm.addKey("Editor.ModuleEditor.update_saved"));

        if (SystemUtils.IS_OS_MAC_OSX) {
            mm.addToSection("Editor.MenuBar", editMenu);
            mm.addToSection("Editor.MenuBar", toolsMenu);
        } else {
            mb.add(editMenu);
            mb.add(toolsMenu);
        }

        // help menu
        if (SystemUtils.IS_OS_MAC_OSX) {
            mm.addToSection("Documentation.VASSAL", mm.addKey("Editor.ModuleEditor.reference_manual"));
        } else {
            final MenuProxy helpMenu = new MenuProxy(Resources.getString("General.help"));

            // FIMXE: setting nmemonic from first letter could cause collisions in
            // some languages
            helpMenu.setMnemonic(Resources.getString("General.help.shortcut").charAt(0));

            helpMenu.add(mm.addKey("General.help"));
            helpMenu.add(mm.addKey("Editor.ModuleEditor.reference_manual"));
            helpMenu.addSeparator();
            helpMenu.add(mm.addKey("AboutScreen.about_vassal"));
            mb.add(helpMenu);
        }

        final int mask = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();

        saveAction = new SaveAction() {
            private static final long serialVersionUID = 1L;

            public void actionPerformed(ActionEvent e) {
                save();
                treeStateChanged(false);
            }
        };

        saveAction.setEnabled(false);
        saveAction.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_S, mask));
        mm.addAction("Editor.save", saveAction);
        toolBar.add(saveAction);

        saveAsAction = new SaveAsAction() {
            private static final long serialVersionUID = 1L;

            public void actionPerformed(ActionEvent e) {
                saveAs();
                treeStateChanged(false);
            }
        };

        saveAsAction.setEnabled(false);
        saveAsAction.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_A, mask));
        mm.addAction("Editor.save_as", saveAsAction);
        toolBar.add(saveAsAction);

        mm.addAction("General.quit", new ShutDownAction());
        // FXIME: mnemonics should be language-dependant
        //    mm.getAction("General.quit").setMnemonic('Q');

        createUpdater = new AbstractAction("Create " + getEditorType() + " updater") {
            private static final long serialVersionUID = 1L;

            public void actionPerformed(ActionEvent e) {
                new ModuleUpdaterDialog(EditorWindow.this).setVisible(true);
            }
        };
        createUpdater.setEnabled(false);
        mm.addAction("create_module_updater", createUpdater);

        URL url = null;
        try {
            url = new File(Documentation.getDocumentationBaseDir(), "README.html").toURI().toURL();
        } catch (MalformedURLException e) {
            ErrorDialog.bug(e);
        }
        mm.addAction("General.help", new ShowHelpAction(url, null));

        url = null;
        try {
            File dir = VASSAL.build.module.Documentation.getDocumentationBaseDir();
            dir = new File(dir, "ReferenceManual/index.htm"); //$NON-NLS-1$
            url = URLUtils.toURL(dir);
        } catch (MalformedURLException e) {
            ErrorDialog.bug(e);
        }

        final Action helpAction = new ShowHelpAction(url, helpWindow.getClass().getResource("/images/Help16.gif")); //$NON-NLS-1$
        helpAction.putValue(Action.SHORT_DESCRIPTION, Resources.getString("Editor.ModuleEditor.reference_manual")); //$NON-NLS-1$

        mm.addAction("Editor.ModuleEditor.reference_manual", helpAction);
        toolBar.add(helpAction);

        mm.addAction("AboutScreen.about_vassal", new AboutVASSALAction(this));

        setJMenuBar(mm.getMenuBarFor(this));

        // the presence of the panel prevents a NullPointerException on packing
        final JPanel panel = new JPanel();
        panel.setPreferredSize(new Dimension(250, 400));

        scrollPane = new JScrollPane(panel, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
                JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);

        add(scrollPane, BorderLayout.CENTER);
        pack();
    }

    protected MenuProxy findMenuProxy(String name, MenuBarProxy mb) {
        for (ChildProxy<?> c : mb.getChildren()) {
            if (c instanceof MenuProxy) {
                final MenuProxy m = (MenuProxy) c;
                if (name.equals(m.getText()))
                    return m;
            }
        }
        return null;
    }

    /*
     * Each component must Save, SaveAs and close itself
     */
    protected abstract void save();

    protected abstract void saveAs();

    protected void close() {
        GameModule.getGameModule().quit();
    }

    protected void saver(final Runnable save) {
        final ValidationReport report = new ValidationReport();
        GameModule.getGameModule().validate(GameModule.getGameModule(), report);
        if (report.getWarnings().size() == 0) {
            save.run();
        } else {
            new ValidationReportDialog(report, new ValidationReportDialog.CallBack() {
                public void ok() {
                    save.run();
                }

                public void cancel() {
                }
            }).setVisible(true);
        }
    }

    /**
     * Called by the enclosed ConfigureTree or ExtensionTree when it's dirty
     * state is changed. The implementing class should override this if they
     * need to take action like changing menu availability.
     *
     * @param changed true if the tree is in a changed (dirty) state
     */
    public void treeStateChanged(boolean changed) {
    }
}