From: David ‘Bombe’ Roden <bombe@pterodactylus.net>
Date: Fri, 4 Apr 2008 21:27:45 +0000 (+0000)
Subject: dialog to manage nodes
X-Git-Url: https://git.pterodactylus.net/?a=commitdiff_plain;h=3b339f1be23515da7c254723cd17013adcb3dcdd;p=jSite2.git

dialog to manage nodes

git-svn-id: http://trooper/svn/projects/jSite/trunk@587 c3eda9e8-030b-0410-8277-bc7414b0a119
---

diff --git a/src/net/pterodactylus/jsite/gui/ManageNodesDialog.java b/src/net/pterodactylus/jsite/gui/ManageNodesDialog.java
new file mode 100644
index 0000000..ceb9904
--- /dev/null
+++ b/src/net/pterodactylus/jsite/gui/ManageNodesDialog.java
@@ -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();
+		}
+
+	}
+
+}