dialog to manage nodes
authorDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Fri, 4 Apr 2008 21:27:45 +0000 (21:27 +0000)
committerDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Fri, 4 Apr 2008 21:27:45 +0000 (21:27 +0000)
git-svn-id: http://trooper/svn/projects/jSite/trunk@587 c3eda9e8-030b-0410-8277-bc7414b0a119

src/net/pterodactylus/jsite/gui/ManageNodesDialog.java [new file with mode: 0644]

diff --git a/src/net/pterodactylus/jsite/gui/ManageNodesDialog.java b/src/net/pterodactylus/jsite/gui/ManageNodesDialog.java
new file mode 100644 (file)
index 0000000..ceb9904
--- /dev/null
@@ -0,0 +1,482 @@
+/*
+ * jSite2 - ManageNodeDialog.java -
+ * Copyright © 2008 David Roden
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+package net.pterodactylus.jsite.gui;
+
+import java.awt.BorderLayout;
+import java.awt.FlowLayout;
+import java.awt.event.ActionEvent;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import javax.swing.AbstractListModel;
+import javax.swing.Action;
+import javax.swing.BorderFactory;
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JFrame;
+import javax.swing.JList;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.ListCellRenderer;
+import javax.swing.border.EtchedBorder;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+
+import net.pterodactylus.jsite.core.Node;
+import net.pterodactylus.jsite.i18n.I18n;
+import net.pterodactylus.jsite.main.Version;
+import net.pterodactylus.util.swing.SwingUtils;
+
+/**
+ * Dialog that lets the user manage her nodes.
+ * 
+ * @author David ‘Bombe’ Roden &lt;bombe@freenetproject.org&gt;
+ * @version $Id$
+ */
+public class ManageNodesDialog extends JDialog implements ListSelectionListener {
+
+       /** The current list of nodes. */
+       private List<NodeWrapper> nodes = new ArrayList<NodeWrapper>();
+
+       /** The current default node. */
+       private Node defaultNode;
+
+       /** The “add node” action. */
+       private Action addNodeAction;
+
+       /** The “edit node” action. */
+       private Action editNodeAction;
+
+       /** The “delete node” action. */
+       private Action deleteNodeAction;
+
+       /** The “set default node” action. */
+       private Action setDefaultNodeAction;
+
+       /** The “okay” action. */
+       private Action okayAction;
+
+       /** The “cancel” action. */
+       private Action cancelAction;
+
+       /** The “edit node” dialog. */
+       private EditNodeDialog editNodeDialog;
+
+       /** The node list. */
+       private JList nodeList;
+
+       /** The mode for the node list. */
+       private NodeListModel nodeListModel = new NodeListModel();
+
+       /**
+        * Creates a new node manager dialog.
+        * 
+        * @param parentFrame
+        *            The parent frame of the dialog
+        */
+       public ManageNodesDialog(JFrame parentFrame) {
+               super(parentFrame, I18n.get("manageNodesDialog.title") + " – jSite " + Version.getVersion(), true);
+               initActions();
+               initComponents();
+               initDialogs();
+               pack();
+               SwingUtils.center(this);
+       }
+
+       //
+       // ACCESSORS
+       //
+
+       /**
+        * Returns the default node.
+        * 
+        * @return The default node, or <code>null</code> if no default node has
+        *         been set
+        */
+       public Node getDefaultNode() {
+               return defaultNode;
+       }
+
+       /**
+        * Sets the default node.
+        * 
+        * @param defaultNode
+        *            The default node, or <code>null</code> if no default node
+        *            has been set
+        */
+       public void setDefaultNode(Node defaultNode) {
+               this.defaultNode = defaultNode;
+       }
+
+       /**
+        * Returns the list of nodes.
+        * 
+        * @return The list of nodes
+        */
+       public List<Node> getNodeList() {
+               List<Node> nodes = new ArrayList<Node>();
+               for (NodeWrapper nodeWrapper: this.nodes) {
+                       nodes.add(nodeWrapper.getWrappedNode());
+               }
+               return nodes;
+       }
+
+       /**
+        * Sets the list of nodes.
+        * 
+        * @param nodes
+        *            The list of nodes
+        */
+       public void setNodeList(List<Node> nodes) {
+               this.nodes.clear();
+               for (Node node: nodes) {
+                       this.nodes.add(new NodeWrapper(node));
+               }
+               nodeListModel.setNodeList(this.nodes);
+       }
+
+       //
+       // PRIVATE METHODS
+       //
+
+       /**
+        * Initializes all actions.
+        */
+       private void initActions() {
+               okayAction = new I18nAction("general.button.okay") {
+
+                       /**
+                        * {@inheritDoc}
+                        */
+                       @SuppressWarnings("synthetic-access")
+                       public void actionPerformed(ActionEvent e) {
+                               confirm();
+                       }
+               };
+               cancelAction = new I18nAction("general.button.cancel") {
+
+                       /**
+                        * {@inheritDoc}
+                        */
+                       @SuppressWarnings("synthetic-access")
+                       public void actionPerformed(ActionEvent e) {
+                               cancel();
+                       }
+               };
+               addNodeAction = new I18nAction("manageNodesDialog.button.addNode") {
+
+                       /**
+                        * {@inheritDoc}
+                        */
+                       @SuppressWarnings("synthetic-access")
+                       public void actionPerformed(ActionEvent e) {
+                               addNode();
+                       }
+               };
+               editNodeAction = new I18nAction("manageNodesDialog.button.editNode", false) {
+
+                       /**
+                        * {@inheritDoc}
+                        */
+                       @SuppressWarnings("synthetic-access")
+                       public void actionPerformed(ActionEvent e) {
+                               editNode();
+                       }
+               };
+               deleteNodeAction = new I18nAction("manageNodesDialog.button.deleteNode", false) {
+
+                       /**
+                        * {@inheritDoc}
+                        */
+                       @SuppressWarnings("synthetic-access")
+                       public void actionPerformed(ActionEvent e) {
+                               deleteNode();
+                       }
+               };
+               setDefaultNodeAction = new I18nAction("manageNodesDialog.button.setDefaultNode", false) {
+
+                       /**
+                        * {@inheritDoc}
+                        */
+                       @SuppressWarnings("synthetic-access")
+                       public void actionPerformed(ActionEvent e) {
+                               setDefaultNode();
+                       }
+               };
+       }
+
+       /**
+        * Initializes all components.
+        */
+       private void initComponents() {
+               JPanel rootPanel = new JPanel(new BorderLayout(12, 12));
+               rootPanel.setBorder(BorderFactory.createEmptyBorder(12, 12, 12, 12));
+
+               JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.TRAILING, 12, 12));
+               rootPanel.add(buttonPanel, BorderLayout.PAGE_END);
+               buttonPanel.setBorder(BorderFactory.createEmptyBorder(-12, -12, -12, -12));
+
+               buttonPanel.add(new JButton(cancelAction));
+               JButton okayButton = new JButton(okayAction);
+               getRootPane().setDefaultButton(okayButton);
+               buttonPanel.add(okayButton);
+
+               JPanel contentPanel = new JPanel(new BorderLayout(12, 12));
+               rootPanel.add(contentPanel, BorderLayout.CENTER);
+               contentPanel.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED), BorderFactory.createEmptyBorder(12, 12, 12, 12)));
+
+               JPanel listButtonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 12, 12));
+               contentPanel.add(listButtonPanel, BorderLayout.PAGE_END);
+               listButtonPanel.setBorder(BorderFactory.createEmptyBorder(-12, -12, -12, -12));
+               listButtonPanel.add(new JButton(addNodeAction));
+               listButtonPanel.add(new JButton(editNodeAction));
+               listButtonPanel.add(new JButton(deleteNodeAction));
+               listButtonPanel.add(new JButton(setDefaultNodeAction));
+
+               nodeList = new JList(nodeListModel);
+               nodeList.addListSelectionListener(this);
+               contentPanel.add(new JScrollPane(nodeList), BorderLayout.CENTER);
+
+               setContentPane(rootPanel);
+       }
+
+       /**
+        * Initializes all child dialogs.
+        */
+       private void initDialogs() {
+               editNodeDialog = new EditNodeDialog(this);
+       }
+
+       //
+       // PRIVATE ACTIONS
+       //
+
+       /**
+        * Adds a new node via {@link #editNodeDialog}.
+        */
+       private void addNode() {
+               editNodeDialog.setNodeName("New Node");
+               editNodeDialog.setNodeHostname("localhost");
+               editNodeDialog.setNodePort(9481);
+               editNodeDialog.setNodeOnSameMachine(true);
+               editNodeDialog.setVisible(true);
+               if (!editNodeDialog.wasCancelled()) {
+                       Node newNode = new Node();
+                       newNode.setName(editNodeDialog.getNodeName());
+                       newNode.setHostname(editNodeDialog.getNodeHostname());
+                       newNode.setPort(editNodeDialog.getNodePort());
+                       NodeWrapper newNodeWrapper = new NodeWrapper(newNode);
+                       if (nodes.isEmpty()) {
+                               defaultNode = newNode;
+                               newNodeWrapper.setDefaultNode(true);
+                       }
+                       nodes.add(new NodeWrapper(newNode));
+                       nodeListModel.setNodeList(nodes);
+               }
+       }
+
+       /**
+        * Edits a node via {@link #editNodeDialog}.
+        */
+       private void editNode() {
+               NodeWrapper selectedNodeWrapper = (NodeWrapper) nodeList.getSelectedValue();
+               Node selectedNode = selectedNodeWrapper.getWrappedNode();
+               editNodeDialog.setNodeName(selectedNode.getName());
+               editNodeDialog.setNodeHostname(selectedNode.getHostname());
+               editNodeDialog.setNodePort(selectedNode.getPort());
+               editNodeDialog.setNodeOnSameMachine(selectedNode.isSameMachine());
+               editNodeDialog.setVisible(true);
+               if (!editNodeDialog.wasCancelled()) {
+                       selectedNode.setName(editNodeDialog.getNodeName());
+                       selectedNode.setHostname(editNodeDialog.getNodeHostname());
+                       selectedNode.setPort(editNodeDialog.getNodePort());
+                       selectedNode.setSameMachine(editNodeDialog.isNodeOnSameMachine());
+                       nodeList.repaint();
+               }
+       }
+
+       /**
+        * Deletes the selected node.
+        */
+       private void deleteNode() {
+               NodeWrapper selectedNode = (NodeWrapper) nodeList.getSelectedValue();
+               nodes.remove(selectedNode);
+               nodeList.clearSelection();
+               nodeList.repaint();
+       }
+
+       /**
+        * Sets the default node to the selected node.
+        */
+       private void setDefaultNode() {
+               NodeWrapper selectedNode = (NodeWrapper) nodeList.getSelectedValue();
+               for (NodeWrapper nodeWrapper: nodes) {
+                       nodeWrapper.setDefaultNode(nodeWrapper == selectedNode);
+               }
+               nodeList.repaint();
+       }
+
+       /**
+        * This method is called when the “okay” button is pressed. The nodes from
+        * the list are read and the {@link #nodes} and {@link #defaultNode} members
+        * are set so that the calling code can use {@link #getNodeList()} and
+        * {@link #getDefaultNode()} to get the changed values.
+        */
+       private void confirm() {
+               setVisible(false);
+       }
+
+       /**
+        * Cancels the dialog.
+        */
+       private void cancel() {
+               setVisible(false);
+       }
+
+       //
+       // INTERFACE ListSelectionListener
+       //
+
+       /**
+        * {@inheritDoc}
+        */
+       public void valueChanged(ListSelectionEvent listSelectionEvent) {
+               JList list = (JList) listSelectionEvent.getSource();
+               int selectCount = list.getSelectedIndices().length;
+               editNodeAction.setEnabled(selectCount == 1);
+               deleteNodeAction.setEnabled(selectCount >= 1);
+               setDefaultNodeAction.setEnabled(selectCount == 1);
+       }
+
+       /**
+        * Wrapper around a {@link Node} to store whether a node is the default
+        * node. This frees us from having to write a {@link ListCellRenderer} for
+        * {@link ManageNodesDialog#nodeList}.
+        * 
+        * @author David ‘Bombe’ Roden &lt;bombe@freenetproject.org&gt;
+        * @version $Id$
+        */
+       private static class NodeWrapper {
+
+               /** The wrapped node. */
+               private final Node wrappedNode;
+
+               /** The default node. */
+               private boolean defaultNode;
+
+               /**
+                * Creates a new node wrapper around the given node.
+                * 
+                * @param wrappedNode
+                *            The node to wrap
+                */
+               public NodeWrapper(Node wrappedNode) {
+                       this.wrappedNode = wrappedNode;
+               }
+
+               /**
+                * Returns the wrapped node.
+                * 
+                * @return The wrapped node
+                */
+               public Node getWrappedNode() {
+                       return wrappedNode;
+               }
+
+               /**
+                * Returns whether the wrapped node is the default node.
+                * 
+                * @return <code>true</code> if the wrapped node is the default node,
+                *         <code>false</code> otherwise
+                */
+               public boolean isDefaultNode() {
+                       return defaultNode;
+               }
+
+               /**
+                * Sets whether the wrapped node is the default node.
+                * 
+                * @param defaultNode
+                *            <code>true</code> if the wrapped node is the default
+                *            node, <code>false</code> otherwise
+                */
+               public void setDefaultNode(boolean defaultNode) {
+                       this.defaultNode = defaultNode;
+               }
+
+               /**
+                * {@inheritDoc}
+                */
+               @Override
+               public String toString() {
+                       return wrappedNode.toString() + (defaultNode ? " (default)" : "");
+               }
+
+       }
+
+       /**
+        * List model for the {@link ManageNodesDialog#nodeList}. TODO
+        * 
+        * @author David ‘Bombe’ Roden &lt;bombe@freenetproject.org&gt;
+        * @version $Id$
+        */
+       private class NodeListModel extends AbstractListModel {
+
+               /** The list of wrapped nodes. */
+               @SuppressWarnings("hiding")
+               private List<NodeWrapper> nodeList = Collections.emptyList();
+
+               /**
+                * Creates a new node list model.
+                */
+               public NodeListModel() {
+               }
+
+               /**
+                * Sets the new node list.
+                * 
+                * @param nodeList
+                *            The list of nodes to display
+                */
+               public void setNodeList(List<NodeWrapper> nodeList) {
+                       this.nodeList = nodeList;
+                       fireContentsChanged(this, 0, nodeList.size() - 1);
+               }
+
+               /**
+                * {@inheritDoc}
+                */
+               @SuppressWarnings("synthetic-access")
+               public Object getElementAt(int index) {
+                       NodeWrapper currentNodeWrapper = nodeList.get(index);
+                       return currentNodeWrapper;
+               }
+
+               /**
+                * {@inheritDoc}
+                */
+               public int getSize() {
+                       return nodeList.size();
+               }
+
+       }
+
+}