From: David ‘Bombe’ Roden 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;ds=sidebyside;h=3b339f1be23515da7c254723cd17013adcb3dcdd;hp=2eb7b9b9251e39a4a17c06d3cdde9ca106fb6943;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 <bombe@freenetproject.org> + * @version $Id$ + */ +public class ManageNodesDialog extends JDialog implements ListSelectionListener { + + /** The current list of nodes. */ + private List nodes = new ArrayList(); + + /** 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 null if no default node has + * been set + */ + public Node getDefaultNode() { + return defaultNode; + } + + /** + * Sets the default node. + * + * @param defaultNode + * The default node, or null 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 getNodeList() { + List nodes = new ArrayList(); + 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 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 <bombe@freenetproject.org> + * @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 true if the wrapped node is the default node, + * false otherwise + */ + public boolean isDefaultNode() { + return defaultNode; + } + + /** + * Sets whether the wrapped node is the default node. + * + * @param defaultNode + * true if the wrapped node is the default + * node, false 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 <bombe@freenetproject.org> + * @version $Id$ + */ + private class NodeListModel extends AbstractListModel { + + /** The list of wrapped nodes. */ + @SuppressWarnings("hiding") + private List 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 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(); + } + + } + +}