next stab at file manager
[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.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.awt.event.ActionListener;
30 import java.io.File;
31 import java.util.List;
32 import java.util.logging.Level;
33 import java.util.logging.Logger;
34
35 import javax.swing.BorderFactory;
36 import javax.swing.JButton;
37 import javax.swing.JCheckBox;
38 import javax.swing.JComboBox;
39 import javax.swing.JDialog;
40 import javax.swing.JOptionPane;
41 import javax.swing.JPanel;
42 import javax.swing.JScrollPane;
43 import javax.swing.JTree;
44 import javax.swing.event.TreeSelectionEvent;
45 import javax.swing.event.TreeSelectionListener;
46 import javax.swing.tree.DefaultTreeModel;
47 import javax.swing.tree.TreeModel;
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 TreeModel 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 “insert” action. */
94         private I18nAction insertAction;
95
96         /** The “insert” checkbox. */
97         private JCheckBox insertCheckBox;
98
99         /** The “use custom mime type” action. */
100         private I18nAction useCustomMimeTypeAction;
101
102         /** The “use custom mime type” checkbox. */
103         private JCheckBox useCustomMimeTypeCheckBox;
104
105         /** The “mime type” combo box. */
106         private JComboBox mimeTypeComboBox;
107
108         /**
109          * Creates a new file manager.
110          * 
111          * @param swingInterface
112          *            The Swing interface
113          * @param project
114          *            The project whose files to manage
115          */
116         public FileManager(SwingInterface swingInterface, Project project) {
117                 super(swingInterface.getMainWindow(), I18n.get("fileManager.title", project.getName()), true);
118                 logger.log(Level.FINEST, "project: " + project);
119                 this.swingInterface = swingInterface;
120                 this.project = project;
121                 fileTreeRoot = new SortableTreeNode(project.getName());
122                 fileTreeModel = new DefaultTreeModel(fileTreeRoot);
123                 initActions();
124                 initComponents();
125                 pack();
126                 SwingUtils.center(this);
127         }
128
129         //
130         // ACTIONS
131         //
132
133         /**
134          * @see java.awt.Component#setVisible(boolean)
135          */
136         @Override
137         public void setVisible(boolean visible) {
138                 if (visible) {
139                         initiateFileScan();
140                 }
141                 super.setVisible(visible);
142         }
143
144         //
145         // PRIVATE METHODS
146         //
147
148         /**
149          * Initializes all actions.
150          */
151         private void initActions() {
152                 closeAction = new I18nAction("fileManager.button.close") {
153
154                         /**
155                          * {@inheritDoc}
156                          */
157                         public void actionPerformed(ActionEvent e) {
158                                 setVisible(false);
159                         }
160                 };
161                 rescanAction = new I18nAction("fileManager.button.rescan") {
162
163                         /**
164                          * {@inheritDoc}
165                          */
166                         @SuppressWarnings("synthetic-access")
167                         public void actionPerformed(ActionEvent actionEvent) {
168                                 initiateFileScan();
169                         }
170                 };
171                 insertAction = new I18nAction("fileManager.checkbox.insertFile") {
172
173                         /**
174                          * {@inheritDoc}
175                          */
176                         @SuppressWarnings("synthetic-access")
177                         public void actionPerformed(ActionEvent actionEvent) {
178                                 /* TODO */
179                         }
180                 };
181                 insertAction.setEnabled(false);
182                 useCustomMimeTypeAction = new I18nAction("fileManager.checkbox.useCustomMimeType") {
183
184                         /**
185                          * {@inheritDoc}
186                          */
187                         @SuppressWarnings("synthetic-access")
188                         public void actionPerformed(ActionEvent actionEvent) {
189                                 /* TODO */
190                         }
191                 };
192                 useCustomMimeTypeAction.setEnabled(false);
193         }
194
195         /**
196          * Initializes all components.
197          */
198         private void initComponents() {
199                 JPanel contentPanel = new JPanel(new BorderLayout(12, 12));
200                 contentPanel.setBorder(BorderFactory.createEmptyBorder(12, 12, 12, 12));
201
202                 contentPanel.add(createFileManagerPanel(), BorderLayout.CENTER);
203                 contentPanel.add(createButtonPanel(), BorderLayout.PAGE_END);
204
205                 setContentPane(contentPanel);
206         }
207
208         /**
209          * Creates the main panel with the file tree and the file properties.
210          * 
211          * @return The mail panel
212          */
213         private Component createFileManagerPanel() {
214                 JPanel fileManagerPanel = new JPanel(new BorderLayout(12, 12));
215
216                 /* file tree panel */
217                 JPanel fileTreePanel = new JPanel(new BorderLayout(12, 12));
218                 fileManagerPanel.add(fileTreePanel, BorderLayout.LINE_START);
219
220                 fileTree = new JTree(fileTreeModel);
221                 fileTree.setShowsRootHandles(false);
222                 fileTree.addTreeSelectionListener(this);
223                 fileTreePanel.add(new JScrollPane(fileTree), BorderLayout.CENTER);
224
225                 projectFilesLabel = new I18nLabel("fileManager.label.projectFiles", fileTree);
226                 JPanel projectFilesLabelPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 0, 0));
227                 fileTreePanel.add(projectFilesLabelPanel, BorderLayout.NORTH);
228                 projectFilesLabelPanel.add(projectFilesLabel);
229
230                 /* properties panel */
231                 JPanel propertiesPanel = new JPanel(new GridBagLayout());
232                 fileManagerPanel.add(propertiesPanel, BorderLayout.CENTER);
233                 propertiesPanel.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEtchedBorder(), BorderFactory.createEmptyBorder(12, 12, 12, 12)));
234
235                 insertCheckBox = new JCheckBox(insertAction);
236                 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));
237
238                 useCustomMimeTypeCheckBox = new JCheckBox(useCustomMimeTypeAction);
239                 List<String> allMimeTypes = MimeTypes.getAllMimeTypes();
240                 mimeTypeComboBox = new JComboBox(allMimeTypes.toArray(new String[0]));
241                 mimeTypeComboBox.setEnabled(false);
242                 mimeTypeComboBox.addActionListener(this);
243                 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));
244                 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));
245
246                 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));
247
248                 /* action button panel */
249                 JPanel actionButtonPanel = new JPanel(new FlowLayout(FlowLayout.LEADING, 12, 12));
250                 actionButtonPanel.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEtchedBorder(), BorderFactory.createEmptyBorder(-12, -12, -12, -12)));
251                 
252                 return fileManagerPanel;
253         }
254
255         /**
256          * Creates the button panel.
257          * 
258          * @return The button panel
259          */
260         private Component createButtonPanel() {
261                 JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.TRAILING, 12, 12));
262
263                 buttonPanel.setBorder(BorderFactory.createEmptyBorder(-12, -12, -12, -12));
264                 JButton closeButton = new JButton(closeAction);
265                 buttonPanel.add(closeButton);
266
267                 getRootPane().setDefaultButton(closeButton);
268                 return buttonPanel;
269         }
270
271         private void initiateFileScan() {
272                 swingInterface.getThreadPool().execute(new Runnable() {
273
274                         /**
275                          * @see java.lang.Runnable#run()
276                          */
277                         @SuppressWarnings("synthetic-access")
278                         public void run() {
279                                 String basePath = project.getBasePath();
280                                 File basePathDirectory = new File(basePath);
281                                 if (!basePathDirectory.exists() || !basePathDirectory.isDirectory()) {
282                                         /* TODO - i18n */
283                                         JOptionPane.showMessageDialog(FileManager.this, I18n.get(""), I18n.get(""), JOptionPane.ERROR_MESSAGE);
284                                         return;
285                                 }
286                                 synchronized (fileTreeRoot) {
287                                         scanDirectory(fileTreeRoot, basePathDirectory);
288                                 }
289                                 fileTree.repaint();
290                         }
291
292                         private void scanDirectory(SortableTreeNode rootNode, File directory) {
293                                 System.out.println("scanning " + directory.getAbsolutePath());
294                                 for (File file: directory.listFiles()) {
295                                         SortableTreeNode fileNode = new SortableTreeNode(file.getName());
296                                         rootNode.add(fileNode);
297                                         if (file.isDirectory()) {
298                                                 scanDirectory(fileNode, file);
299                                         }
300                                 }
301                                 rootNode.sort();
302                         }
303
304                 });
305         }
306
307         //
308         // INTERFACE I18nable
309         //
310
311         /**
312          * {@inheritDoc}
313          */
314         public void updateI18n() {
315                 setTitle(I18n.get("fileManager.title", project.getName()));
316         }
317
318         //
319         // INTERFACE TreeSelectionListener
320         //
321
322         /**
323          * {@inheritDoc}
324          */
325         public void valueChanged(TreeSelectionEvent treeSelectionEvent) {
326         }
327
328         //
329         // INTERFACE ActionListener
330         //
331
332         /**
333          * {@inheritDoc}
334          */
335         public void actionPerformed(ActionEvent actionEvent) {
336         }
337
338 }