2 * jSite2 - ManageNodeDialog.java -
3 * Copyright © 2008 David Roden
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 package net.pterodactylus.jsite.gui;
22 import java.awt.BorderLayout;
23 import java.awt.FlowLayout;
24 import java.awt.event.ActionEvent;
25 import java.net.UnknownHostException;
26 import java.util.ArrayList;
27 import java.util.Collection;
28 import java.util.Iterator;
29 import java.util.List;
30 import java.util.logging.Logger;
32 import javax.swing.AbstractListModel;
33 import javax.swing.BorderFactory;
34 import javax.swing.JButton;
35 import javax.swing.JDialog;
36 import javax.swing.JList;
37 import javax.swing.JOptionPane;
38 import javax.swing.JPanel;
39 import javax.swing.JScrollPane;
40 import javax.swing.border.EtchedBorder;
41 import javax.swing.event.ListSelectionEvent;
42 import javax.swing.event.ListSelectionListener;
44 import net.pterodactylus.jsite.core.Core;
45 import net.pterodactylus.jsite.core.Node;
46 import net.pterodactylus.jsite.i18n.I18n;
47 import net.pterodactylus.jsite.i18n.I18nable;
48 import net.pterodactylus.jsite.i18n.gui.I18nAction;
49 import net.pterodactylus.jsite.i18n.gui.I18nLabel;
50 import net.pterodactylus.jsite.main.Version;
51 import net.pterodactylus.util.logging.Logging;
52 import net.pterodactylus.util.swing.SwingUtils;
55 * Dialog that lets the user manage her nodes.
57 * @author David ‘Bombe’ Roden <bombe@freenetproject.org>
60 public class ManageNodesDialog extends JDialog implements ListSelectionListener, I18nable {
63 @SuppressWarnings("unused")
64 private static final Logger logger = Logging.getLogger(ManageNodesDialog.class.getName());
67 private final Core core;
69 /** The original list of nodes. */
70 private List<Node> originalNodeList;
72 /** The “add node” action. */
73 private I18nAction addNodeAction;
75 /** The “edit node” action. */
76 private I18nAction editNodeAction;
78 /** The “delete node” action. */
79 private I18nAction deleteNodeAction;
81 /** The “okay” action. */
82 private I18nAction okayAction;
84 /** The “cancel” action. */
85 private I18nAction cancelAction;
87 /** The “edit node” dialog. */
88 private EditNodeDialog editNodeDialog;
90 /** The warning label. */
91 private I18nLabel immediatelyEffectiveLabel;
94 private JList nodeList;
96 /** The mode for the node list. */
97 private NodeListModel nodeListModel = new NodeListModel();
100 * Creates a new node manager dialog.
102 * @param swingInterface
103 * The Swing interface
105 public ManageNodesDialog(SwingInterface swingInterface) {
106 super(swingInterface.getMainWindow(), I18n.get("manageNodesDialog.title") + " – jSite " + Version.getVersion(), true);
107 this.core = swingInterface.getCore();
112 I18n.registerI18nable(this);
113 SwingUtils.center(this);
121 * Expose the edit node dialog for the simple mode.
123 * @return The edit node dialog
125 EditNodeDialog getEditNodeDialog() {
126 return editNodeDialog;
130 * Returns the list of nodes.
132 * @return The list of nodes
134 public List<Node> getNodeList() {
135 return originalNodeList;
139 * Sets the list of nodes.
144 public void setNodeList(List<Node> nodeList) {
145 originalNodeList = new ArrayList<Node>(nodeList);
146 nodeListModel.clear();
147 for (Node node: nodeList) {
148 nodeListModel.addNode(node);
157 * Initializes all actions.
159 private void initActions() {
160 okayAction = new I18nAction("general.button.okay") {
165 @SuppressWarnings("synthetic-access")
166 public void actionPerformed(ActionEvent e) {
170 cancelAction = new I18nAction("general.button.cancel") {
175 @SuppressWarnings("synthetic-access")
176 public void actionPerformed(ActionEvent e) {
180 addNodeAction = new I18nAction("manageNodesDialog.button.addNode") {
185 @SuppressWarnings("synthetic-access")
186 public void actionPerformed(ActionEvent e) {
190 editNodeAction = new I18nAction("manageNodesDialog.button.editNode", false) {
195 @SuppressWarnings("synthetic-access")
196 public void actionPerformed(ActionEvent e) {
200 deleteNodeAction = new I18nAction("manageNodesDialog.button.deleteNode", false) {
205 @SuppressWarnings("synthetic-access")
206 public void actionPerformed(ActionEvent e) {
213 * Initializes all components.
215 private void initComponents() {
216 JPanel rootPanel = new JPanel(new BorderLayout(12, 12));
217 rootPanel.setBorder(BorderFactory.createEmptyBorder(12, 12, 12, 12));
219 JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.TRAILING, 12, 12));
220 rootPanel.add(buttonPanel, BorderLayout.PAGE_END);
221 buttonPanel.setBorder(BorderFactory.createEmptyBorder(-12, -12, -12, -12));
223 buttonPanel.add(new JButton(cancelAction));
224 JButton okayButton = new JButton(okayAction);
225 getRootPane().setDefaultButton(okayButton);
226 buttonPanel.add(okayButton);
228 JPanel contentPanel = new JPanel(new BorderLayout(12, 12));
229 rootPanel.add(contentPanel, BorderLayout.CENTER);
230 contentPanel.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED), BorderFactory.createEmptyBorder(12, 12, 12, 12)));
232 JPanel warningPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 12, 12));
233 warningPanel.setBorder(BorderFactory.createEmptyBorder(-12, -12, -12, -12));
234 warningPanel.add(immediatelyEffectiveLabel = new I18nLabel("manageNodesDialog.label.immediatelyEffective"));
235 contentPanel.add(warningPanel, BorderLayout.PAGE_START);
237 JPanel listButtonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 12, 12));
238 contentPanel.add(listButtonPanel, BorderLayout.PAGE_END);
239 listButtonPanel.setBorder(BorderFactory.createEmptyBorder(-12, -12, -12, -12));
240 listButtonPanel.add(new JButton(addNodeAction));
241 listButtonPanel.add(new JButton(editNodeAction));
242 listButtonPanel.add(new JButton(deleteNodeAction));
244 nodeList = new JList(nodeListModel);
245 nodeList.addListSelectionListener(this);
246 contentPanel.add(new JScrollPane(nodeList), BorderLayout.CENTER);
248 setContentPane(rootPanel);
252 * Initializes all child dialogs.
254 private void initDialogs() {
255 editNodeDialog = new EditNodeDialog(this);
263 * Adds a new node via {@link #editNodeDialog}.
265 private void addNode() {
266 editNodeDialog.setNodeName(I18n.get("general.newNode.name"));
267 editNodeDialog.setNodeHostname("localhost");
268 editNodeDialog.setNodePort(9481);
269 editNodeDialog.setVisible(true);
270 if (!editNodeDialog.wasCancelled()) {
271 Node newNode = new Node();
272 newNode.setName(editNodeDialog.getNodeName());
273 newNode.setHostname(editNodeDialog.getNodeHostname());
274 newNode.setPort(editNodeDialog.getNodePort());
276 if (!core.addNode(newNode)) {
277 JOptionPane.showMessageDialog(this, I18n.get("manageNodesDialog.error.nodeAlreadyKnown.message", newNode.getHostname(), newNode.getPort()), I18n.get("manageNodesDialog.error.nodeAlreadyKnown.title"), JOptionPane.ERROR_MESSAGE);
279 } catch (UnknownHostException e) {
281 * normally this shouldn't throw because the node editor catches
284 JOptionPane.showMessageDialog(this, I18n.get("manageNodesDialog.error.nodeUnresolvable.message", newNode.getHostname()), I18n.get("manageNodesDialog.error.nodeUnresolvable.title"), JOptionPane.ERROR_MESSAGE);
290 * Edits a node via {@link #editNodeDialog}.
292 private void editNode() {
293 Node selectedNode = (Node) nodeList.getSelectedValue();
294 editNodeDialog.setNodeName(selectedNode.getName());
295 editNodeDialog.setNodeHostname(selectedNode.getHostname());
296 editNodeDialog.setNodePort(selectedNode.getPort());
297 editNodeDialog.setVisible(true);
298 if (!editNodeDialog.wasCancelled()) {
299 selectedNode.setName(editNodeDialog.getNodeName());
300 selectedNode.setHostname(editNodeDialog.getNodeHostname());
301 selectedNode.setPort(editNodeDialog.getNodePort());
307 * Deletes the selected node.
309 private void deleteNodes() {
310 Object[] selectedNodes = nodeList.getSelectedValues();
311 for (Object node: selectedNodes) {
312 Node selectedNode = (Node) node;
313 if (core.isNodeConnected(selectedNode)) {
314 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);
315 if (response == JOptionPane.CANCEL_OPTION) {
317 } else if (response == JOptionPane.NO_OPTION) {
321 nodeListModel.removeNode(selectedNode);
323 nodeList.clearSelection();
327 * Checks whether the list of nodes is not empty.
329 * @return <code>true</code> if there is at least one node defined,
330 * <code>false</code> otherwise
332 private boolean verifyNodesExist() {
333 return nodeListModel.getSize() > 0;
337 * This method is called when the “okay” button is pressed. The nodes from
338 * the list are read and the {@link #originalNodeList} member is set so that
339 * the calling code can use {@link #getNodeList()} to get the changed
342 private void confirm() {
343 if (!verifyNodesExist()) {
344 JOptionPane.showMessageDialog(this, I18n.get("manageNodesDialog.error.nodeListEmpty.message"), I18n.get("manageNodesDialog.error.nodeListEmpty.title"), JOptionPane.ERROR_MESSAGE);
347 originalNodeList.clear();
348 for (Node node: nodeListModel) {
349 originalNodeList.add(node);
355 * Cancels the dialog.
357 private void cancel() {
362 // INTERFACE ListSelectionListener
368 public void valueChanged(ListSelectionEvent listSelectionEvent) {
369 JList list = (JList) listSelectionEvent.getSource();
370 int selectCount = list.getSelectedIndices().length;
371 editNodeAction.setEnabled(selectCount == 1);
372 deleteNodeAction.setEnabled(selectCount >= 1);
376 // INTERFACE I18nable
382 public void updateI18n() {
383 okayAction.updateI18n();
384 cancelAction.updateI18n();
385 addNodeAction.updateI18n();
386 editNodeAction.updateI18n();
387 deleteNodeAction.updateI18n();
388 immediatelyEffectiveLabel.updateI18n();
389 setTitle(I18n.get("manageNodesDialog.title") + " – jSite " + Version.getVersion());
390 SwingUtils.repackCentered(this);
394 * List model for the {@link ManageNodesDialog#nodeList}.
396 * @author David ‘Bombe’ Roden <bombe@freenetproject.org>
399 private class NodeListModel extends AbstractListModel implements Iterable<Node> {
401 /** The list of nodes. */
402 @SuppressWarnings("hiding")
403 private final List<Node> nodeList = new ArrayList<Node>();
406 * Creates a new node list model.
408 public NodeListModel() {
413 * Adds the given node to the list model.
415 * @see Collection#add(Object)
419 public void addNode(Node node) {
421 fireIntervalAdded(this, nodeList.size() - 1, nodeList.size() - 1);
425 * Removes the given node from the list model.
427 * @see Collection#remove(Object)
431 public void removeNode(Node node) {
432 int nodeIndex = nodeList.indexOf(node);
433 nodeList.remove(node);
434 fireIntervalRemoved(this, nodeIndex, nodeIndex);
438 * Removes all nodes from the list model.
440 * @see Collection#clear()
442 public void clear() {
443 int nodeCount = nodeList.size();
446 fireIntervalRemoved(this, 0, nodeCount - 1);
453 public Iterator<Node> iterator() {
454 return nodeList.iterator();
460 @SuppressWarnings("synthetic-access")
461 public Object getElementAt(int index) {
462 return nodeList.get(index);
468 public int getSize() {
469 return nodeList.size();