fix scroll pane size
[jSite2.git] / src / net / pterodactylus / jsite / gui / FileManager.java
1 /*
2  * jSite2 - FileManager.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.Dimension;
25 import java.awt.FlowLayout;
26 import java.awt.GridBagConstraints;
27 import java.awt.GridBagLayout;
28 import java.awt.Insets;
29 import java.awt.event.ActionEvent;
30 import java.awt.event.ActionListener;
31 import java.io.File;
32 import java.util.List;
33 import java.util.logging.Level;
34 import java.util.logging.Logger;
35
36 import javax.swing.BorderFactory;
37 import javax.swing.JButton;
38 import javax.swing.JCheckBox;
39 import javax.swing.JComboBox;
40 import javax.swing.JDialog;
41 import javax.swing.JOptionPane;
42 import javax.swing.JPanel;
43 import javax.swing.JScrollPane;
44 import javax.swing.JTree;
45 import javax.swing.event.TreeSelectionEvent;
46 import javax.swing.event.TreeSelectionListener;
47 import javax.swing.tree.DefaultTreeModel;
48
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.jsite.project.Project;
54 import net.pterodactylus.util.io.MimeTypes;
55 import net.pterodactylus.util.logging.Logging;
56 import net.pterodactylus.util.swing.SortableTreeNode;
57 import net.pterodactylus.util.swing.SwingUtils;
58
59 /**
60  * Manages physical and virtual files in a project.
61  * 
62  * @author David ‘Bombe’ Roden <bombe@freenetproject.org>
63  */
64 public class FileManager extends JDialog implements I18nable, ActionListener, TreeSelectionListener {
65
66         /** Logger. */
67         private static final Logger logger = Logging.getLogger(FileManager.class.getName());
68
69         /** The Swing interface. */
70         private final SwingInterface swingInterface;
71
72         /** The project whose files to manage. */
73         private final Project project;
74
75         /** The root of the file tree. */
76         private final SortableTreeNode fileTreeRoot;
77
78         /** The tree model for the project files. */
79         private final DefaultTreeModel fileTreeModel;
80
81         /** The “rescan” action. */
82         private I18nAction rescanAction;
83
84         /** The “close” action. */
85         private I18nAction closeAction;
86
87         /** The “project files” label. */
88         private I18nLabel projectFilesLabel;
89
90         /** The tree that shows the files. */
91         private JTree fileTree;
92
93         /** The scroll pane that holds the file tree. */
94         private JScrollPane fileScrollPane;
95         
96         /** The “insert” action. */
97         private I18nAction insertAction;
98
99         /** The “insert” checkbox. */
100         private JCheckBox insertCheckBox;
101
102         /** The “use custom mime type” action. */
103         private I18nAction useCustomMimeTypeAction;
104
105         /** The “use custom mime type” checkbox. */
106         private JCheckBox useCustomMimeTypeCheckBox;
107
108         /** The “mime type” combo box. */
109         private JComboBox mimeTypeComboBox;
110
111         /**
112          * Creates a new file manager.
113          * 
114          * @param swingInterface
115          *            The Swing interface
116          * @param project
117          *            The project whose files to manage
118          */
119         public FileManager(SwingInterface swingInterface, Project project) {
120                 super(swingInterface.getMainWindow(), I18n.get("fileManager.title", project.getName()), true);
121                 logger.log(Level.FINEST, "project: " + project);
122                 this.swingInterface = swingInterface;
123                 this.project = project;
124                 fileTreeRoot = new SortableTreeNode(project.getName());
125                 fileTreeModel = new DefaultTreeModel(fileTreeRoot);
126                 initActions();
127                 initComponents();
128                 pack();
129                 SwingUtils.center(this);
130         }
131
132         //
133         // ACTIONS
134         //
135
136         /**
137          * @see java.awt.Component#setVisible(boolean)
138          */
139         @Override
140         public void setVisible(boolean visible) {
141                 if (visible) {
142                         initiateFileScan();
143                 }
144                 super.setVisible(visible);
145         }
146
147         //
148         // PRIVATE METHODS
149         //
150
151         /**
152          * Initializes all actions.
153          */
154         private void initActions() {
155                 closeAction = new I18nAction("fileManager.button.close") {
156
157                         /**
158                          * {@inheritDoc}
159                          */
160                         public void actionPerformed(ActionEvent e) {
161                                 setVisible(false);
162                         }
163                 };
164                 rescanAction = new I18nAction("fileManager.button.rescan") {
165
166                         /**
167                          * {@inheritDoc}
168                          */
169                         @SuppressWarnings("synthetic-access")
170                         public void actionPerformed(ActionEvent actionEvent) {
171                                 initiateFileScan();
172                                 setEnabled(false);
173                         }
174                 };
175                 insertAction = new I18nAction("fileManager.checkbox.insertFile") {
176
177                         /**
178                          * {@inheritDoc}
179                          */
180                         @SuppressWarnings("synthetic-access")
181                         public void actionPerformed(ActionEvent actionEvent) {
182                                 /* TODO */
183                         }
184                 };
185                 insertAction.setEnabled(false);
186                 useCustomMimeTypeAction = new I18nAction("fileManager.checkbox.useCustomMimeType") {
187
188                         /**
189                          * {@inheritDoc}
190                          */
191                         @SuppressWarnings("synthetic-access")
192                         public void actionPerformed(ActionEvent actionEvent) {
193                                 /* TODO */
194                         }
195                 };
196                 useCustomMimeTypeAction.setEnabled(false);
197         }
198
199         /**
200          * Initializes all components.
201          */
202         private void initComponents() {
203                 JPanel contentPanel = new JPanel(new BorderLayout(12, 12));
204                 contentPanel.setBorder(BorderFactory.createEmptyBorder(12, 12, 12, 12));
205
206                 contentPanel.add(createFileManagerPanel(), BorderLayout.CENTER);
207                 contentPanel.add(createButtonPanel(), BorderLayout.PAGE_END);
208
209                 setContentPane(contentPanel);
210         }
211
212         /**
213          * Creates the main panel with the file tree and the file properties.
214          * 
215          * @return The mail panel
216          */
217         private Component createFileManagerPanel() {
218                 JPanel fileManagerPanel = new JPanel(new BorderLayout(12, 12));
219
220                 /* file tree panel */
221                 JPanel fileTreePanel = new JPanel(new BorderLayout(12, 12));
222                 fileManagerPanel.add(fileTreePanel, BorderLayout.LINE_START);
223
224                 fileTree = new JTree(fileTreeModel);
225                 fileTree.setShowsRootHandles(false);
226                 fileTree.addTreeSelectionListener(this);
227                 fileTreePanel.add(fileScrollPane = new JScrollPane(fileTree), BorderLayout.CENTER);
228                 fileScrollPane.setPreferredSize(new Dimension(250, 400));
229
230                 projectFilesLabel = new I18nLabel("fileManager.label.projectFiles", fileTree);
231                 JPanel projectFilesLabelPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 0, 0));
232                 fileTreePanel.add(projectFilesLabelPanel, BorderLayout.NORTH);
233                 projectFilesLabelPanel.add(projectFilesLabel);
234
235                 /* the right panel */
236                 JPanel rightPanel = new JPanel(new BorderLayout(12, 12));
237                 fileManagerPanel.add(rightPanel, BorderLayout.CENTER);
238
239                 /* properties panel */
240                 JPanel propertiesPanel = new JPanel(new GridBagLayout());
241                 rightPanel.add(propertiesPanel, BorderLayout.CENTER);
242                 propertiesPanel.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEtchedBorder(), BorderFactory.createEmptyBorder(12, 12, 12, 12)));
243
244                 insertCheckBox = new JCheckBox(insertAction);
245                 propertiesPanel.add(insertCheckBox, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
246
247                 useCustomMimeTypeCheckBox = new JCheckBox(useCustomMimeTypeAction);
248                 List<String> allMimeTypes = MimeTypes.getAllMimeTypes();
249                 mimeTypeComboBox = new JComboBox(allMimeTypes.toArray(new String[0]));
250                 mimeTypeComboBox.setEnabled(false);
251                 mimeTypeComboBox.addActionListener(this);
252                 propertiesPanel.add(useCustomMimeTypeCheckBox, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.BOTH, new Insets(6, 0, 0, 0), 0, 0));
253                 propertiesPanel.add(mimeTypeComboBox, new GridBagConstraints(1, 1, 1, 1, 1.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.BOTH, new Insets(6, 6, 0, 0), 0, 0));
254
255                 propertiesPanel.add(new JPanel(), new GridBagConstraints(0, 2, 1, 1, 1.0, 1.0, GridBagConstraints.LINE_START, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
256
257                 /* action button panel */
258                 JPanel actionButtonPanel = new JPanel(new FlowLayout(FlowLayout.LEADING, 12, 12));
259                 rightPanel.add(actionButtonPanel, BorderLayout.PAGE_END);
260                 actionButtonPanel.setBorder(BorderFactory.createEtchedBorder());
261
262                 JButton rescanButton = new JButton(rescanAction);
263                 actionButtonPanel.add(rescanButton);
264
265                 return fileManagerPanel;
266         }
267
268         /**
269          * Creates the button panel.
270          * 
271          * @return The button panel
272          */
273         private Component createButtonPanel() {
274                 JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.TRAILING, 12, 12));
275
276                 buttonPanel.setBorder(BorderFactory.createEmptyBorder(-12, -12, -12, -12));
277                 JButton closeButton = new JButton(closeAction);
278                 buttonPanel.add(closeButton);
279
280                 getRootPane().setDefaultButton(closeButton);
281                 return buttonPanel;
282         }
283
284         /**
285          * Initiates a file scan.
286          */
287         private void initiateFileScan() {
288                 swingInterface.getThreadPool().execute(new Runnable() {
289
290                         /**
291                          * @see java.lang.Runnable#run()
292                          */
293                         @SuppressWarnings("synthetic-access")
294                         public void run() {
295                                 String basePath = project.getBasePath();
296                                 File basePathDirectory = new File(basePath);
297                                 if (!basePathDirectory.exists() || !basePathDirectory.isDirectory()) {
298                                         /* TODO - i18n */
299                                         JOptionPane.showMessageDialog(FileManager.this, I18n.get(""), I18n.get(""), JOptionPane.ERROR_MESSAGE);
300                                         return;
301                                 }
302                                 synchronized (fileTreeRoot) {
303                                         fileTreeRoot.removeAll();
304                                         scanDirectory(fileTreeRoot, basePathDirectory);
305                                 }
306                                 fileTreeModel.reload();
307                                 fileScrollPane.revalidate();
308                                 rescanAction.setEnabled(true);
309                         }
310
311                         private void scanDirectory(SortableTreeNode rootNode, File directory) {
312                                 for (File file: directory.listFiles()) {
313                                         SortableTreeNode fileNode = new SortableTreeNode(file.getName());
314                                         rootNode.add(fileNode);
315                                         if (file.isDirectory()) {
316                                                 scanDirectory(fileNode, file);
317                                         }
318                                 }
319                                 rootNode.sort();
320                         }
321
322                 });
323         }
324
325         //
326         // INTERFACE I18nable
327         //
328
329         /**
330          * {@inheritDoc}
331          */
332         public void updateI18n() {
333                 setTitle(I18n.get("fileManager.title", project.getName()));
334         }
335
336         //
337         // INTERFACE TreeSelectionListener
338         //
339
340         /**
341          * {@inheritDoc}
342          */
343         public void valueChanged(TreeSelectionEvent treeSelectionEvent) {
344                 /* TODO */
345         }
346
347         //
348         // INTERFACE ActionListener
349         //
350
351         /**
352          * {@inheritDoc}
353          */
354         public void actionPerformed(ActionEvent actionEvent) {
355                 /* TODO */
356         }
357
358 }