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