Calculate hashes when scanning files.
[jSite.git] / src / de / todesbaum / jsite / gui / ProjectFilesPage.java
1 /*
2  * jSite - ProjectFilesPage.java - Copyright © 2006–2011 David Roden
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17  */
18
19 package de.todesbaum.jsite.gui;
20
21 import java.awt.BorderLayout;
22 import java.awt.Dimension;
23 import java.awt.GridBagConstraints;
24 import java.awt.GridBagLayout;
25 import java.awt.Insets;
26 import java.awt.event.ActionEvent;
27 import java.awt.event.ActionListener;
28 import java.awt.event.KeyEvent;
29 import java.text.MessageFormat;
30 import java.util.ArrayList;
31 import java.util.HashSet;
32 import java.util.Iterator;
33 import java.util.List;
34 import java.util.Set;
35
36 import javax.swing.AbstractAction;
37 import javax.swing.Action;
38 import javax.swing.JButton;
39 import javax.swing.JCheckBox;
40 import javax.swing.JComboBox;
41 import javax.swing.JComponent;
42 import javax.swing.JLabel;
43 import javax.swing.JList;
44 import javax.swing.JOptionPane;
45 import javax.swing.JPanel;
46 import javax.swing.JScrollPane;
47 import javax.swing.JTextField;
48 import javax.swing.ListSelectionModel;
49 import javax.swing.SwingUtilities;
50 import javax.swing.event.DocumentEvent;
51 import javax.swing.event.DocumentListener;
52 import javax.swing.event.ListSelectionEvent;
53 import javax.swing.event.ListSelectionListener;
54 import javax.swing.text.BadLocationException;
55 import javax.swing.text.Document;
56
57 import de.todesbaum.jsite.application.FileOption;
58 import de.todesbaum.jsite.application.Project;
59 import de.todesbaum.jsite.gui.FileScanner.ScannedFile;
60 import de.todesbaum.jsite.i18n.I18n;
61 import de.todesbaum.jsite.i18n.I18nContainer;
62 import de.todesbaum.util.mime.DefaultMIMETypes;
63 import de.todesbaum.util.swing.TLabel;
64 import de.todesbaum.util.swing.TWizard;
65 import de.todesbaum.util.swing.TWizardPage;
66
67 /**
68  * Wizard page that lets the user manage the files of a project.
69  *
70  * @author David ‘Bombe’ Roden <bombe@freenetproject.org>
71  */
72 public class ProjectFilesPage extends TWizardPage implements ActionListener, ListSelectionListener, DocumentListener, FileScannerListener {
73
74         /** The project. */
75         private Project project;
76
77         /** The “scan files” action. */
78         private Action scanAction;
79
80         /** The “ignore hidden files” checkbox. */
81         private JCheckBox ignoreHiddenFilesCheckBox;
82
83         /** The list of project files. */
84         private JList projectFileList;
85
86         /** The “default file” checkbox. */
87         private JCheckBox defaultFileCheckBox;
88
89         /** The “insert” checkbox. */
90         private JCheckBox fileOptionsInsertCheckBox;
91
92         /** The “insert redirect” checkbox. */
93         private JCheckBox fileOptionsInsertRedirectCheckBox;
94
95         /** The “custom key” textfield. */
96         private JTextField fileOptionsCustomKeyTextField;
97
98         /** The “rename” check box. */
99         private JCheckBox fileOptionsRenameCheckBox;
100
101         /** The “new name” text field. */
102         private JTextField fileOptionsRenameTextField;
103
104         /** The “mime type” combo box. */
105         private JComboBox fileOptionsMIMETypeComboBox;
106
107         /**
108          * Creates a new project file page.
109          *
110          * @param wizard
111          *            The wizard the page belongs to
112          */
113         public ProjectFilesPage(final TWizard wizard) {
114                 super(wizard);
115                 pageInit();
116         }
117
118         /**
119          * Initializes the page and all its actions and components.
120          */
121         private void pageInit() {
122                 createActions();
123                 setLayout(new BorderLayout(12, 12));
124                 add(createProjectFilesPanel(), BorderLayout.CENTER);
125         }
126
127         /**
128          * Creates all actions.
129          */
130         private void createActions() {
131                 scanAction = new AbstractAction(I18n.getMessage("jsite.project-files.action.rescan")) {
132
133                         @SuppressWarnings("synthetic-access")
134                         public void actionPerformed(ActionEvent actionEvent) {
135                                 actionScan();
136                         }
137                 };
138                 scanAction.putValue(Action.MNEMONIC_KEY, KeyEvent.VK_S);
139                 scanAction.putValue(Action.SHORT_DESCRIPTION, I18n.getMessage("jsite.project-files.action.rescan.tooltip"));
140
141                 I18nContainer.getInstance().registerRunnable(new Runnable() {
142
143                         @SuppressWarnings("synthetic-access")
144                         public void run() {
145                                 scanAction.putValue(Action.NAME, I18n.getMessage("jsite.project-files.action.rescan"));
146                                 scanAction.putValue(Action.SHORT_DESCRIPTION, I18n.getMessage("jsite.project-files.action.rescan.tooltip"));
147                         }
148                 });
149         }
150
151         /**
152          * {@inheritDoc}
153          */
154         @Override
155         public void pageAdded(TWizard wizard) {
156                 actionScan();
157                 this.wizard.setPreviousName(I18n.getMessage("jsite.wizard.previous"));
158                 this.wizard.setNextName(I18n.getMessage("jsite.project-files.insert-now"));
159                 this.wizard.setQuitName(I18n.getMessage("jsite.wizard.quit"));
160         }
161
162         /**
163          * Creates the panel contains the project file list and options.
164          *
165          * @return The created panel
166          */
167         private JComponent createProjectFilesPanel() {
168                 JPanel projectFilesPanel = new JPanel(new BorderLayout(12, 12));
169
170                 projectFileList = new JList();
171                 projectFileList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
172                 projectFileList.setMinimumSize(new Dimension(250, projectFileList.getPreferredSize().height));
173                 projectFileList.addListSelectionListener(this);
174
175                 projectFilesPanel.add(new JScrollPane(projectFileList), BorderLayout.CENTER);
176
177                 JPanel fileOptionsAlignmentPanel = new JPanel(new BorderLayout(12, 12));
178                 projectFilesPanel.add(fileOptionsAlignmentPanel, BorderLayout.PAGE_END);
179                 JPanel fileOptionsPanel = new JPanel(new GridBagLayout());
180                 fileOptionsAlignmentPanel.add(fileOptionsPanel, BorderLayout.PAGE_START);
181
182                 ignoreHiddenFilesCheckBox = new JCheckBox(I18n.getMessage("jsite.project-files.ignore-hidden-files"));
183                 ignoreHiddenFilesCheckBox.setToolTipText(I18n.getMessage("jsite.project-files.ignore-hidden-files.tooltip"));
184                 ignoreHiddenFilesCheckBox.setName("ignore-hidden-files");
185                 ignoreHiddenFilesCheckBox.addActionListener(this);
186                 fileOptionsPanel.add(ignoreHiddenFilesCheckBox, new GridBagConstraints(0, 0, 5, 1, 1.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
187
188                 fileOptionsPanel.add(new JButton(scanAction), new GridBagConstraints(0, 1, 5, 1, 1.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.NONE, new Insets(6, 0, 0, 0), 0, 0));
189
190                 final JLabel fileOptionsLabel = new JLabel("<html><b>" + I18n.getMessage("jsite.project-files.file-options") + "</b></html>");
191                 fileOptionsPanel.add(fileOptionsLabel, new GridBagConstraints(0, 2, 5, 1, 1.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.NONE, new Insets(6, 0, 0, 0), 0, 0));
192
193                 defaultFileCheckBox = new JCheckBox(I18n.getMessage("jsite.project-files.default"));
194                 defaultFileCheckBox.setToolTipText(I18n.getMessage("jsite.project-files.default.tooltip"));
195                 defaultFileCheckBox.setName("default-file");
196                 defaultFileCheckBox.addActionListener(this);
197                 defaultFileCheckBox.setEnabled(false);
198
199                 fileOptionsPanel.add(defaultFileCheckBox, new GridBagConstraints(0, 3, 5, 1, 0.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL, new Insets(6, 18, 0, 0), 0, 0));
200
201                 fileOptionsInsertCheckBox = new JCheckBox(I18n.getMessage("jsite.project-files.insert"), true);
202                 fileOptionsInsertCheckBox.setToolTipText(I18n.getMessage("jsite.project-files.insert.tooltip"));
203                 fileOptionsInsertCheckBox.setName("insert");
204                 fileOptionsInsertCheckBox.setMnemonic(KeyEvent.VK_I);
205                 fileOptionsInsertCheckBox.addActionListener(this);
206                 fileOptionsInsertCheckBox.setEnabled(false);
207
208                 fileOptionsPanel.add(fileOptionsInsertCheckBox, new GridBagConstraints(0, 4, 5, 1, 0.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.NONE, new Insets(6, 18, 0, 0), 0, 0));
209
210                 fileOptionsCustomKeyTextField = new JTextField(45);
211                 fileOptionsCustomKeyTextField.setToolTipText(I18n.getMessage("jsite.project-files.custom-key.tooltip"));
212                 fileOptionsCustomKeyTextField.setEnabled(false);
213                 fileOptionsCustomKeyTextField.getDocument().addDocumentListener(this);
214
215                 fileOptionsInsertRedirectCheckBox = new JCheckBox(I18n.getMessage("jsite.project-files.insert-redirect"), false);
216                 fileOptionsInsertRedirectCheckBox.setToolTipText(I18n.getMessage("jsite.project-files.insert-redirect.tooltip"));
217                 fileOptionsInsertRedirectCheckBox.setName("insert-redirect");
218                 fileOptionsInsertRedirectCheckBox.setMnemonic(KeyEvent.VK_R);
219                 fileOptionsInsertRedirectCheckBox.addActionListener(this);
220                 fileOptionsInsertRedirectCheckBox.setEnabled(false);
221
222                 final TLabel customKeyLabel = new TLabel(I18n.getMessage("jsite.project-files.custom-key") + ":", KeyEvent.VK_K, fileOptionsCustomKeyTextField);
223                 fileOptionsPanel.add(fileOptionsInsertRedirectCheckBox, new GridBagConstraints(0, 5, 1, 1, 0.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.NONE, new Insets(6, 18, 0, 0), 0, 0));
224                 fileOptionsPanel.add(customKeyLabel, new GridBagConstraints(1, 5, 1, 1, 0.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.NONE, new Insets(6, 6, 0, 0), 0, 0));
225                 fileOptionsPanel.add(fileOptionsCustomKeyTextField, new GridBagConstraints(2, 5, 3, 1, 1.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL, new Insets(6, 6, 0, 0), 0, 0));
226
227                 fileOptionsRenameCheckBox = new JCheckBox(I18n.getMessage("jsite.project-files.rename"), false);
228                 fileOptionsRenameCheckBox.setToolTipText(I18n.getMessage("jsite.project-files.rename.tooltip"));
229                 fileOptionsRenameCheckBox.setName("rename");
230                 fileOptionsRenameCheckBox.setMnemonic(KeyEvent.VK_N);
231                 fileOptionsRenameCheckBox.addActionListener(this);
232                 fileOptionsRenameCheckBox.setEnabled(false);
233
234                 fileOptionsRenameTextField = new JTextField();
235                 fileOptionsRenameTextField.setEnabled(false);
236                 fileOptionsRenameTextField.getDocument().addDocumentListener(new DocumentListener() {
237
238                         @SuppressWarnings("synthetic-access")
239                         private void storeText(DocumentEvent documentEvent) {
240                                 FileOption fileOption = getSelectedFile();
241                                 Document document = documentEvent.getDocument();
242                                 int documentLength = document.getLength();
243                                 try {
244                                         fileOption.setChangedName(document.getText(0, documentLength).trim());
245                                 } catch (BadLocationException ble1) {
246                                         /* ignore, it should never happen. */
247                                 }
248                         }
249
250                         public void changedUpdate(DocumentEvent documentEvent) {
251                                 storeText(documentEvent);
252                         }
253
254                         public void insertUpdate(DocumentEvent documentEvent) {
255                                 storeText(documentEvent);
256                         }
257
258                         public void removeUpdate(DocumentEvent documentEvent) {
259                                 storeText(documentEvent);
260                         }
261
262                 });
263
264                 fileOptionsPanel.add(fileOptionsRenameCheckBox, new GridBagConstraints(0, 6, 2, 1, 0.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.NONE, new Insets(6, 18, 0, 0), 0, 0));
265                 fileOptionsPanel.add(fileOptionsRenameTextField, new GridBagConstraints(2, 6, 3, 1, 1.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL, new Insets(6, 6, 0, 0), 0, 0));
266
267                 fileOptionsMIMETypeComboBox = new JComboBox(DefaultMIMETypes.getAllMIMETypes());
268                 fileOptionsMIMETypeComboBox.setToolTipText(I18n.getMessage("jsite.project-files.mime-type.tooltip"));
269                 fileOptionsMIMETypeComboBox.setName("project-files.mime-type");
270                 fileOptionsMIMETypeComboBox.addActionListener(this);
271                 fileOptionsMIMETypeComboBox.setEditable(true);
272                 fileOptionsMIMETypeComboBox.setEnabled(false);
273
274                 final TLabel mimeTypeLabel = new TLabel(I18n.getMessage("jsite.project-files.mime-type") + ":", KeyEvent.VK_M, fileOptionsMIMETypeComboBox);
275                 fileOptionsPanel.add(mimeTypeLabel, new GridBagConstraints(0, 7, 1, 1, 0.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.NONE, new Insets(6, 18, 0, 0), 0, 0));
276                 fileOptionsPanel.add(fileOptionsMIMETypeComboBox, new GridBagConstraints(1, 7, 4, 1, 1.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL, new Insets(6, 6, 0, 0), 0, 0));
277
278                 I18nContainer.getInstance().registerRunnable(new Runnable() {
279
280                         @SuppressWarnings("synthetic-access")
281                         public void run() {
282                                 ignoreHiddenFilesCheckBox.setText(I18n.getMessage("jsite.project-files.ignore-hidden-files"));
283                                 ignoreHiddenFilesCheckBox.setToolTipText(I18n.getMessage("jsite.projet-files.ignore-hidden-files.tooltip"));
284                                 fileOptionsLabel.setText("<html><b>" + I18n.getMessage("jsite.project-files.file-options") + "</b></html>");
285                                 defaultFileCheckBox.setText(I18n.getMessage("jsite.project-files.default"));
286                                 defaultFileCheckBox.setToolTipText(I18n.getMessage("jsite.project-files.default.tooltip"));
287                                 fileOptionsInsertCheckBox.setText(I18n.getMessage("jsite.project-files.insert"));
288                                 fileOptionsInsertCheckBox.setToolTipText(I18n.getMessage("jsite.project-files.insert.tooltip"));
289                                 fileOptionsInsertRedirectCheckBox.setText(I18n.getMessage("jsite.project-files.insert-redirect"));
290                                 fileOptionsInsertRedirectCheckBox.setToolTipText(I18n.getMessage("jsite.project-files.insert-redirect.tooltip"));
291                                 fileOptionsCustomKeyTextField.setToolTipText(I18n.getMessage("jsite.project-files.custom-key.tooltip"));
292                                 customKeyLabel.setText(I18n.getMessage("jsite.project-files.custom-key") + ":");
293                                 fileOptionsRenameCheckBox.setText("jsite.project-files.rename");
294                                 fileOptionsRenameCheckBox.setToolTipText("jsite.project-files.rename.tooltip");
295                                 fileOptionsMIMETypeComboBox.setToolTipText(I18n.getMessage("jsite.project-files.mime-type.tooltip"));
296                                 mimeTypeLabel.setText(I18n.getMessage("jsite.project-files.mime-type") + ":");
297                         }
298                 });
299
300                 return projectFilesPanel;
301         }
302
303         /**
304          * Sets the project whose files to manage.
305          *
306          * @param project
307          *            The project whose files to manage
308          */
309         public void setProject(final Project project) {
310                 this.project = project;
311                 setHeading(MessageFormat.format(I18n.getMessage("jsite.project-files.heading"), project.getName()));
312                 setDescription(I18n.getMessage("jsite.project-files.description"));
313                 ignoreHiddenFilesCheckBox.setSelected(project.isIgnoreHiddenFiles());
314                 I18nContainer.getInstance().registerRunnable(new Runnable() {
315
316                         public void run() {
317                                 setHeading(MessageFormat.format(I18n.getMessage("jsite.project-files.heading"), project.getName()));
318                                 setDescription(I18n.getMessage("jsite.project-files.description"));
319                         }
320                 });
321         }
322
323         /**
324          * Returns a list of all project files.
325          *
326          * @return All project files
327          */
328         private List<String> getProjectFiles() {
329                 List<String> files = new ArrayList<String>();
330                 for (int index = 0, size = projectFileList.getModel().getSize(); index < size; index++) {
331                         files.add((String) projectFileList.getModel().getElementAt(index));
332                 }
333                 return files;
334         }
335
336         //
337         // ACTIONS
338         //
339
340         /**
341          * Rescans the project’s files.
342          */
343         private void actionScan() {
344                 projectFileList.clearSelection();
345                 projectFileList.setListData(new Object[0]);
346
347                 wizard.setNextEnabled(false);
348                 wizard.setPreviousEnabled(false);
349                 wizard.setQuitEnabled(false);
350
351                 FileScanner fileScanner = new FileScanner(project);
352                 fileScanner.addFileScannerListener(this);
353                 new Thread(fileScanner).start();
354         }
355
356         /**
357          * {@inheritDoc}
358          * <p>
359          * Updates the file list.
360          */
361         public void fileScannerFinished(FileScanner fileScanner) {
362                 final boolean error = fileScanner.isError();
363                 if (!error) {
364                         final List<ScannedFile> files = fileScanner.getFiles();
365                         SwingUtilities.invokeLater(new Runnable() {
366
367                                 @SuppressWarnings("synthetic-access")
368                                 public void run() {
369                                         String[] filenames = new String[files.size()];
370                                         for (int fileIndex = 0; fileIndex < files.size(); ++fileIndex) {
371                                                 filenames[fileIndex] = files.get(fileIndex).getFilename();
372                                         }
373                                         projectFileList.setListData(filenames);
374                                         projectFileList.clearSelection();
375                                 }
376                         });
377                         Set<String> entriesToRemove = new HashSet<String>();
378                         Iterator<String> filenames = new HashSet<String>(project.getFileOptions().keySet()).iterator();
379                         while (filenames.hasNext()) {
380                                 String filename = filenames.next();
381                                 if (!files.contains(filename)) {
382                                         entriesToRemove.add(filename);
383                                 }
384                         }
385                         for (String filename : entriesToRemove) {
386                                 project.setFileOption(filename, null);
387                         }
388                 } else {
389                         JOptionPane.showMessageDialog(wizard, I18n.getMessage("jsite.project-files.scan-error"), null, JOptionPane.ERROR_MESSAGE);
390                 }
391                 SwingUtilities.invokeLater(new Runnable() {
392
393                         @SuppressWarnings("synthetic-access")
394                         public void run() {
395                                 wizard.setPreviousEnabled(true);
396                                 wizard.setNextEnabled(!error);
397                                 wizard.setQuitEnabled(true);
398                         }
399                 });
400         }
401
402         /**
403          * Returns the {@link FileOption file options} for the currently selected
404          * file.
405          *
406          * @return The {@link FileOption}s for the selected file, or {@code null} if
407          *         no file is selected
408          */
409         private FileOption getSelectedFile() {
410                 String filename = (String) projectFileList.getSelectedValue();
411                 if (filename == null) {
412                         return null;
413                 }
414                 return project.getFileOption(filename);
415         }
416
417         //
418         // INTERFACE ActionListener
419         //
420
421         /**
422          * {@inheritDoc}
423          */
424         public void actionPerformed(ActionEvent actionEvent) {
425                 Object source = actionEvent.getSource();
426                 if ((source instanceof JCheckBox) && ("ignore-hidden-files".equals(((JCheckBox) source).getName()))) {
427                         project.setIgnoreHiddenFiles(((JCheckBox) source).isSelected());
428                         actionScan();
429                         return;
430                 }
431                 String filename = (String) projectFileList.getSelectedValue();
432                 if (filename == null) {
433                         return;
434                 }
435                 FileOption fileOption = project.getFileOption(filename);
436                 if (source instanceof JCheckBox) {
437                         JCheckBox checkBox = (JCheckBox) source;
438                         if ("default-file".equals(checkBox.getName())) {
439                                 if (checkBox.isSelected()) {
440                                         if (filename.indexOf('/') > -1) {
441                                                 JOptionPane.showMessageDialog(wizard, I18n.getMessage("jsite.project-files.invalid-default-file"), null, JOptionPane.ERROR_MESSAGE);
442                                                 checkBox.setSelected(false);
443                                         } else {
444                                                 project.setIndexFile(filename);
445                                         }
446                                 } else {
447                                         if (filename.equals(project.getIndexFile())) {
448                                                 project.setIndexFile(null);
449                                         }
450                                 }
451                         } else if ("insert".equals(checkBox.getName())) {
452                                 boolean isInsert = checkBox.isSelected();
453                                 fileOption.setInsert(isInsert);
454                                 fileOptionsInsertRedirectCheckBox.setEnabled(!isInsert);
455                         } else if ("insert-redirect".equals(checkBox.getName())) {
456                                 boolean isInsertRedirect = checkBox.isSelected();
457                                 fileOption.setInsertRedirect(isInsertRedirect);
458                                 fileOptionsCustomKeyTextField.setEnabled(isInsertRedirect);
459                         } else if ("rename".equals(checkBox.getName())) {
460                                 boolean isRenamed = checkBox.isSelected();
461                                 fileOptionsRenameTextField.setEnabled(isRenamed);
462                                 fileOption.setChangedName(isRenamed ? fileOptionsRenameTextField.getText() : "");
463                         }
464                 } else if (source instanceof JComboBox) {
465                         JComboBox comboBox = (JComboBox) source;
466                         if ("project-files.mime-type".equals(comboBox.getName())) {
467                                 fileOption.setMimeType((String) comboBox.getSelectedItem());
468                         }
469                 }
470         }
471
472         //
473         // INTERFACE ListSelectionListener
474         //
475
476         /**
477          * {@inheritDoc}
478          */
479         public void valueChanged(ListSelectionEvent e) {
480                 String filename = (String) projectFileList.getSelectedValue();
481                 boolean enabled = filename != null;
482                 boolean insert = fileOptionsInsertCheckBox.isSelected();
483                 defaultFileCheckBox.setEnabled(enabled);
484                 fileOptionsInsertCheckBox.setEnabled(enabled);
485                 fileOptionsRenameCheckBox.setEnabled(enabled);
486                 fileOptionsMIMETypeComboBox.setEnabled(enabled);
487                 if (filename != null) {
488                         FileOption fileOption = project.getFileOption(filename);
489                         defaultFileCheckBox.setSelected(filename.equals(project.getIndexFile()));
490                         fileOptionsInsertCheckBox.setSelected(fileOption.isInsert());
491                         fileOptionsInsertRedirectCheckBox.setEnabled(!fileOption.isInsert());
492                         fileOptionsInsertRedirectCheckBox.setSelected(fileOption.isInsertRedirect());
493                         fileOptionsCustomKeyTextField.setEnabled(fileOption.isInsertRedirect());
494                         fileOptionsCustomKeyTextField.setText(fileOption.getCustomKey());
495                         fileOptionsRenameCheckBox.setSelected(fileOption.hasChangedName());
496                         fileOptionsRenameTextField.setEnabled(fileOption.hasChangedName());
497                         fileOptionsRenameTextField.setText(fileOption.getChangedName());
498                         fileOptionsMIMETypeComboBox.getModel().setSelectedItem(fileOption.getMimeType());
499                 } else {
500                         defaultFileCheckBox.setSelected(false);
501                         fileOptionsInsertCheckBox.setSelected(true);
502                         fileOptionsInsertRedirectCheckBox.setEnabled(false);
503                         fileOptionsInsertRedirectCheckBox.setSelected(false);
504                         fileOptionsCustomKeyTextField.setEnabled(false);
505                         fileOptionsCustomKeyTextField.setText("CHK@");
506                         fileOptionsRenameCheckBox.setEnabled(false);
507                         fileOptionsRenameCheckBox.setSelected(false);
508                         fileOptionsRenameTextField.setEnabled(false);
509                         fileOptionsRenameTextField.setText("");
510                         fileOptionsMIMETypeComboBox.getModel().setSelectedItem(DefaultMIMETypes.DEFAULT_MIME_TYPE);
511                 }
512         }
513
514         //
515         // INTERFACE DocumentListener
516         //
517
518         /**
519          * Updates the options of the currently selected file with the changes made
520          * in the “custom key” textfield.
521          *
522          * @param documentEvent
523          *            The document event to process
524          */
525         private void processDocumentUpdate(DocumentEvent documentEvent) {
526                 String filename = (String) projectFileList.getSelectedValue();
527                 if (filename == null) {
528                         return;
529                 }
530                 FileOption fileOption = project.getFileOption(filename);
531                 Document document = documentEvent.getDocument();
532                 try {
533                         String text = document.getText(0, document.getLength());
534                         fileOption.setCustomKey(text);
535                 } catch (BadLocationException ble1) {
536                         /* ignore. */
537                 }
538         }
539
540         /**
541          * {@inheritDoc}
542          */
543         public void changedUpdate(DocumentEvent documentEvent) {
544                 processDocumentUpdate(documentEvent);
545         }
546
547         /**
548          * {@inheritDoc}
549          */
550         public void insertUpdate(DocumentEvent documentEvent) {
551                 processDocumentUpdate(documentEvent);
552         }
553
554         /**
555          * {@inheritDoc}
556          */
557         public void removeUpdate(DocumentEvent documentEvent) {
558                 processDocumentUpdate(documentEvent);
559         }
560
561 }