add more status notifications to core listener
[jSite2.git] / src / net / pterodactylus / jsite / gui / SwingInterface.java
index ef15f79..e022cf1 100644 (file)
 package net.pterodactylus.jsite.gui;
 
 import java.awt.event.ActionEvent;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
 import java.util.List;
+import java.util.Locale;
+import java.util.Properties;
 
-import javax.swing.Action;
+import javax.swing.JOptionPane;
 
 import net.pterodactylus.jsite.core.Core;
 import net.pterodactylus.jsite.core.CoreListener;
 import net.pterodactylus.jsite.core.Node;
+import net.pterodactylus.jsite.core.Project;
+import net.pterodactylus.jsite.i18n.I18n;
+import net.pterodactylus.jsite.i18n.gui.I18nAction;
+import net.pterodactylus.util.io.Closer;
 
 /**
- * TODO
- * 
+ * The Swing user interface.
+ *
  * @author David ‘Bombe’ Roden <bombe@freenetproject.org>
  * @version $Id$
  */
@@ -39,32 +50,95 @@ public class SwingInterface implements CoreListener {
        /** The application core. */
        private final Core core;
 
+       /** The configuration directory. */
+       private final String configDirectory;
+
        /** The main window. */
        private MainWindow mainWindow;
 
+       /** The “configure” action. */
+       private I18nAction configureAction;
+
+       /** The “import config” action. */
+       private I18nAction importConfigAction;
+
+       /** The “quit” action. */
+       private I18nAction quitAction;
+
        /** The “manage nodes” action. */
-       private Action manageNodesAction;
+       private I18nAction manageNodesAction;
 
        /** The “connect to node” action. */
-       private Action nodeConnectAction;
+       private I18nAction nodeConnectAction;
 
        /** The “disconnect from node” action. */
-       private Action nodeDisconnectAction;
+       private I18nAction nodeDisconnectAction;
 
        /** The node manager dialog. */
        private ManageNodesDialog manageNodesDialog;
 
+       /** All lanugage menu items. */
+       private List<I18nAction> languageActions = new ArrayList<I18nAction>();
+
+       /** The “about” action. */
+       private I18nAction helpAboutAction;
+
+       /** The “add project” action. */
+       private I18nAction addProjectAction;
+
+       /** The “clone project” action. */
+       private I18nAction cloneProjectAction;
+
+       /** The “delete project” action. */
+       private I18nAction deleteProjectAction;
+
+       /** The “about” dialog. */
+       private AboutDialog aboutDialog;
+
+       /** The configuration dialog. */
+       private ConfigurationDialog configurationDialog;
+
        /** The list of all defined nodes. */
        private List<Node> nodeList;
 
+       //
+       // CONFIGURATION
+       //
+
+       /** The advanced mode. */
+       private boolean advancedMode;
+
+       /** Whether to antialias the GUI. */
+       private boolean antialias;
+
+       /** The control font. */
+       private String controlFont;
+
+       /** The user font. */
+       private String userFont;
+
        /**
         * Creates a new swing interface.
-        * 
+        *
         * @param core
         *            The core to operate on
+        * @param configDirectory
+        *            The directory the configuration is stored in
         */
-       public SwingInterface(Core core) {
+       public SwingInterface(Core core, String configDirectory) {
                this.core = core;
+               this.configDirectory = configDirectory;
+               I18n.setLocale(Locale.ENGLISH);
+               loadConfig();
+               if (antialias) {
+                       System.setProperty("swing.aatext", "true");
+               }
+               if (controlFont != null) {
+                       System.setProperty("swing.plaf.metal.controlFont", controlFont);
+               }
+               if (userFont != null) {
+                       System.setProperty("swing.plaf.metal.userFont", userFont);
+               }
                initActions();
                initDialogs();
        }
@@ -74,32 +148,122 @@ public class SwingInterface implements CoreListener {
        //
 
        /**
+        * Returns the core that is controlled by the Swing interface.
+        *
+        * @return The core
+        */
+       Core getCore() {
+               return core;
+       }
+
+       /**
+        * Returns the main window of the Swing interface.
+        *
+        * @return The main window
+        */
+       MainWindow getMainWindow() {
+               return mainWindow;
+       }
+
+       /**
+        * Returns the “configure” action.
+        *
+        * @return The “configure” action
+        */
+       I18nAction getConfigureAction() {
+               return configureAction;
+       }
+
+       /**
+        * Returns the “import config” action.
+        *
+        * @return The “import config” action
+        */
+       I18nAction getImportConfigAction() {
+               return importConfigAction;
+       }
+
+       /**
+        * Returns the “quit” action.
+        *
+        * @return The “quit” action
+        */
+       I18nAction getQuitAction() {
+               return quitAction;
+       }
+
+       /**
         * Returns the “manage nodes” action.
-        * 
+        *
         * @return The “manage nodes” action
         */
-       public Action getManageNodesAction() {
+       I18nAction getManageNodesAction() {
                return manageNodesAction;
        }
 
        /**
         * Returns the “connect to node” action.
-        * 
+        *
         * @return The “connect to node” action
         */
-       public Action getNodeConnectAction() {
+       I18nAction getNodeConnectAction() {
                return nodeConnectAction;
        }
 
        /**
         * Returns the “disconnect from node” action.
-        * 
+        *
         * @return The “disconnect from node” action
         */
-       public Action getNodeDisconnectAction() {
+       I18nAction getNodeDisconnectAction() {
                return nodeDisconnectAction;
        }
 
+       /**
+        * Returns all language actions.
+        *
+        * @return All language actions
+        */
+       List<I18nAction> getLanguageActions() {
+               return languageActions;
+       }
+
+       /**
+        * Returns the “about” action.
+        *
+        * @return The “about” action
+        */
+       I18nAction getHelpAboutAction() {
+               return helpAboutAction;
+       }
+
+       /**
+        * Returns the “add project” action.
+        *
+        * @return The “add project” action
+        */
+       I18nAction getAddProjectAction() {
+               return addProjectAction;
+       }
+
+       /**
+        * Returns the “clone project” action.
+        *
+        * @return The “clone project” action
+        */
+       I18nAction getCloneProjectAction() {
+               return cloneProjectAction;
+       }
+
+       /**
+        * Returns the “delete project” action.
+        *
+        * @return The “delete project” action
+        */
+       I18nAction getDeleteProjectAction() {
+               return deleteProjectAction;
+       }
+
        //
        // ACTIONS
        //
@@ -120,23 +284,129 @@ public class SwingInterface implements CoreListener {
        //
 
        /**
+        * Loads the configuration of the interface.
+        */
+       private void loadConfig() {
+               /* initialize default stuff. */
+               antialias = false;
+               /* now read config. */
+               File configFile = new File(configDirectory, "swing-interface.properties");
+               if (!configFile.exists() || !configFile.canRead() || !configFile.isFile()) {
+                       System.err.println("could not find “" + configFile.getAbsolutePath() + "”!");
+                       return;
+               }
+               Properties configProperties = new Properties();
+               FileInputStream configInputStream = null;
+               try {
+                       configInputStream = new FileInputStream(configFile);
+                       configProperties.load(configInputStream);
+               } catch (IOException ioe1) {
+                       System.err.println("could not load config, " + ioe1.getMessage());
+               } finally {
+                       Closer.close(configInputStream);
+               }
+               if (configProperties.containsKey("advancedMode")) {
+                       advancedMode = Boolean.valueOf(configProperties.getProperty("advancedMode"));
+               }
+               if (configProperties.containsKey("antialias")) {
+                       antialias = Boolean.valueOf(configProperties.getProperty("antialias"));
+               }
+               if (configProperties.containsKey("controlFont")) {
+                       controlFont = configProperties.getProperty("controlFont");
+               }
+               if (configProperties.containsKey("userFont")) {
+                       userFont = configProperties.getProperty("userFont");
+               }
+               if (configProperties.containsKey("language")) {
+                       I18n.setLocale(new Locale(configProperties.getProperty("language")));
+               }
+       }
+
+       /**
+        * Saves the configuration.
+        */
+       private void saveConfig() {
+               File configDirectory = new File(this.configDirectory);
+               if (!configDirectory.exists()) {
+                       if (!configDirectory.mkdirs()) {
+                               System.err.println("could not create “" + this.configDirectory + "”!");
+                               return;
+                       }
+               }
+               if (!configDirectory.exists() || !configDirectory.isDirectory() || !configDirectory.canWrite()) {
+                       System.err.println("can not access “" + this.configDirectory + "”!");
+                       return;
+               }
+               File configFile = new File(configDirectory, "swing-interface.properties");
+               Properties configProperties = new Properties();
+               configProperties.setProperty("advancedMode", String.valueOf(advancedMode));
+               configProperties.setProperty("antialias", String.valueOf(antialias));
+               if (controlFont != null) {
+                       configProperties.setProperty("controlFont", controlFont);
+               }
+               if (userFont != null) {
+                       configProperties.setProperty("userFont", userFont);
+               }
+               configProperties.setProperty("language", I18n.getLocale().getLanguage());
+               FileOutputStream configOutputStream = null;
+               try {
+                       configOutputStream = new FileOutputStream(configFile);
+                       configProperties.store(configOutputStream, "configuration of swing interface");
+               } catch (IOException ioe1) {
+                       System.err.println("could not save config, " + ioe1.getMessage());
+               } finally {
+                       Closer.close(configOutputStream);
+               }
+       }
+
+       /**
         * Initializes all actions.
         */
        private void initActions() {
+               configureAction = new I18nAction("mainWindow.menu.jSite.configure") {
+
+                       /**
+                        * {@inheritDoc}
+                        */
+                       @SuppressWarnings("synthetic-access")
+                       public void actionPerformed(ActionEvent actionEvent) {
+                               configure();
+                       }
+               };
+               importConfigAction = new I18nAction("mainWindow.menu.jSite.importConfig") {
+
+                       /**
+                        * {@inheritDoc}
+                        */
+                       @SuppressWarnings("synthetic-access")
+                       public void actionPerformed(ActionEvent actionEvent) {
+                               importConfig();
+                       }
+               };
+               quitAction = new I18nAction("mainWindow.menu.jSite.quit") {
+
+                       /**
+                        * {@inheritDoc}
+                        */
+                       @SuppressWarnings("synthetic-access")
+                       public void actionPerformed(ActionEvent actionEvent) {
+                               quit();
+                       }
+               };
                manageNodesAction = new I18nAction("mainWindow.menu.node.item.manageNodes") {
 
                        /**
                         * {@inheritDoc}
                         */
                        @SuppressWarnings("synthetic-access")
-                       public void actionPerformed(ActionEvent e) {
+                       public void actionPerformed(ActionEvent actionEvent) {
                                manageNodes();
                        }
                };
                nodeConnectAction = new I18nAction("mainWindow.menu.node.item.connect", false) {
 
                        @SuppressWarnings("synthetic-access")
-                       public void actionPerformed(ActionEvent e) {
+                       public void actionPerformed(ActionEvent actionEvent) {
                                nodeConnect();
                        }
 
@@ -151,67 +421,300 @@ public class SwingInterface implements CoreListener {
                                nodeDisconnect();
                        }
                };
+               List<Locale> availableLanguages = I18n.findAvailableLanguages();
+               for (final Locale locale: availableLanguages) {
+                       I18nAction languageAction = new I18nAction("general.language." + locale.getLanguage()) {
+
+                               @SuppressWarnings("synthetic-access")
+                               public void actionPerformed(ActionEvent e) {
+                                       changeLanguage(locale, this);
+                               }
+
+                       };
+                       if (I18n.getLocale().getLanguage().equals(locale.getLanguage())) {
+                               languageAction.setEnabled(false);
+                       }
+                       languageActions.add(languageAction);
+               }
+               helpAboutAction = new I18nAction("mainWindow.menu.help.item.about") {
+
+                       /**
+                        * {@inheritDoc}
+                        */
+                       @SuppressWarnings("synthetic-access")
+                       public void actionPerformed(ActionEvent actionEvent) {
+                               helpAbout();
+                       }
+               };
+               addProjectAction = new I18nAction("mainWindow.button.addProject") {
+
+                       /**
+                        * {@inheritDoc}
+                        */
+                       @SuppressWarnings("synthetic-access")
+                       public void actionPerformed(ActionEvent actionEvent) {
+                               addProject();
+                       }
+               };
+               cloneProjectAction = new I18nAction("mainWindow.button.cloneProject") {
+
+                       /**
+                        * {@inheritDoc}
+                        */
+                       @SuppressWarnings("synthetic-access")
+                       public void actionPerformed(ActionEvent actionEvent) {
+                               cloneProject();
+                       }
+               };
+               deleteProjectAction = new I18nAction("mainWindow.button.deleteProject") {
+
+                       /**
+                        * {@inheritDoc}
+                        */
+                       @SuppressWarnings("synthetic-access")
+                       public void actionPerformed(ActionEvent actionEvent) {
+                               deleteProject();
+                       }
+               };
        }
 
        /**
         * Initializes all child dialogs.
         */
        private void initDialogs() {
-               manageNodesDialog = new ManageNodesDialog(mainWindow);
+               manageNodesDialog = new ManageNodesDialog(this);
+               aboutDialog = new AboutDialog(this);
+               configurationDialog = new ConfigurationDialog(this);
+       }
+
+       //
+       // PRIVATE ACTIONS
+       //
+
+       /**
+        * Shows the configuration dialog.
+        */
+       private void configure() {
+               configurationDialog.setAdvancedMode(advancedMode);
+               configurationDialog.setAntialias(antialias);
+               configurationDialog.setControlFont(controlFont);
+               configurationDialog.setUserFont(userFont);
+               configurationDialog.setVisible(true);
+               if (!configurationDialog.wasCancelled()) {
+                       advancedMode = configurationDialog.isAdvancedMode();
+                       if (!advancedMode && (nodeList.size() > 1)) {
+                               JOptionPane.showMessageDialog(mainWindow, I18n.get("mainWindow.warning.multipleNodesNotAdvancedMode.message"), I18n.get("mainWindow.warning.multipleNodesNotAdvancedMode.title"), JOptionPane.WARNING_MESSAGE);
+                       }
+                       antialias = configurationDialog.isAntialias();
+                       controlFont = configurationDialog.getControlFont();
+                       userFont = configurationDialog.getUserFont();
+                       saveConfig();
+               }
+       }
+
+       /**
+        * Imports old jSite configuration.
+        */
+       private void importConfig() {
+               /* TODO */
+       }
+
+       /**
+        * Quits jSite.
+        */
+       private void quit() {
+               saveConfig();
+               System.exit(0);
        }
 
        /**
         * Pops up the “manage nodes” dialog.
         */
        private void manageNodes() {
-               manageNodesDialog.setNodeList(nodeList);
-               manageNodesDialog.setVisible(true);
-               nodeList = manageNodesDialog.getNodeList();
+               if (advancedMode) {
+                       manageNodesDialog.setNodeList(nodeList);
+                       manageNodesDialog.setVisible(true);
+                       nodeList = manageNodesDialog.getNodeList();
+               } else {
+                       if (nodeList.isEmpty()) {
+                               Node newNode = new Node();
+                               newNode.setName(I18n.get("general.defaultNode.name"));
+                               newNode.setHostname("localhost");
+                               newNode.setPort(9481);
+                               nodeList.add(newNode);
+                       }
+                       Node firstNode = nodeList.get(0);
+                       EditNodeDialog editNodeDialog = manageNodesDialog.getEditNodeDialog();
+                       editNodeDialog.setNodeName(firstNode.getName());
+                       editNodeDialog.setNodeHostname(firstNode.getHostname());
+                       editNodeDialog.setNodePort(firstNode.getPort());
+                       editNodeDialog.setVisible(true);
+                       if (!editNodeDialog.wasCancelled()) {
+                               firstNode.setName(editNodeDialog.getNodeName());
+                               firstNode.setHostname(editNodeDialog.getNodeHostname());
+                               firstNode.setPort(editNodeDialog.getNodePort());
+                               /* TODO - give to core. */
+                       }
+               }
        }
 
        /**
         * Connects to the node.
         */
        private void nodeConnect() {
-               core.connectToNode(null); // FIXME
+               /* TODO */
        }
 
        /**
         * Disconnects from the node.
         */
        private void nodeDisconnect() {
+               /* TODO */
+       }
+
+       /**
+        * Changes the language of the interface. This method also disables the
+        * action for the newly set language and enables all others.
+        *
+        * @param newLocale
+        *            The new language
+        * @param languageAction
+        *            The action that triggered the change
+        */
+       private void changeLanguage(Locale newLocale, I18nAction languageAction) {
+               for (I18nAction i18nAction: languageActions) {
+                       i18nAction.setEnabled(i18nAction != languageAction);
+               }
+               I18n.setLocale(newLocale);
+       }
+
+       /**
+        * Shows the “about” dialog.
+        */
+       private void helpAbout() {
+               aboutDialog.setVisible(true);
+       }
+
+       /**
+        * Adds a project.
+        */
+       private void addProject() {
+               Project project = new Project();
+               project.setName("New Project");
+               project.setDescription("");
+       }
+
+       /**
+        * Clones a project.
+        */
+       private void cloneProject() {
+               /* TODO */
+       }
+
+       /**
+        * Deletes a project.
+        */
+       private void deleteProject() {
+               /* TODO */
        }
 
        //
        // INTERFACE CoreListener
        //
 
+
+       /**
+        * {@inheritDoc}
+        */
+       public void loadingProjectsDone(String directory) {
+               mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.projectLoadingDone"));
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public void loadingProjectsFailed(String directory, Throwable throwable) {
+               JOptionPane.showMessageDialog(mainWindow, I18n.get("mainWindow.error.projectLoadingFailed.message", directory), I18n.get("mainWindow.error.projectLoadingFailed.title"), JOptionPane.ERROR_MESSAGE);
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public void savingProjectsDone(String directory) {
+               mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.projectSavingDone"));
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public void savingProjectsFailed(String directory, Throwable throwabled) {
+               /* TODO */
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public void loadingNodesDone(String directory) {
+               mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.loadingNodesDone"));
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public void loadingNodesFailed(String directory, Throwable throwable) {
+               /* TODO */
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public void savingNodesDone(String directory) {
+               mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.savingNodesDone"));
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public void savingNodesFailed(String directory, Throwable throwable) {
+               /* TODO */
+       }
+
        /**
         * {@inheritDoc}
         */
        public void coreLoaded() {
-               this.nodeList = core.getNodeList();
+               this.nodeList = core.getNodes();
                manageNodesDialog.setNodeList(nodeList);
                mainWindow.setVisible(true);
-               mainWindow.setStatusBarText("Core loaded.");
+               mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.coreLoaded"));
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public void coreStopped() {
+               mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.coreStopped"));
        }
 
        /**
         * {@inheritDoc}
         */
        public void nodeConnected(Node node) {
+               /* TODO */
        }
 
        /**
         * {@inheritDoc}
         */
        public void nodeConnecting(Node node) {
+               /* TODO */
        }
 
        /**
         * {@inheritDoc}
         */
        public void nodeDisconnected(Node node) {
+               /* TODO */
        }
 
 }