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