add node-is-still-connected dialog texts
[jSite2.git] / src / net / pterodactylus / jsite / gui / ManageNodesDialog.java
1 /*
2  * jSite2 - ManageNodeDialog.java -
3  * Copyright © 2008 David Roden
4  *
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.
9  *
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.
14  *
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.
18  */
19
20 package net.pterodactylus.jsite.gui;
21
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.Collection;
27 import java.util.Iterator;
28 import java.util.List;
29
30 import javax.swing.AbstractListModel;
31 import javax.swing.Action;
32 import javax.swing.BorderFactory;
33 import javax.swing.JButton;
34 import javax.swing.JDialog;
35 import javax.swing.JList;
36 import javax.swing.JOptionPane;
37 import javax.swing.JPanel;
38 import javax.swing.JScrollPane;
39 import javax.swing.border.EtchedBorder;
40 import javax.swing.event.ListSelectionEvent;
41 import javax.swing.event.ListSelectionListener;
42
43 import net.pterodactylus.jsite.core.Core;
44 import net.pterodactylus.jsite.core.Node;
45 import net.pterodactylus.jsite.i18n.I18n;
46 import net.pterodactylus.jsite.main.Version;
47 import net.pterodactylus.util.swing.SwingUtils;
48
49 /**
50  * Dialog that lets the user manage her nodes.
51  * 
52  * @author David ‘Bombe’ Roden <bombe@freenetproject.org>
53  * @version $Id$
54  */
55 public class ManageNodesDialog extends JDialog implements ListSelectionListener {
56
57         /** The core. */
58         private final Core core;
59
60         /** The original list of nodes. */
61         private List<Node> originalNodeList;
62
63         /** The “add node” action. */
64         private Action addNodeAction;
65
66         /** The “edit node” action. */
67         private Action editNodeAction;
68
69         /** The “delete node” action. */
70         private Action deleteNodeAction;
71
72         /** The “okay” action. */
73         private Action okayAction;
74
75         /** The “cancel” action. */
76         private Action cancelAction;
77
78         /** The “edit node” dialog. */
79         private EditNodeDialog editNodeDialog;
80
81         /** The node list. */
82         private JList nodeList;
83
84         /** The mode for the node list. */
85         private NodeListModel nodeListModel = new NodeListModel();
86
87         /**
88          * Creates a new node manager dialog.
89          * 
90          * @param swingInterface
91          *            The Swing interface
92          */
93         public ManageNodesDialog(SwingInterface swingInterface) {
94                 super(swingInterface.getMainWindow(), I18n.get("manageNodesDialog.title") + " – jSite " + Version.getVersion(), true);
95                 this.core = swingInterface.getCore();
96                 initActions();
97                 initComponents();
98                 initDialogs();
99                 pack();
100                 SwingUtils.center(this);
101         }
102
103         //
104         // ACCESSORS
105         //
106
107         /**
108          * Returns the list of nodes.
109          * 
110          * @return The list of nodes
111          */
112         public List<Node> getNodeList() {
113                 return originalNodeList;
114         }
115
116         /**
117          * Sets the list of nodes.
118          * 
119          * @param nodeList
120          *            The list of nodes
121          */
122         public void setNodeList(List<Node> nodeList) {
123                 originalNodeList = nodeList;
124                 nodeListModel.clear();
125                 for (Node node: nodeList) {
126                         nodeListModel.addNode(node);
127                 }
128         }
129
130         //
131         // PRIVATE METHODS
132         //
133
134         /**
135          * Initializes all actions.
136          */
137         private void initActions() {
138                 okayAction = new I18nAction("general.button.okay") {
139
140                         /**
141                          * {@inheritDoc}
142                          */
143                         @SuppressWarnings("synthetic-access")
144                         public void actionPerformed(ActionEvent e) {
145                                 confirm();
146                         }
147                 };
148                 cancelAction = new I18nAction("general.button.cancel") {
149
150                         /**
151                          * {@inheritDoc}
152                          */
153                         @SuppressWarnings("synthetic-access")
154                         public void actionPerformed(ActionEvent e) {
155                                 cancel();
156                         }
157                 };
158                 addNodeAction = new I18nAction("manageNodesDialog.button.addNode") {
159
160                         /**
161                          * {@inheritDoc}
162                          */
163                         @SuppressWarnings("synthetic-access")
164                         public void actionPerformed(ActionEvent e) {
165                                 addNode();
166                         }
167                 };
168                 editNodeAction = new I18nAction("manageNodesDialog.button.editNode", false) {
169
170                         /**
171                          * {@inheritDoc}
172                          */
173                         @SuppressWarnings("synthetic-access")
174                         public void actionPerformed(ActionEvent e) {
175                                 editNode();
176                         }
177                 };
178                 deleteNodeAction = new I18nAction("manageNodesDialog.button.deleteNode", false) {
179
180                         /**
181                          * {@inheritDoc}
182                          */
183                         @SuppressWarnings("synthetic-access")
184                         public void actionPerformed(ActionEvent e) {
185                                 deleteNodes();
186                         }
187                 };
188         }
189
190         /**
191          * Initializes all components.
192          */
193         private void initComponents() {
194                 JPanel rootPanel = new JPanel(new BorderLayout(12, 12));
195                 rootPanel.setBorder(BorderFactory.createEmptyBorder(12, 12, 12, 12));
196
197                 JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.TRAILING, 12, 12));
198                 rootPanel.add(buttonPanel, BorderLayout.PAGE_END);
199                 buttonPanel.setBorder(BorderFactory.createEmptyBorder(-12, -12, -12, -12));
200
201                 buttonPanel.add(new JButton(cancelAction));
202                 JButton okayButton = new JButton(okayAction);
203                 getRootPane().setDefaultButton(okayButton);
204                 buttonPanel.add(okayButton);
205
206                 JPanel contentPanel = new JPanel(new BorderLayout(12, 12));
207                 rootPanel.add(contentPanel, BorderLayout.CENTER);
208                 contentPanel.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED), BorderFactory.createEmptyBorder(12, 12, 12, 12)));
209
210                 JPanel listButtonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 12, 12));
211                 contentPanel.add(listButtonPanel, BorderLayout.PAGE_END);
212                 listButtonPanel.setBorder(BorderFactory.createEmptyBorder(-12, -12, -12, -12));
213                 listButtonPanel.add(new JButton(addNodeAction));
214                 listButtonPanel.add(new JButton(editNodeAction));
215                 listButtonPanel.add(new JButton(deleteNodeAction));
216
217                 nodeList = new JList(nodeListModel);
218                 nodeList.addListSelectionListener(this);
219                 contentPanel.add(new JScrollPane(nodeList), BorderLayout.CENTER);
220
221                 setContentPane(rootPanel);
222         }
223
224         /**
225          * Initializes all child dialogs.
226          */
227         private void initDialogs() {
228                 editNodeDialog = new EditNodeDialog(this);
229         }
230
231         //
232         // PRIVATE ACTIONS
233         //
234
235         /**
236          * Adds a new node via {@link #editNodeDialog}.
237          */
238         private void addNode() {
239                 editNodeDialog.setNodeName("New Node");
240                 editNodeDialog.setNodeHostname("localhost");
241                 editNodeDialog.setNodePort(9481);
242                 editNodeDialog.setNodeOnSameMachine(true);
243                 editNodeDialog.setVisible(true);
244                 if (!editNodeDialog.wasCancelled()) {
245                         Node newNode = new Node();
246                         newNode.setName(editNodeDialog.getNodeName());
247                         newNode.setHostname(editNodeDialog.getNodeHostname());
248                         newNode.setPort(editNodeDialog.getNodePort());
249                         nodeListModel.addNode(newNode);
250                 }
251         }
252
253         /**
254          * Edits a node via {@link #editNodeDialog}.
255          */
256         private void editNode() {
257                 Node selectedNode = (Node) nodeList.getSelectedValue();
258                 editNodeDialog.setNodeName(selectedNode.getName());
259                 editNodeDialog.setNodeHostname(selectedNode.getHostname());
260                 editNodeDialog.setNodePort(selectedNode.getPort());
261                 editNodeDialog.setNodeOnSameMachine(selectedNode.isSameMachine());
262                 editNodeDialog.setVisible(true);
263                 if (!editNodeDialog.wasCancelled()) {
264                         selectedNode.setName(editNodeDialog.getNodeName());
265                         selectedNode.setHostname(editNodeDialog.getNodeHostname());
266                         selectedNode.setPort(editNodeDialog.getNodePort());
267                         selectedNode.setSameMachine(editNodeDialog.isNodeOnSameMachine());
268                         nodeList.repaint();
269                 }
270         }
271
272         /**
273          * Deletes the selected node.
274          */
275         private void deleteNodes() {
276                 Object[] selectedNodes = nodeList.getSelectedValues();
277                 for (Object node: selectedNodes) {
278                         Node selectedNode = (Node) node;
279                         if (core.isNodeConnected(selectedNode)) {
280                                 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);
281                                 if (response == JOptionPane.CANCEL_OPTION) {
282                                         break;
283                                 } else if (response == JOptionPane.NO_OPTION) {
284                                         continue;
285                                 }
286                         }
287                         nodeListModel.removeNode(selectedNode);
288                 }
289                 nodeList.clearSelection();
290         }
291
292         /**
293          * Checks whether the list of nodes is not empty.
294          * 
295          * @return <code>true</code> if there is at least one node defined,
296          *         <code>false</code> otherwise
297          */
298         private boolean verifyNodesExist() {
299                 return nodeListModel.getSize() > 0;
300         }
301
302         /**
303          * This method is called when the “okay” button is pressed. The nodes from
304          * the list are read and the {@link #originalNodeList} member is set so that
305          * the calling code can use {@link #getNodeList()} to get the changed
306          * values.
307          */
308         private void confirm() {
309                 if (!verifyNodesExist()) {
310                         JOptionPane.showMessageDialog(this, I18n.get("manageNodesDialog.error.nodeListEmpty.message"), I18n.get("manageNodesDialog.error.nodeListEmpty.title"), JOptionPane.ERROR_MESSAGE);
311                         return;
312                 }
313                 originalNodeList.clear();
314                 for (Node node: nodeListModel) {
315                         originalNodeList.add(node);
316                 }
317                 setVisible(false);
318         }
319
320         /**
321          * Cancels the dialog.
322          */
323         private void cancel() {
324                 setVisible(false);
325         }
326
327         //
328         // INTERFACE ListSelectionListener
329         //
330
331         /**
332          * {@inheritDoc}
333          */
334         public void valueChanged(ListSelectionEvent listSelectionEvent) {
335                 JList list = (JList) listSelectionEvent.getSource();
336                 int selectCount = list.getSelectedIndices().length;
337                 editNodeAction.setEnabled(selectCount == 1);
338                 deleteNodeAction.setEnabled(selectCount >= 1);
339         }
340
341         /**
342          * List model for the {@link ManageNodesDialog#nodeList}. TODO
343          * 
344          * @author David ‘Bombe’ Roden &lt;bombe@freenetproject.org&gt;
345          * @version $Id$
346          */
347         private class NodeListModel extends AbstractListModel implements Iterable<Node> {
348
349                 /** The list of nodes. */
350                 @SuppressWarnings("hiding")
351                 private final List<Node> nodeList = new ArrayList<Node>();
352
353                 /**
354                  * Creates a new node list model.
355                  */
356                 public NodeListModel() {
357                 }
358
359                 /**
360                  * Adds the given node to the list model.
361                  * 
362                  * @see Collection#add(Object)
363                  * @param node
364                  *            The node to add
365                  */
366                 public void addNode(Node node) {
367                         nodeList.add(node);
368                         fireIntervalAdded(this, nodeList.size() - 1, nodeList.size() - 1);
369                 }
370
371                 /**
372                  * Removes the given node from the list model.
373                  * 
374                  * @see Collection#remove(Object)
375                  * @param node
376                  *            The node to remove
377                  */
378                 public void removeNode(Node node) {
379                         int nodeIndex = nodeList.indexOf(node);
380                         nodeList.remove(node);
381                         fireIntervalRemoved(this, nodeIndex, nodeIndex);
382                 }
383
384                 /**
385                  * Removes all nodes from the list model.
386                  * 
387                  * @see Collection#clear()
388                  */
389                 public void clear() {
390                         int nodeCount = nodeList.size();
391                         if (nodeCount > 0) {
392                                 nodeList.clear();
393                                 fireIntervalRemoved(this, 0, nodeCount - 1);
394                         }
395                 }
396
397                 /**
398                  * {@inheritDoc}
399                  */
400                 public Iterator<Node> iterator() {
401                         return nodeList.iterator();
402                 }
403
404                 /**
405                  * {@inheritDoc}
406                  */
407                 @SuppressWarnings("synthetic-access")
408                 public Object getElementAt(int index) {
409                         return nodeList.get(index);
410                 }
411
412                 /**
413                  * {@inheritDoc}
414                  */
415                 public int getSize() {
416                         return nodeList.size();
417                 }
418
419         }
420
421 }