X-Git-Url: https://git.pterodactylus.net/?a=blobdiff_plain;f=src%2Fnet%2Fpterodactylus%2Fjsite%2Fgui%2FSwingInterface.java;h=3b8971c6c23b2ac138763682e05bf8e35d5c1496;hb=751f589bf2b601b1a34bf0f075a6c6bb2e1e1f66;hp=65e1eddd99ca9681e29e95c31c357813e3bab698;hpb=9eec7156e8223a363d6f30392f66dbc8a4aa41cd;p=jSite2.git diff --git a/src/net/pterodactylus/jsite/gui/SwingInterface.java b/src/net/pterodactylus/jsite/gui/SwingInterface.java index 65e1edd..3b8971c 100644 --- a/src/net/pterodactylus/jsite/gui/SwingInterface.java +++ b/src/net/pterodactylus/jsite/gui/SwingInterface.java @@ -20,12 +20,16 @@ package net.pterodactylus.jsite.gui; import java.awt.event.ActionEvent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; +import java.net.UnknownHostException; import java.util.ArrayList; import java.util.Collections; +import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Locale; @@ -37,19 +41,17 @@ import java.util.logging.Level; import java.util.logging.LogRecord; import java.util.logging.Logger; -import javax.swing.AbstractAction; -import javax.swing.Action; import javax.swing.JOptionPane; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; import net.pterodactylus.jsite.core.Core; import net.pterodactylus.jsite.core.CoreListener; +import net.pterodactylus.jsite.core.JSiteException; import net.pterodactylus.jsite.core.Node; -import net.pterodactylus.jsite.core.Project; -import net.pterodactylus.jsite.core.Request; import net.pterodactylus.jsite.i18n.I18n; import net.pterodactylus.jsite.i18n.gui.I18nAction; +import net.pterodactylus.jsite.project.Project; import net.pterodactylus.util.image.IconLoader; import net.pterodactylus.util.io.Closer; import net.pterodactylus.util.logging.Logging; @@ -59,9 +61,8 @@ import net.pterodactylus.util.logging.LoggingListener; * The Swing user interface. * * @author David ‘Bombe’ Roden <bombe@freenetproject.org> - * @version $Id$ */ -public class SwingInterface implements CoreListener, LoggingListener { +public class SwingInterface implements CoreListener, LoggingListener, PropertyChangeListener { /** The logger. */ private static final Logger logger = Logging.getLogger(SwingInterface.class.getName()); @@ -90,35 +91,20 @@ public class SwingInterface implements CoreListener, LoggingListener { /** The “quit” action. */ private I18nAction quitAction; - /** The “manage nodes” action. */ - private I18nAction manageNodesAction; - - /** The “connect to node” (simple mode) action. */ - private I18nAction nodeConnectAction; - - /** The “disconnect from node” (simple mode) action. */ - private I18nAction nodeDisconnectAction; + /** The “add node” action. */ + private I18nAction addNodeAction; /** All node menu items. */ - private List nodeConnectActions = Collections.synchronizedList(new ArrayList()); - - /** Mapping from nodes to node connect actions. */ - private Map nodeNodeConnectActions = Collections.synchronizedMap(new HashMap()); - - /** Mapping from node connect actions to nodes. */ - private Map nodeConnectActionNodes = Collections.synchronizedMap(new HashMap()); + private Map nodeConnectActions = Collections.synchronizedMap(new HashMap()); /** All node disconnect actions. */ - private List nodeDisconnectActions = Collections.synchronizedList(new ArrayList()); - - /** Mapping from nodes to node disconnect actions. */ - private Map nodeNodeDisconnectActions = Collections.synchronizedMap(new HashMap()); + private Map nodeDisconnectActions = Collections.synchronizedMap(new HashMap()); - /** Mapping from node disconnect actions to nodes. */ - private Map nodeDisconnectActionNodes = Collections.synchronizedMap(new HashMap()); + /** All node edit actions. */ + private Map nodeEditActions = Collections.synchronizedMap(new HashMap()); - /** The node manager dialog. */ - private ManageNodesDialog manageNodesDialog; + /** All node removal actions. */ + private Map nodeDeleteActions = Collections.synchronizedMap(new HashMap()); /** All lanugage menu items. */ private List languageActions = new ArrayList(); @@ -141,6 +127,9 @@ public class SwingInterface implements CoreListener, LoggingListener { /** The configuration dialog. */ private ConfigurationDialog configurationDialog; + /** The node editor dialog. */ + private EditNodeDialog editNodeDialog; + /** The list of all defined nodes. */ private List nodeList = Collections.synchronizedList(new ArrayList()); @@ -163,6 +152,18 @@ public class SwingInterface implements CoreListener, LoggingListener { /** The class name of the look and feel. */ private String lookAndFeel; + /** X coordinate of the main window. */ + private int mainWindowX = -1; + + /** Y coordinate of the main window. */ + private int mainWindowY = -1; + + /** Width of the main window. */ + private int mainWindowWidth = -1; + + /** Height of the main window. */ + private int mainWindowHeight = -1; + /** * Creates a new swing interface. * @@ -202,6 +203,10 @@ public class SwingInterface implements CoreListener, LoggingListener { initDialogs(); mainWindow = new MainWindow(this); mainWindow.setAdvancedMode(advancedMode); + if ((mainWindowX != -1) && (mainWindowY != -1) && (mainWindowWidth != -1) && (mainWindowHeight != -1)) { + mainWindow.setLocation(mainWindowX, mainWindowY); + mainWindow.setSize(mainWindowWidth, mainWindowHeight); + } logWindow = new LogWindow(); } @@ -265,48 +270,56 @@ public class SwingInterface implements CoreListener, LoggingListener { } /** - * Returns the “manage nodes” action. + * Returns the “add node” action. * - * @return The “manage nodes” action + * @return The “add node” action */ - I18nAction getManageNodesAction() { - return manageNodesAction; + I18nAction getAddNodeAction() { + return addNodeAction; } /** - * Returns the “connect to node” action. + * Returns the “connect to node” action for the given node. * + * @param node + * The node go get the “connect” action for * @return The “connect to node” action */ - I18nAction getNodeConnectAction() { - return nodeConnectAction; + I18nAction getNodeConnectAction(Node node) { + return nodeConnectActions.get(node); } /** - * Returns all “connect node” actions. + * Returns the “disconnect from node” action for the given node. * - * @return All “connect node” actions + * @param node + * The node go get the “disconnect” action for + * @return The “disconnect from node” action */ - List getNodeConnectActions() { - return nodeConnectActions; + I18nAction getNodeDisconnectAction(Node node) { + return nodeDisconnectActions.get(node); } /** - * Returns the “disconnect from node” action. + * Returns the “edit node” action for the given node. * - * @return The “disconnect from node” action + * @param node + * The node to edit + * @return The “edit node” action */ - I18nAction getNodeDisconnectAction() { - return nodeDisconnectAction; + I18nAction getNodeEditAction(Node node) { + return nodeEditActions.get(node); } /** - * Returns all “disconnect node” actions. + * Returns the “delete node” action for the given node. * - * @return All “disconnect node” action + * @param node + * The node to delete + * @return The “delete node” action */ - List getNodeDisconnectActions() { - return nodeDisconnectActions; + I18nAction getNodeDeleteAction(Node node) { + return nodeDeleteActions.get(node); } /** @@ -354,6 +367,24 @@ public class SwingInterface implements CoreListener, LoggingListener { return deleteProjectAction; } + /** + * Returns all currently configured nodes. + * + * @return All configured nodes + */ + List getNodes() { + return nodeList; + } + + /** + * Returns the thread pool used for off-thread processes. + * + * @return The thread pool + */ + Executor getThreadPool() { + return threadPool; + } + // // ACTIONS // @@ -406,6 +437,18 @@ public class SwingInterface implements CoreListener, LoggingListener { if (configProperties.containsKey("language")) { I18n.setLocale(new Locale(configProperties.getProperty("language"))); } + if (configProperties.containsKey("mainWindowX")) { + mainWindowX = Integer.valueOf(configProperties.getProperty("mainWindowX")); + } + if (configProperties.containsKey("mainWindowY")) { + mainWindowY = Integer.valueOf(configProperties.getProperty("mainWindowY")); + } + if (configProperties.containsKey("mainWindowWidth")) { + mainWindowWidth = Integer.valueOf(configProperties.getProperty("mainWindowWidth")); + } + if (configProperties.containsKey("mainWindowHeight")) { + mainWindowHeight = Integer.valueOf(configProperties.getProperty("mainWindowHeight")); + } } /** @@ -437,6 +480,10 @@ public class SwingInterface implements CoreListener, LoggingListener { configProperties.setProperty("lookAndFeel", lookAndFeel); } configProperties.setProperty("language", I18n.getLocale().getLanguage()); + configProperties.setProperty("mainWindowX", String.valueOf(mainWindowX)); + configProperties.setProperty("mainWindowY", String.valueOf(mainWindowY)); + configProperties.setProperty("mainWindowWidth", String.valueOf(mainWindowWidth)); + configProperties.setProperty("mainWindowHeight", String.valueOf(mainWindowHeight)); FileOutputStream configOutputStream = null; try { configOutputStream = new FileOutputStream(configFile); @@ -482,43 +529,6 @@ public class SwingInterface implements CoreListener, LoggingListener { quit(); } }; - manageNodesAction = new I18nAction("mainWindow.menu.node.item.manageNodes") { - - /** - * {@inheritDoc} - */ - @SuppressWarnings("synthetic-access") - public void actionPerformed(ActionEvent actionEvent) { - manageNodes(); - } - }; - nodeConnectAction = new I18nAction("mainWindow.menu.node.item.connect", false) { - - @SuppressWarnings("synthetic-access") - public void actionPerformed(ActionEvent actionEvent) { - List nodes = core.getNodes(); - if (nodes.isEmpty()) { - return; - } - nodeConnect(nodes.get(0)); - } - - }; - nodeDisconnectAction = new I18nAction("mainWindow.menu.node.item.disconnect", false) { - - /** - * {@inheritDoc} - */ - @SuppressWarnings("synthetic-access") - public void actionPerformed(ActionEvent e) { - List nodes = core.getNodes(); - if (nodes.isEmpty()) { - return; - } - nodeDisconnect(nodes.get(0)); - } - }; - rebuildNodeActions(core.getNodes()); List availableLanguages = I18n.findAvailableLanguages(); for (final Locale locale: availableLanguages) { I18nAction languageAction = new I18nAction("general.language." + locale.getLanguage()) { @@ -534,6 +544,16 @@ public class SwingInterface implements CoreListener, LoggingListener { } languageActions.add(languageAction); } + addNodeAction = new I18nAction("mainWindow.menu.node.item.addNode", IconLoader.loadIcon("/node-new.png")) { + + /** + * {@inheritDoc} + */ + @SuppressWarnings("synthetic-access") + public void actionPerformed(ActionEvent actionEvent) { + addNode(); + } + }; helpAboutAction = new I18nAction("mainWindow.menu.help.item.about") { /** @@ -580,9 +600,9 @@ public class SwingInterface implements CoreListener, LoggingListener { * Initializes all child dialogs. */ private void initDialogs() { - manageNodesDialog = new ManageNodesDialog(this); aboutDialog = new AboutDialog(this); configurationDialog = new ConfigurationDialog(this); + editNodeDialog = new EditNodeDialog(mainWindow); } // @@ -626,87 +646,63 @@ public class SwingInterface implements CoreListener, LoggingListener { private void quit() { /* TODO - ask */ core.stop(); + mainWindowX = mainWindow.getX(); + mainWindowY = mainWindow.getY(); + mainWindowWidth = mainWindow.getWidth(); + mainWindowHeight = mainWindow.getHeight(); saveConfig(); System.exit(0); } /** - * Rebuilds all node connect and disconnect actions. + * Adds a node. + */ + private void addNode() { + editNodeDialog.setNodeName(I18n.get(nodeList.isEmpty() ? "general.defaultNode.name" : "general.newNode.name")); + editNodeDialog.setNodeHostname("localhost"); + editNodeDialog.setNodePort(9481); + editNodeDialog.setVisible(true); + if (!editNodeDialog.wasCancelled()) { + Node newNode = new Node(); + newNode.setName(editNodeDialog.getNodeName()); + newNode.setHostname(editNodeDialog.getNodeHostname()); + newNode.setPort(editNodeDialog.getNodePort()); + try { + core.addNode(newNode); + } catch (UnknownHostException e) { + JOptionPane.showMessageDialog(mainWindow, I18n.get("mainWindow.error.hostnameUnresolvable.message"), I18n.get("mainWindow.error.hostnameUnresolvable.title"), JOptionPane.ERROR_MESSAGE); + } + } + } + + /** + * Edits the given node. * - * @param nodes - * The list of nodes - */ - private void rebuildNodeActions(List nodes) { - logger.fine("rebuilding node actions…"); - nodeConnectActions.clear(); - nodeNodeConnectActions.clear(); - nodeConnectActionNodes.clear(); - nodeDisconnectActions.clear(); - nodeNodeDisconnectActions.clear(); - nodeDisconnectActionNodes.clear(); - for (Node node: nodes) { - logger.finer("adding node “" + node + "” to menu"); - Action nodeConnectAction = new AbstractAction(node.getName()) { - - /** - * {@inheritDoc} - */ - @SuppressWarnings("synthetic-access") - public void actionPerformed(ActionEvent e) { - Node node = nodeConnectActionNodes.get(this); - nodeConnect(node); - } - }; - nodeConnectActions.add(nodeConnectAction); - nodeConnectActionNodes.put(nodeConnectAction, node); - nodeNodeConnectActions.put(node, nodeConnectAction); - Action nodeDisconnectAction = new AbstractAction(node.getName()) { - - /** - * {@inheritDoc} - */ - @SuppressWarnings("synthetic-access") - public void actionPerformed(ActionEvent e) { - Node node = nodeDisconnectActionNodes.get(this); - nodeDisconnect(node); - } - }; -// nodeDisconnectActions.add(nodeDisconnectAction); - nodeDisconnectActionNodes.put(nodeDisconnectAction, node); - nodeNodeDisconnectActions.put(node, nodeDisconnectAction); + * @param node + * The node to edit + */ + private void editNode(Node node) { + editNodeDialog.setNodeName(node.getName()); + editNodeDialog.setNodeHostname(node.getHostname()); + editNodeDialog.setNodePort(node.getPort()); + editNodeDialog.setVisible(true); + if (!editNodeDialog.wasCancelled()) { + node.setName(editNodeDialog.getNodeName()); + node.setHostname(editNodeDialog.getNodeHostname()); + node.setPort(editNodeDialog.getNodePort()); } } /** - * Pops up the “manage nodes” dialog. + * Deletes the given node. + * + * @param node + * The node to delete */ - private void manageNodes() { - if (advancedMode) { - manageNodesDialog.setNodeList(nodeList); - manageNodesDialog.setVisible(true); - nodeList = manageNodesDialog.getNodeList(); - rebuildNodeActions(nodeList); - mainWindow.refreshNodeMenuItems(); - } 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. */ - } + private void deleteNode(Node node) { + int option = JOptionPane.showConfirmDialog(mainWindow, I18n.get("mainWindow.question.deleteNode.message", node.getName()), I18n.get("mainWindow.question.deleteNode.title"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE); + if (option == JOptionPane.OK_OPTION) { + core.removeNode(node); } } @@ -768,9 +764,18 @@ public class SwingInterface implements CoreListener, LoggingListener { * Adds a project. */ private void addProject() { - Project project = new Project(); - project.setName("New Project"); - project.setDescription(""); + try { + Project project = core.createProject(); + project.setName(I18n.get("general.newProject.name")); + project.setDescription(I18n.get("general.newProject.description", new Date())); + mainWindow.addProject(project, true); + } catch (JSiteException nne1) { + /* TODO - add i18n */ + JOptionPane.showMessageDialog(mainWindow, I18n.get(""), I18n.get(""), JOptionPane.ERROR_MESSAGE); + } catch (IOException e) { + /* TODO - add i18n */ + JOptionPane.showMessageDialog(mainWindow, I18n.get(""), I18n.get(""), JOptionPane.ERROR_MESSAGE); + } } /** @@ -796,6 +801,9 @@ public class SwingInterface implements CoreListener, LoggingListener { */ public void loadingProjectsDone(String directory) { mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.projectLoadingDone")); + for (Project project: core.getProjects()) { + mainWindow.addProject(project, false); + } } /** @@ -865,12 +873,53 @@ public class SwingInterface implements CoreListener, LoggingListener { /** * {@inheritDoc} */ - public void nodeAdded(Node node) { + public void nodeAdded(final Node node) { logger.log(Level.INFO, "node added: " + node); nodeList.add(node); - manageNodesDialog.setNodeList(nodeList); - rebuildNodeActions(nodeList); - mainWindow.refreshNodeMenuItems(); + node.addPropertyChangeListener(this); + logger.log(Level.FINE, "nodeList.size(): " + nodeList.size()); + nodeConnectActions.put(node, new I18nAction("mainWindow.menu.node.item.connect") { + + /** + * {@inheritDoc} + */ + @SuppressWarnings("synthetic-access") + public void actionPerformed(ActionEvent e) { + nodeConnect(node); + } + }); + nodeDisconnectActions.put(node, new I18nAction("mainWindow.menu.node.item.disconnect") { + + /** + * {@inheritDoc} + */ + @SuppressWarnings("synthetic-access") + public void actionPerformed(ActionEvent e) { + nodeDisconnect(node); + } + }); + nodeDisconnectActions.get(node).setEnabled(false); + nodeEditActions.put(node, new I18nAction("mainWindow.menu.node.item.edit") { + + /** + * {@inheritDoc} + */ + @SuppressWarnings("synthetic-access") + public void actionPerformed(ActionEvent actionEvent) { + editNode(node); + } + }); + nodeDeleteActions.put(node, new I18nAction("mainWindow.menu.node.item.remove") { + + /** + * {@inheritDoc} + */ + @SuppressWarnings("synthetic-access") + public void actionPerformed(ActionEvent actionEvent) { + deleteNode(node); + } + }); + mainWindow.addNode(node); } /** @@ -879,55 +928,86 @@ public class SwingInterface implements CoreListener, LoggingListener { public void nodeRemoved(Node node) { logger.log(Level.INFO, "node removed: " + node); nodeList.remove(node); - rebuildNodeActions(nodeList); - mainWindow.refreshNodeMenuItems(); + node.removePropertyChangeListener(this); + nodeConnectActions.remove(node); + nodeDisconnectActions.remove(node); + nodeEditActions.remove(node); + nodeDeleteActions.remove(node); + mainWindow.removeNode(node); } /** * {@inheritDoc} */ public void nodeConnecting(Node node) { - Action nodeConnectAction = nodeNodeConnectActions.get(node); - nodeConnectActions.remove(nodeConnectAction); + nodeConnectActions.get(node).setEnabled(false); + nodeEditActions.get(node).setEnabled(false); + nodeDeleteActions.get(node).setEnabled(false); mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.connectingToNode", node.getName(), node.getHostname(), node.getPort())); - mainWindow.refreshNodeMenuItems(); } /** * {@inheritDoc} */ public void nodeConnected(Node node) { - Action nodeDisconnectAction = nodeNodeDisconnectActions.get(node); - nodeDisconnectActions.add(nodeDisconnectAction); + nodeDisconnectActions.get(node).setEnabled(true); mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.connectedToNode", node.getName(), node.getHostname(), node.getPort())); - mainWindow.refreshNodeMenuItems(); + mainWindow.setOnline(node); + } + + /** + * {@inheritDoc} + */ + public void nodeConnectionFailed(Node node, Throwable cause) { + nodeConnectActions.get(node).setEnabled(true); + nodeEditActions.get(node).setEnabled(true); + nodeDeleteActions.get(node).setEnabled(true); + mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.connectionToNodeFailed", node.getName(), node.getHostname(), node.getPort(), (cause != null) ? cause.getMessage() : "no reason given")); + mainWindow.setError(node); + JOptionPane.showMessageDialog(mainWindow, I18n.get("mainWindow.error.nodeConnectionFailed.message", node.getName(), node.getHostname(), node.getPort(), (cause != null) ? cause.getMessage() : "no reason given"), I18n.get("mainWindow.error.nodeConnectionFailed.title"), JOptionPane.ERROR_MESSAGE); } /** * {@inheritDoc} */ public void nodeDisconnected(Node node, Throwable throwable) { - Action nodeConnectAction = nodeNodeConnectActions.get(node); - nodeConnectActions.add(nodeConnectAction); - Action nodeDisconnectAction = nodeNodeDisconnectActions.get(node); - nodeDisconnectActions.remove(nodeDisconnectAction); + nodeDisconnectActions.get(node).setEnabled(false); + nodeConnectActions.get(node).setEnabled(true); + nodeEditActions.get(node).setEnabled(true); + nodeDeleteActions.get(node).setEnabled(true); mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.disconnectedFromNode", node.getName(), node.getHostname(), node.getPort())); - mainWindow.refreshNodeMenuItems(); + mainWindow.setOffline(node); } /** - * {@inheritDoc} + * @see net.pterodactylus.jsite.core.CoreListener#projectInsertStarted(net.pterodactylus.jsite.project.Project) */ - public void requestAdded(Node node, Request request) { - logger.log(Level.INFO, "request added to node: " + request + ", " + node); - /* TODO - implement */ + public void projectInsertStarted(Project project) { + mainWindow.projectInsertStarted(project); } /** - * {@inheritDoc} + * @see net.pterodactylus.jsite.core.CoreListener#projectInsertProgressed(net.pterodactylus.jsite.project.Project, + * int, int, int, int, int, boolean) + */ + public void projectInsertProgressed(Project project, int totalBlocks, int requiredBlocks, int successfulBlocks, int failedBlocks, int fatallyFailedBlocks, boolean finalizedTotal) { + mainWindow.projectInsertProgressed(project, totalBlocks, requiredBlocks, successfulBlocks, failedBlocks, fatallyFailedBlocks, finalizedTotal); + } + + /** + * @see net.pterodactylus.jsite.core.CoreListener#projectInsertGeneratedURI(net.pterodactylus.jsite.project.Project, + * java.lang.String) + */ + public void projectInsertGeneratedURI(Project project, String uri) { + mainWindow.projectInsertGeneratedURI(project); + } + + /** + * @see net.pterodactylus.jsite.core.CoreListener#projectInsertFinished(net.pterodactylus.jsite.project.Project, + * boolean) */ - public void requestProgressed(Request request, int totalBlocks, int requiredBlocks, int successfulBlocks, int failedBlocks, int fatallyFailedBlocks, boolean finalizedTotal) { - /* TODO - update table model */ + public void projectInsertFinished(Project project, boolean success) { + mainWindow.projectInsertFinished(project, success); } // @@ -941,4 +1021,15 @@ public class SwingInterface implements CoreListener, LoggingListener { logWindow.logged(logRecord); } + // + // INTERFACE PropertyChangeListener + // + + /** + * {@inheritDoc} + */ + public void propertyChange(PropertyChangeEvent propertyChangeEvent) { + /* do not react to anything (yet). */ + } + }