import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
+import java.net.UnknownHostException;
import java.util.ArrayList;
-import java.util.Collections;
+import java.util.Collection;
+import java.util.Iterator;
import java.util.List;
+import java.util.logging.Logger;
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.JOptionPane;
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.Core;
import net.pterodactylus.jsite.core.Node;
import net.pterodactylus.jsite.i18n.I18n;
+import net.pterodactylus.jsite.i18n.I18nable;
+import net.pterodactylus.jsite.i18n.gui.I18nAction;
+import net.pterodactylus.jsite.i18n.gui.I18nLabel;
import net.pterodactylus.jsite.main.Version;
+import net.pterodactylus.util.logging.Logging;
import net.pterodactylus.util.swing.SwingUtils;
/**
* @author David ‘Bombe’ Roden <bombe@freenetproject.org>
* @version $Id$
*/
-public class ManageNodesDialog extends JDialog implements ListSelectionListener {
+public class ManageNodesDialog extends JDialog implements ListSelectionListener, I18nable {
- /** The current list of nodes. */
- private List<NodeWrapper> nodes = new ArrayList<NodeWrapper>();
+ /** The logger. */
+ @SuppressWarnings("unused")
+ private static final Logger logger = Logging.getLogger(ManageNodesDialog.class.getName());
- /** The current default node. */
- private Node defaultNode;
+ /** The core. */
+ private final Core core;
+
+ /** The original list of nodes. */
+ private List<Node> originalNodeList;
/** The “add node” action. */
- private Action addNodeAction;
+ private I18nAction addNodeAction;
/** The “edit node” action. */
- private Action editNodeAction;
+ private I18nAction editNodeAction;
/** The “delete node” action. */
- private Action deleteNodeAction;
-
- /** The “set default node” action. */
- private Action setDefaultNodeAction;
+ private I18nAction deleteNodeAction;
/** The “okay” action. */
- private Action okayAction;
+ private I18nAction okayAction;
/** The “cancel” action. */
- private Action cancelAction;
+ private I18nAction cancelAction;
/** The “edit node” dialog. */
private EditNodeDialog editNodeDialog;
+ /** The warning label. */
+ private I18nLabel immediatelyEffectiveLabel;
+
/** The node list. */
private JList nodeList;
/**
* Creates a new node manager dialog.
*
- * @param parentFrame
- * The parent frame of the dialog
+ * @param swingInterface
+ * The Swing interface
*/
- public ManageNodesDialog(JFrame parentFrame) {
- super(parentFrame, I18n.get("manageNodesDialog.title") + " – jSite " + Version.getVersion(), true);
+ public ManageNodesDialog(SwingInterface swingInterface) {
+ super(swingInterface.getMainWindow(), I18n.get("manageNodesDialog.title") + " – jSite " + Version.getVersion(), true);
+ this.core = swingInterface.getCore();
initActions();
initComponents();
initDialogs();
pack();
+ I18n.registerI18nable(this);
SwingUtils.center(this);
}
//
/**
- * 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.
+ * Expose the edit node dialog for the simple mode.
*
- * @param defaultNode
- * The default node, or <code>null</code> if no default node
- * has been set
+ * @return The edit node dialog
*/
- public void setDefaultNode(Node defaultNode) {
- this.defaultNode = defaultNode;
+ EditNodeDialog getEditNodeDialog() {
+ return editNodeDialog;
}
/**
* @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;
+ return originalNodeList;
}
/**
* Sets the list of nodes.
*
- * @param nodes
+ * @param nodeList
* The list of nodes
*/
- public void setNodeList(List<Node> nodes) {
- this.nodes.clear();
- for (Node node: nodes) {
- this.nodes.add(new NodeWrapper(node));
+ public void setNodeList(List<Node> nodeList) {
+ originalNodeList = new ArrayList<Node>(nodeList);
+ nodeListModel.clear();
+ for (Node node: nodeList) {
+ nodeListModel.addNode(node);
}
- nodeListModel.setNodeList(this.nodes);
}
//
*/
@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();
+ deleteNodes();
}
};
}
rootPanel.add(contentPanel, BorderLayout.CENTER);
contentPanel.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED), BorderFactory.createEmptyBorder(12, 12, 12, 12)));
+ JPanel warningPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 12, 12));
+ warningPanel.setBorder(BorderFactory.createEmptyBorder(-12, -12, -12, -12));
+ warningPanel.add(immediatelyEffectiveLabel = new I18nLabel("manageNodesDialog.label.immediatelyEffective"));
+ contentPanel.add(warningPanel, BorderLayout.PAGE_START);
+
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);
* Adds a new node via {@link #editNodeDialog}.
*/
private void addNode() {
- editNodeDialog.setNodeName("New Node");
+ editNodeDialog.setNodeName(I18n.get("general.newNode.name"));
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);
+ try {
+ if (!core.addNode(newNode)) {
+ JOptionPane.showMessageDialog(this, I18n.get("manageNodesDialog.error.nodeAlreadyKnown.message", newNode.getHostname(), newNode.getPort()), I18n.get("manageNodesDialog.error.nodeAlreadyKnown.title"), JOptionPane.ERROR_MESSAGE);
+ }
+ } catch (UnknownHostException e) {
+ /*
+ * normally this shouldn't throw because the node editor catches
+ * it.
+ */
+ JOptionPane.showMessageDialog(this, I18n.get("manageNodesDialog.error.nodeUnresolvable.message", newNode.getHostname()), I18n.get("manageNodesDialog.error.nodeUnresolvable.title"), JOptionPane.ERROR_MESSAGE);
}
- 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();
+ Node selectedNode = (Node) nodeList.getSelectedValue();
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);
+ private void deleteNodes() {
+ Object[] selectedNodes = nodeList.getSelectedValues();
+ for (Object node: selectedNodes) {
+ Node selectedNode = (Node) node;
+ if (core.isNodeConnected(selectedNode)) {
+ int response = JOptionPane.showConfirmDialog(this, I18n.get("manageNodesDialog.error.nodeConnected.message", selectedNode.getName()), I18n.get("manageNodesDialog.error.nodeConnected.title"), JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE);
+ if (response == JOptionPane.CANCEL_OPTION) {
+ break;
+ } else if (response == JOptionPane.NO_OPTION) {
+ continue;
+ }
+ }
+ nodeListModel.removeNode(selectedNode);
+ }
nodeList.clearSelection();
- nodeList.repaint();
}
/**
- * Sets the default node to the selected node.
+ * Checks whether the list of nodes is not empty.
+ *
+ * @return <code>true</code> if there is at least one node defined,
+ * <code>false</code> otherwise
*/
- private void setDefaultNode() {
- NodeWrapper selectedNode = (NodeWrapper) nodeList.getSelectedValue();
- for (NodeWrapper nodeWrapper: nodes) {
- nodeWrapper.setDefaultNode(nodeWrapper == selectedNode);
- }
- nodeList.repaint();
+ private boolean verifyNodesExist() {
+ return nodeListModel.getSize() > 0;
}
/**
* 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.
+ * the list are read and the {@link #originalNodeList} member is set so that
+ * the calling code can use {@link #getNodeList()} to get the changed
+ * values.
*/
private void confirm() {
+ if (!verifyNodesExist()) {
+ JOptionPane.showMessageDialog(this, I18n.get("manageNodesDialog.error.nodeListEmpty.message"), I18n.get("manageNodesDialog.error.nodeListEmpty.title"), JOptionPane.ERROR_MESSAGE);
+ return;
+ }
+ originalNodeList.clear();
+ for (Node node: nodeListModel) {
+ originalNodeList.add(node);
+ }
setVisible(false);
}
int selectCount = list.getSelectedIndices().length;
editNodeAction.setEnabled(selectCount == 1);
deleteNodeAction.setEnabled(selectCount >= 1);
- setDefaultNodeAction.setEnabled(selectCount == 1);
}
+ //
+ // INTERFACE I18nable
+ //
+
/**
- * 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}.
+ * {@inheritDoc}
+ */
+ public void updateI18n() {
+ okayAction.updateI18n();
+ cancelAction.updateI18n();
+ addNodeAction.updateI18n();
+ editNodeAction.updateI18n();
+ deleteNodeAction.updateI18n();
+ immediatelyEffectiveLabel.updateI18n();
+ setTitle(I18n.get("manageNodesDialog.title") + " – jSite " + Version.getVersion());
+ SwingUtils.repackCentered(this);
+ }
+
+ /**
+ * List model for the {@link ManageNodesDialog#nodeList}.
*
* @author David ‘Bombe’ Roden <bombe@freenetproject.org>
* @version $Id$
*/
- private static class NodeWrapper {
+ private class NodeListModel extends AbstractListModel implements Iterable<Node> {
- /** The wrapped node. */
- private final Node wrappedNode;
-
- /** The default node. */
- private boolean defaultNode;
+ /** The list of nodes. */
+ @SuppressWarnings("hiding")
+ private final List<Node> nodeList = new ArrayList<Node>();
/**
- * Creates a new node wrapper around the given node.
- *
- * @param wrappedNode
- * The node to wrap
+ * Creates a new node list model.
*/
- public NodeWrapper(Node wrappedNode) {
- this.wrappedNode = wrappedNode;
+ public NodeListModel() {
+ /* do nothing. */
}
/**
- * Returns the wrapped node.
+ * Adds the given node to the list model.
*
- * @return The wrapped node
+ * @see Collection#add(Object)
+ * @param node
+ * The node to add
*/
- public Node getWrappedNode() {
- return wrappedNode;
+ public void addNode(Node node) {
+ nodeList.add(node);
+ fireIntervalAdded(this, nodeList.size() - 1, nodeList.size() - 1);
}
/**
- * Returns whether the wrapped node is the default node.
+ * Removes the given node from the list model.
*
- * @return <code>true</code> if the wrapped node is the default node,
- * <code>false</code> otherwise
+ * @see Collection#remove(Object)
+ * @param node
+ * The node to remove
*/
- public boolean isDefaultNode() {
- return defaultNode;
+ public void removeNode(Node node) {
+ int nodeIndex = nodeList.indexOf(node);
+ nodeList.remove(node);
+ fireIntervalRemoved(this, nodeIndex, nodeIndex);
}
/**
- * Sets whether the wrapped node is the default node.
+ * Removes all nodes from the list model.
*
- * @param defaultNode
- * <code>true</code> if the wrapped node is the default
- * node, <code>false</code> otherwise
+ * @see Collection#clear()
*/
- public void setDefaultNode(boolean defaultNode) {
- this.defaultNode = defaultNode;
+ public void clear() {
+ int nodeCount = nodeList.size();
+ if (nodeCount > 0) {
+ nodeList.clear();
+ fireIntervalRemoved(this, 0, nodeCount - 1);
+ }
}
/**
* {@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<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);
+ public Iterator<Node> iterator() {
+ return nodeList.iterator();
}
/**
*/
@SuppressWarnings("synthetic-access")
public Object getElementAt(int index) {
- NodeWrapper currentNodeWrapper = nodeList.get(index);
- return currentNodeWrapper;
+ return nodeList.get(index);
}
/**