2dd1031ad1ed95db6c480de47ab3dd71e663e9e9
[jSite2.git] / src / net / pterodactylus / jsite / gui / ProjectPanel.java
1 /*
2  * jSite2 - ProjectPanel.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.Component;
24 import java.awt.FlowLayout;
25 import java.awt.GridBagConstraints;
26 import java.awt.GridBagLayout;
27 import java.awt.Insets;
28 import java.awt.event.ActionEvent;
29 import java.util.logging.Level;
30 import java.util.logging.Logger;
31
32 import javax.swing.AbstractAction;
33 import javax.swing.Action;
34 import javax.swing.BorderFactory;
35 import javax.swing.DefaultComboBoxModel;
36 import javax.swing.DefaultListCellRenderer;
37 import javax.swing.JButton;
38 import javax.swing.JComboBox;
39 import javax.swing.JFileChooser;
40 import javax.swing.JList;
41 import javax.swing.JPanel;
42 import javax.swing.JTextField;
43 import javax.swing.event.DocumentEvent;
44 import javax.swing.event.DocumentListener;
45 import javax.swing.text.Document;
46
47 import net.pterodactylus.jsite.core.Node;
48 import net.pterodactylus.jsite.core.Project;
49 import net.pterodactylus.jsite.i18n.I18n;
50 import net.pterodactylus.jsite.i18n.I18nable;
51 import net.pterodactylus.jsite.i18n.gui.I18nAction;
52 import net.pterodactylus.jsite.i18n.gui.I18nLabel;
53 import net.pterodactylus.util.logging.Logging;
54
55 /**
56  * A panel that contains all information about a project and lets the user edit
57  * the properties of the project.
58  * 
59  * @author David ‘Bombe’ Roden <bombe@freenetproject.org>
60  */
61 public class ProjectPanel extends JPanel implements DocumentListener, I18nable {
62
63         /** Logger. */
64         @SuppressWarnings("unused")
65         private static final Logger logger = Logging.getLogger(ProjectPanel.class.getName());
66
67         /** The Swing interface. */
68         private final SwingInterface swingInterface;
69
70         /** The project to show. */
71         private final Project project;
72
73         /** The “change base path” action. */
74         private I18nAction changeBasePathAction;
75
76         /** The “edit files” action. */
77         private I18nAction editFilesAction;
78
79         /** The “name” label. */
80         private I18nLabel nameLabel;
81
82         /** The “name” textfield. */
83         private JTextField nameTextField;
84
85         /** The “description” label. */
86         private I18nLabel descriptionLabel;
87
88         /** The “description” textfield. */
89         private JTextField descriptionTextField;
90
91         /** The “base path” label. */
92         private I18nLabel basePathLabel;
93
94         /** The “base path” textfield. */
95         private JTextField basePathTextField;
96
97         /** The “node” label. */
98         private I18nLabel nodeLabel;
99
100         /** The “node” action. */
101         private Action nodeAction;
102
103         /** The “node” combo box. */
104         private JComboBox nodeComboBox;
105
106         /**
107          * Creates a new project panel.
108          * 
109          * @param swingInterface
110          *            The Swing interface
111          * @param project
112          *            The project to display
113          */
114         public ProjectPanel(SwingInterface swingInterface, Project project) {
115                 super(new BorderLayout(12, 12));
116                 logger.log(Level.FINEST, "project: " + project);
117                 this.swingInterface = swingInterface;
118                 this.project = project;
119                 initActions();
120                 initComponents();
121         }
122
123         //
124         // ACCESSORS
125         //
126
127         /**
128          * Returns the project that is displayed in this panel.
129          * 
130          * @return The project of this panel
131          */
132         public Project getProject() {
133                 return project;
134         }
135
136         //
137         // ACTIONS
138         //
139
140         /**
141          * Adds the given node to the node combo boxes in all {@link ProjectPanel}s.
142          * 
143          * @param node
144          *            The node to add
145          */
146         public void addNode(Node node) {
147                 ((DefaultComboBoxModel) nodeComboBox.getModel()).addElement(node);
148         }
149
150         /**
151          * Removes the given node from the node combo boxes in all
152          * {@link ProjectPanel}s.
153          * 
154          * @param node
155          *            The node to remove
156          */
157         public void removeNode(Node node) {
158                 ((DefaultComboBoxModel) nodeComboBox.getModel()).removeElement(node);
159         }
160
161         //
162         // PRIVATE METHODS
163         //
164
165         /**
166          * Initializes all actions.
167          */
168         private void initActions() {
169                 changeBasePathAction = new I18nAction("projectPanel.button.changeBasePath") {
170
171                         /**
172                          * {@inheritDoc}
173                          */
174                         @SuppressWarnings("synthetic-access")
175                         public void actionPerformed(ActionEvent actionEvent) {
176                                 changeBasePath();
177                         }
178                 };
179                 editFilesAction = new I18nAction("projectPanel.button.editFiles") {
180
181                         /**
182                          * {@inheritDoc}
183                          */
184                         @SuppressWarnings("synthetic-access")
185                         public void actionPerformed(ActionEvent actionEvent) {
186                                 editFiles();
187                         }
188                 };
189                 nodeAction = new AbstractAction() {
190
191                         /**
192                          * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
193                          */
194                         @SuppressWarnings("synthetic-access")
195                         public void actionPerformed(ActionEvent actionEvent) {
196                                 Node node = (Node) nodeComboBox.getSelectedItem();
197                                 project.setNode(node);
198                         }
199                 };
200         }
201
202         /**
203          * Initializes all components of the panel.
204          */
205         private void initComponents() {
206                 setBorder(BorderFactory.createEmptyBorder(12, 12, 12, 12));
207
208                 JPanel propertiesPanel = createPropertiesPanel();
209                 add(propertiesPanel, BorderLayout.CENTER);
210
211                 JPanel buttonPanel = createButtonPanel();
212                 add(buttonPanel, BorderLayout.PAGE_END);
213         }
214
215         /**
216          * Creates the properties panel.
217          * 
218          * @return The properties panel
219          */
220         private JPanel createPropertiesPanel() {
221                 JPanel propertiesPanel = new JPanel(new GridBagLayout());
222
223                 nameTextField = new JTextField(project.getName());
224                 nameTextField.getDocument().addDocumentListener(this);
225                 nameLabel = new I18nLabel("projectPanel.label.name", nameTextField);
226                 propertiesPanel.add(nameLabel, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
227                 propertiesPanel.add(nameTextField, new GridBagConstraints(1, 0, 3, 1, 1.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.BOTH, new Insets(0, 12, 0, 0), 0, 0));
228
229                 descriptionTextField = new JTextField(project.getDescription());
230                 descriptionTextField.getDocument().addDocumentListener(this);
231                 descriptionLabel = new I18nLabel("projectPanel.label.description", descriptionTextField);
232                 propertiesPanel.add(descriptionLabel, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.BOTH, new Insets(12, 0, 0, 0), 0, 0));
233                 propertiesPanel.add(descriptionTextField, new GridBagConstraints(1, 1, 3, 1, 1.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.BOTH, new Insets(12, 12, 0, 0), 0, 0));
234
235                 basePathTextField = new JTextField(project.getBasePath());
236                 basePathTextField.setEditable(false);
237                 basePathLabel = new I18nLabel("projectPanel.label.basePath");
238                 JButton changeBasePathButton = new JButton(changeBasePathAction);
239                 JButton editFilesButton = new JButton(editFilesAction);
240                 propertiesPanel.add(basePathLabel, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.BOTH, new Insets(12, 0, 0, 0), 0, 0));
241                 propertiesPanel.add(basePathTextField, new GridBagConstraints(1, 2, 1, 1, 1.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL, new Insets(12, 12, 0, 0), 0, 0));
242                 propertiesPanel.add(changeBasePathButton, new GridBagConstraints(2, 2, 1, 1, 0.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.BOTH, new Insets(12, 12, 0, 0), 0, 0));
243                 propertiesPanel.add(editFilesButton, new GridBagConstraints(3, 2, 1, 1, 0.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.BOTH, new Insets(12, 12, 0, 0), 0, 0));
244
245                 nodeComboBox = new JComboBox(new DefaultComboBoxModel());
246                 nodeComboBox.setRenderer(new NodeComboBoxCellRenderer());
247                 ((DefaultComboBoxModel) nodeComboBox.getModel()).addElement(null);
248                 for (Node node : swingInterface.getNodes()) {
249                         ((DefaultComboBoxModel) nodeComboBox.getModel()).addElement(node);
250                 }
251                 nodeComboBox.setSelectedItem(project.getNode());
252                 nodeComboBox.addActionListener(nodeAction);
253                 nodeLabel = new I18nLabel("projectPanel.label.node", nodeComboBox);
254                 propertiesPanel.add(nodeLabel, new GridBagConstraints(0, 3, 1, 1, 0.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.BOTH, new Insets(12, 0, 0, 0), 0, 0));
255                 propertiesPanel.add(nodeComboBox, new GridBagConstraints(1, 3, 3, 1, 1.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.BOTH, new Insets(12, 12, 0, 0), 0, 0));
256
257                 propertiesPanel.add(new JPanel(), new GridBagConstraints(0, 4, 4, 1, 1.0, 1.0, GridBagConstraints.LINE_START, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
258
259                 return propertiesPanel;
260         }
261
262         /**
263          * Creates the button panel.
264          * 
265          * @return The button panel
266          */
267         private JPanel createButtonPanel() {
268                 JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.TRAILING, 12, 12));
269                 buttonPanel.setBorder(BorderFactory.createEmptyBorder(-12, -12, -12, -12));
270
271                 buttonPanel.add(new JButton(swingInterface.getDeleteProjectAction(project)));
272                 buttonPanel.add(new JButton(swingInterface.getCloneProjectAction(project)));
273
274                 return buttonPanel;
275         }
276
277         /**
278          * Updates the project from changes in the text fields.
279          * 
280          * @param document
281          *            The document that was changed
282          */
283         private void textFieldsUpdated(Document document) {
284                 if (nameTextField.getDocument() == document) {
285                         project.setName(nameTextField.getText());
286                 } else if (descriptionTextField.getDocument() == document) {
287                         project.setDescription(descriptionTextField.getText());
288                 }
289         }
290
291         //
292         // PRIVATE ACTIONS
293         //
294
295         /**
296          * Lets the user select a new base path and repopulates the file list.
297          */
298         void changeBasePath() {
299                 JFileChooser fileChooser = new JFileChooser(project.getBasePath());
300                 fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
301                 fileChooser.setApproveButtonText(I18n.get("projectPanel.button.approve.name"));
302                 int chooseAction = fileChooser.showOpenDialog(this);
303                 if (chooseAction == JFileChooser.APPROVE_OPTION) {
304                         String newBasePath = fileChooser.getSelectedFile().getPath();
305                         basePathTextField.setText(newBasePath);
306                         project.setBasePath(newBasePath);
307                 }
308         }
309
310         /**
311          * Pops up the file manager and lets the user edit the parameters for the
312          * physical and virtual files.
313          */
314         private void editFiles() {
315                 FileManager fileManager = new FileManager(swingInterface, project);
316                 fileManager.setVisible(true);
317         }
318
319         //
320         // INTERFACE I18nable
321         //
322
323         /**
324          * {@inheritDoc}
325          */
326         public void updateI18n() {
327                 nameLabel.updateI18n();
328                 descriptionLabel.updateI18n();
329                 basePathLabel.updateI18n();
330                 changeBasePathAction.updateI18n();
331                 editFilesAction.updateI18n();
332         }
333
334         //
335         // INTERFACE DocumentListener
336         //
337
338         /**
339          * {@inheritDoc}
340          */
341         public void changedUpdate(DocumentEvent documentEvent) {
342                 textFieldsUpdated(documentEvent.getDocument());
343         }
344
345         /**
346          * {@inheritDoc}
347          */
348         public void insertUpdate(DocumentEvent documentEvent) {
349                 textFieldsUpdated(documentEvent.getDocument());
350         }
351
352         /**
353          * {@inheritDoc}
354          */
355         public void removeUpdate(DocumentEvent documentEvent) {
356                 textFieldsUpdated(documentEvent.getDocument());
357         }
358
359         /**
360          * Cell cenderer for the node combo box.
361          * 
362          * @author David ‘Bombe’ Roden <bombe@freenetproject.org>
363          */
364         private static class NodeComboBoxCellRenderer extends DefaultListCellRenderer {
365
366                 /**
367                  * Empty constructor.
368                  */
369                 public NodeComboBoxCellRenderer() {
370                         super();
371                 }
372
373                 /**
374                  * @see javax.swing.DefaultListCellRenderer#getListCellRendererComponent(javax.swing.JList,
375                  *      java.lang.Object, int, boolean, boolean)
376                  */
377                 @Override
378                 public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
379                         if (value == null) {
380                                 return super.getListCellRendererComponent(list, "\u00a0", index, isSelected, cellHasFocus);
381                         }
382                         return super.getListCellRendererComponent(list, ((Node) value).getName(), index, isSelected, cellHasFocus);
383                 }
384
385         }
386
387 }