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.util.ArrayList;
26 import java.util.Collections;
27 import java.util.List;
29 import javax.swing.AbstractListModel;
30 import javax.swing.Action;
31 import javax.swing.BorderFactory;
32 import javax.swing.JButton;
33 import javax.swing.JDialog;
34 import javax.swing.JFrame;
35 import javax.swing.JList;
36 import javax.swing.JPanel;
37 import javax.swing.JScrollPane;
38 import javax.swing.ListCellRenderer;
39 import javax.swing.border.EtchedBorder;
40 import javax.swing.event.ListSelectionEvent;
41 import javax.swing.event.ListSelectionListener;
43 import net.pterodactylus.jsite.core.Node;
44 import net.pterodactylus.jsite.i18n.I18n;
45 import net.pterodactylus.jsite.main.Version;
46 import net.pterodactylus.util.swing.SwingUtils;
49 * Dialog that lets the user manage her nodes.
51 * @author David ‘Bombe’ Roden <bombe@freenetproject.org>
54 public class ManageNodesDialog extends JDialog implements ListSelectionListener {
56 /** The original list of nodes. */
57 private List<Node> originalNodeList;
59 /** The current list of wrapped nodes. */
60 private List<NodeWrapper> wrappedNodeList = new ArrayList<NodeWrapper>();
62 /** The current default node. */
63 private Node defaultNode;
65 /** The “add node” action. */
66 private Action addNodeAction;
68 /** The “edit node” action. */
69 private Action editNodeAction;
71 /** The “delete node” action. */
72 private Action deleteNodeAction;
74 /** The “set default node” action. */
75 private Action setDefaultNodeAction;
77 /** The “okay” action. */
78 private Action okayAction;
80 /** The “cancel” action. */
81 private Action cancelAction;
83 /** The “edit node” dialog. */
84 private EditNodeDialog editNodeDialog;
87 private JList nodeList;
89 /** The mode for the node list. */
90 private NodeListModel nodeListModel = new NodeListModel();
93 * Creates a new node manager dialog.
96 * The parent frame of the dialog
98 public ManageNodesDialog(JFrame parentFrame) {
99 super(parentFrame, I18n.get("manageNodesDialog.title") + " – jSite " + Version.getVersion(), true);
104 SwingUtils.center(this);
112 * Returns the default node.
114 * @return The default node, or <code>null</code> if no default node has
117 public Node getDefaultNode() {
122 * Sets the default node.
125 * The default node, or <code>null</code> if no default node
128 public void setDefaultNode(Node defaultNode) {
129 this.defaultNode = defaultNode;
133 * Returns the list of nodes.
135 * @return The list of nodes
137 public List<Node> getNodeList() {
138 return originalNodeList;
142 * Sets the list of nodes.
147 public void setNodeList(List<Node> nodeList) {
148 originalNodeList = nodeList;
149 wrappedNodeList.clear();
150 for (Node node: nodeList) {
151 wrappedNodeList.add(new NodeWrapper(node));
153 nodeListModel.setNodeList(wrappedNodeList);
161 * Initializes all actions.
163 private void initActions() {
164 okayAction = new I18nAction("general.button.okay") {
169 @SuppressWarnings("synthetic-access")
170 public void actionPerformed(ActionEvent e) {
174 cancelAction = new I18nAction("general.button.cancel") {
179 @SuppressWarnings("synthetic-access")
180 public void actionPerformed(ActionEvent e) {
184 addNodeAction = new I18nAction("manageNodesDialog.button.addNode") {
189 @SuppressWarnings("synthetic-access")
190 public void actionPerformed(ActionEvent e) {
194 editNodeAction = new I18nAction("manageNodesDialog.button.editNode", false) {
199 @SuppressWarnings("synthetic-access")
200 public void actionPerformed(ActionEvent e) {
204 deleteNodeAction = new I18nAction("manageNodesDialog.button.deleteNode", false) {
209 @SuppressWarnings("synthetic-access")
210 public void actionPerformed(ActionEvent e) {
214 setDefaultNodeAction = new I18nAction("manageNodesDialog.button.setDefaultNode", false) {
219 @SuppressWarnings("synthetic-access")
220 public void actionPerformed(ActionEvent e) {
227 * Initializes all components.
229 private void initComponents() {
230 JPanel rootPanel = new JPanel(new BorderLayout(12, 12));
231 rootPanel.setBorder(BorderFactory.createEmptyBorder(12, 12, 12, 12));
233 JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.TRAILING, 12, 12));
234 rootPanel.add(buttonPanel, BorderLayout.PAGE_END);
235 buttonPanel.setBorder(BorderFactory.createEmptyBorder(-12, -12, -12, -12));
237 buttonPanel.add(new JButton(cancelAction));
238 JButton okayButton = new JButton(okayAction);
239 getRootPane().setDefaultButton(okayButton);
240 buttonPanel.add(okayButton);
242 JPanel contentPanel = new JPanel(new BorderLayout(12, 12));
243 rootPanel.add(contentPanel, BorderLayout.CENTER);
244 contentPanel.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED), BorderFactory.createEmptyBorder(12, 12, 12, 12)));
246 JPanel listButtonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 12, 12));
247 contentPanel.add(listButtonPanel, BorderLayout.PAGE_END);
248 listButtonPanel.setBorder(BorderFactory.createEmptyBorder(-12, -12, -12, -12));
249 listButtonPanel.add(new JButton(addNodeAction));
250 listButtonPanel.add(new JButton(editNodeAction));
251 listButtonPanel.add(new JButton(deleteNodeAction));
252 listButtonPanel.add(new JButton(setDefaultNodeAction));
254 nodeList = new JList(nodeListModel);
255 nodeList.addListSelectionListener(this);
256 contentPanel.add(new JScrollPane(nodeList), BorderLayout.CENTER);
258 setContentPane(rootPanel);
262 * Initializes all child dialogs.
264 private void initDialogs() {
265 editNodeDialog = new EditNodeDialog(this);
273 * Adds a new node via {@link #editNodeDialog}.
275 private void addNode() {
276 editNodeDialog.setNodeName("New Node");
277 editNodeDialog.setNodeHostname("localhost");
278 editNodeDialog.setNodePort(9481);
279 editNodeDialog.setNodeOnSameMachine(true);
280 editNodeDialog.setVisible(true);
281 if (!editNodeDialog.wasCancelled()) {
282 Node newNode = new Node();
283 newNode.setName(editNodeDialog.getNodeName());
284 newNode.setHostname(editNodeDialog.getNodeHostname());
285 newNode.setPort(editNodeDialog.getNodePort());
286 NodeWrapper newNodeWrapper = new NodeWrapper(newNode);
287 if (wrappedNodeList.isEmpty()) {
288 defaultNode = newNode;
289 newNodeWrapper.setDefaultNode(true);
291 wrappedNodeList.add(new NodeWrapper(newNode));
292 nodeListModel.setNodeList(wrappedNodeList);
297 * Edits a node via {@link #editNodeDialog}.
299 private void editNode() {
300 NodeWrapper selectedNodeWrapper = (NodeWrapper) nodeList.getSelectedValue();
301 Node selectedNode = selectedNodeWrapper.getWrappedNode();
302 editNodeDialog.setNodeName(selectedNode.getName());
303 editNodeDialog.setNodeHostname(selectedNode.getHostname());
304 editNodeDialog.setNodePort(selectedNode.getPort());
305 editNodeDialog.setNodeOnSameMachine(selectedNode.isSameMachine());
306 editNodeDialog.setVisible(true);
307 if (!editNodeDialog.wasCancelled()) {
308 selectedNode.setName(editNodeDialog.getNodeName());
309 selectedNode.setHostname(editNodeDialog.getNodeHostname());
310 selectedNode.setPort(editNodeDialog.getNodePort());
311 selectedNode.setSameMachine(editNodeDialog.isNodeOnSameMachine());
317 * Deletes the selected node.
319 private void deleteNode() {
320 NodeWrapper selectedNode = (NodeWrapper) nodeList.getSelectedValue();
321 wrappedNodeList.remove(selectedNode);
322 nodeList.clearSelection();
327 * Sets the default node to the selected node.
329 private void setDefaultNode() {
330 NodeWrapper selectedNode = (NodeWrapper) nodeList.getSelectedValue();
331 for (NodeWrapper nodeWrapper: wrappedNodeList) {
332 nodeWrapper.setDefaultNode(nodeWrapper == selectedNode);
338 * This method is called when the “okay” button is pressed. The nodes from
339 * the list are read and the {@link #wrappedNodeList} and
340 * {@link #defaultNode} members are set so that the calling code can use
341 * {@link #getNodeList()} and {@link #getDefaultNode()} to get the changed
344 private void confirm() {
345 originalNodeList.clear();
346 for (NodeWrapper nodeWrapper: wrappedNodeList) {
347 originalNodeList.add(nodeWrapper.getWrappedNode());
348 if (nodeWrapper.isDefaultNode()) {
349 defaultNode = nodeWrapper.getWrappedNode();
356 * Cancels the dialog.
358 private void cancel() {
363 // INTERFACE ListSelectionListener
369 public void valueChanged(ListSelectionEvent listSelectionEvent) {
370 JList list = (JList) listSelectionEvent.getSource();
371 int selectCount = list.getSelectedIndices().length;
372 editNodeAction.setEnabled(selectCount == 1);
373 deleteNodeAction.setEnabled(selectCount >= 1);
374 setDefaultNodeAction.setEnabled(selectCount == 1);
378 * Wrapper around a {@link Node} to store whether a node is the default
379 * node. This frees us from having to write a {@link ListCellRenderer} for
380 * {@link ManageNodesDialog#nodeList}.
382 * @author David ‘Bombe’ Roden <bombe@freenetproject.org>
385 private static class NodeWrapper {
387 /** The wrapped node. */
388 private final Node wrappedNode;
390 /** The default node. */
391 private boolean defaultNode;
394 * Creates a new node wrapper around the given node.
399 public NodeWrapper(Node wrappedNode) {
400 this.wrappedNode = wrappedNode;
404 * Returns the wrapped node.
406 * @return The wrapped node
408 public Node getWrappedNode() {
413 * Returns whether the wrapped node is the default node.
415 * @return <code>true</code> if the wrapped node is the default node,
416 * <code>false</code> otherwise
418 public boolean isDefaultNode() {
423 * Sets whether the wrapped node is the default node.
426 * <code>true</code> if the wrapped node is the default
427 * node, <code>false</code> otherwise
429 public void setDefaultNode(boolean defaultNode) {
430 this.defaultNode = defaultNode;
437 public String toString() {
438 return wrappedNode.toString() + (defaultNode ? " (default)" : "");
444 * List model for the {@link ManageNodesDialog#nodeList}. TODO
446 * @author David ‘Bombe’ Roden <bombe@freenetproject.org>
449 private class NodeListModel extends AbstractListModel {
451 /** The list of wrapped nodes. */
452 @SuppressWarnings("hiding")
453 private List<NodeWrapper> nodeList = Collections.emptyList();
456 * Creates a new node list model.
458 public NodeListModel() {
462 * Sets the new node list.
465 * The list of nodes to display
467 public void setNodeList(List<NodeWrapper> nodeList) {
468 this.nodeList = nodeList;
469 fireContentsChanged(this, 0, nodeList.size() - 1);
475 @SuppressWarnings("synthetic-access")
476 public Object getElementAt(int index) {
477 NodeWrapper currentNodeWrapper = nodeList.get(index);
478 return currentNodeWrapper;
484 public int getSize() {
485 return nodeList.size();