fix exception when files is removed (should fix #1755)
[jSite.git] / src / de / todesbaum / jsite / gui / ProjectFilesPage.java
1 /*
2  * jSite - a tool for uploading websites into Freenet
3  * Copyright (C) 2006 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 de.todesbaum.jsite.gui;
21
22 import java.awt.BorderLayout;
23 import java.awt.Dimension;
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.awt.event.KeyEvent;
31 import java.text.MessageFormat;
32 import java.util.ArrayList;
33 import java.util.Collections;
34 import java.util.HashSet;
35 import java.util.Iterator;
36 import java.util.List;
37 import java.util.Set;
38 import java.util.Map.Entry;
39
40 import javax.swing.AbstractAction;
41 import javax.swing.Action;
42 import javax.swing.DefaultComboBoxModel;
43 import javax.swing.JButton;
44 import javax.swing.JCheckBox;
45 import javax.swing.JComboBox;
46 import javax.swing.JComponent;
47 import javax.swing.JLabel;
48 import javax.swing.JList;
49 import javax.swing.JOptionPane;
50 import javax.swing.JPanel;
51 import javax.swing.JScrollPane;
52 import javax.swing.JSpinner;
53 import javax.swing.JTextField;
54 import javax.swing.ListSelectionModel;
55 import javax.swing.SpinnerNumberModel;
56 import javax.swing.SwingUtilities;
57 import javax.swing.border.EmptyBorder;
58 import javax.swing.event.ChangeEvent;
59 import javax.swing.event.ChangeListener;
60 import javax.swing.event.DocumentEvent;
61 import javax.swing.event.DocumentListener;
62 import javax.swing.event.ListSelectionEvent;
63 import javax.swing.event.ListSelectionListener;
64 import javax.swing.text.BadLocationException;
65 import javax.swing.text.Document;
66
67 import de.todesbaum.jsite.application.FileOption;
68 import de.todesbaum.jsite.application.Project;
69 import de.todesbaum.jsite.i18n.I18n;
70 import de.todesbaum.jsite.i18n.I18nContainer;
71 import de.todesbaum.util.mime.DefaultMIMETypes;
72 import de.todesbaum.util.swing.TLabel;
73 import de.todesbaum.util.swing.TWizard;
74 import de.todesbaum.util.swing.TWizardPage;
75
76 /**
77  * @author David Roden <droden@gmail.com>
78  * @version $Id$
79  */
80 public class ProjectFilesPage extends TWizardPage implements ActionListener, ListSelectionListener, DocumentListener, FileScannerListener, ChangeListener {
81
82         protected Project project;
83
84         protected Action scanAction;
85         protected Action editContainerAction;
86         protected Action addContainerAction;
87         protected Action deleteContainerAction;
88
89         protected JList projectFileList;
90         private JCheckBox defaultFileCheckBox;
91         private JCheckBox fileOptionsInsertCheckBox;
92         private JTextField fileOptionsCustomKeyTextField;
93         private JComboBox fileOptionsMIMETypeComboBox;
94         protected DefaultComboBoxModel containerComboBoxModel;
95         private JComboBox fileOptionsContainerComboBox;
96         private JSpinner replaceEditionRangeSpinner;
97         private JCheckBox replacementCheckBox;
98
99         public ProjectFilesPage(final TWizard wizard) {
100                 super(wizard);
101                 pageInit();
102         }
103
104         private void pageInit() {
105                 createActions();
106                 setLayout(new BorderLayout(12, 12));
107                 add(createProjectFilesPanel(), BorderLayout.CENTER);
108         }
109
110         private void createActions() {
111                 scanAction = new AbstractAction(I18n.getMessage("jsite.project-files.action.rescan")) {
112
113                         public void actionPerformed(ActionEvent actionEvent) {
114                                 actionScan();
115                         }
116                 };
117                 scanAction.putValue(Action.MNEMONIC_KEY, KeyEvent.VK_S);
118                 scanAction.putValue(Action.SHORT_DESCRIPTION, I18n.getMessage("jsite.project-files.action.rescan.tooltip"));
119
120                 addContainerAction = new AbstractAction(I18n.getMessage("jsite.project-files.action.add-container")) {
121
122                         public void actionPerformed(ActionEvent actionEvent) {
123                                 actionAddContainer();
124                         }
125                 };
126                 addContainerAction.putValue(Action.SHORT_DESCRIPTION, I18n.getMessage("jsite.project-files.action.add-container.tooltip"));
127                 addContainerAction.setEnabled(false);
128
129                 editContainerAction = new AbstractAction(I18n.getMessage("jsite.project-files.action.edit-container")) {
130
131                         public void actionPerformed(ActionEvent actionEvent) {
132                                 actionEditContainer();
133                         }
134                 };
135                 editContainerAction.putValue(Action.SHORT_DESCRIPTION, I18n.getMessage("jsite.project-files.action.edit-container.tooltip"));
136                 editContainerAction.setEnabled(false);
137
138                 deleteContainerAction = new AbstractAction(I18n.getMessage("jsite.project-files.action.delete-container")) {
139
140                         public void actionPerformed(ActionEvent actionEvent) {
141                                 actionDeleteContainer();
142                         }
143                 };
144                 deleteContainerAction.putValue(Action.SHORT_DESCRIPTION, I18n.getMessage("jsite.project-files.action.delete-container.tooltip"));
145                 deleteContainerAction.setEnabled(false);
146
147                 I18nContainer.getInstance().registerRunnable(new Runnable() {
148
149                         public void run() {
150                                 scanAction.putValue(Action.NAME, I18n.getMessage("jsite.project-files.action.rescan"));
151                                 scanAction.putValue(Action.SHORT_DESCRIPTION, I18n.getMessage("jsite.project-files.action.rescan.tooltip"));
152                                 addContainerAction.putValue(Action.NAME, I18n.getMessage("jsite.project-files.action.add-container"));
153                                 addContainerAction.putValue(Action.SHORT_DESCRIPTION, I18n.getMessage("jsite.project-files.action.add-container.tooltip"));
154                                 editContainerAction.putValue(Action.NAME, I18n.getMessage("jsite.project-files.action.edit-container"));
155                                 editContainerAction.putValue(Action.SHORT_DESCRIPTION, I18n.getMessage("jsite.project-files.action.edit-container.tooltip"));
156                                 deleteContainerAction.putValue(Action.NAME, I18n.getMessage("jsite.project-files.action.delete-container"));
157                                 deleteContainerAction.putValue(Action.SHORT_DESCRIPTION, I18n.getMessage("jsite.project-files.action.delete-container.tooltip"));
158                         }
159                 });
160         }
161
162         @Override
163         public void pageAdded(TWizard wizard) {
164                 actionScan();
165                 this.wizard.setPreviousName(I18n.getMessage("jsite.wizard.previous"));
166                 this.wizard.setNextName(I18n.getMessage("jsite.project-files.insert-now"));
167                 this.wizard.setQuitName(I18n.getMessage("jsite.wizard.quit"));
168         }
169
170         private JComponent createProjectFilesPanel() {
171                 JPanel projectFilesPanel = new JPanel(new BorderLayout(12, 12));
172
173                 projectFileList = new JList();
174                 projectFileList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
175                 projectFileList.setMinimumSize(new Dimension(250, projectFileList.getPreferredSize().height));
176                 projectFileList.addListSelectionListener(this);
177
178                 projectFilesPanel.add(new JScrollPane(projectFileList), BorderLayout.CENTER);
179
180                 JPanel fileOptionsAlignmentPanel = new JPanel(new BorderLayout(12, 12));
181                 projectFilesPanel.add(fileOptionsAlignmentPanel, BorderLayout.PAGE_END);
182                 JPanel fileOptionsPanel = new JPanel(new GridBagLayout());
183                 fileOptionsAlignmentPanel.add(fileOptionsPanel, BorderLayout.PAGE_START);
184
185                 fileOptionsPanel.add(new JButton(scanAction), new GridBagConstraints(0, 0, 5, 1, 1.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
186
187                 final JLabel fileOptionsLabel = new JLabel("<html><b>" + I18n.getMessage("jsite.project-files.file-options") + "</b></html>");
188                 fileOptionsPanel.add(fileOptionsLabel, 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                 defaultFileCheckBox = new JCheckBox(I18n.getMessage("jsite.project-files.default"));
191                 defaultFileCheckBox.setToolTipText(I18n.getMessage("jsite.project-files.default.tooltip"));
192                 defaultFileCheckBox.setName("default-file");
193                 defaultFileCheckBox.addActionListener(this);
194                 defaultFileCheckBox.setEnabled(false);
195
196                 fileOptionsPanel.add(defaultFileCheckBox, new GridBagConstraints(0, 2, 5, 1, 0.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL, new Insets(6, 18, 0, 0), 0, 0));
197
198                 fileOptionsInsertCheckBox = new JCheckBox(I18n.getMessage("jsite.project-files.insert"), true);
199                 fileOptionsInsertCheckBox.setToolTipText(I18n.getMessage("jsite.project-files.insert.tooltip"));
200                 fileOptionsInsertCheckBox.setName("insert");
201                 fileOptionsInsertCheckBox.setMnemonic(KeyEvent.VK_I);
202                 fileOptionsInsertCheckBox.addActionListener(this);
203                 fileOptionsInsertCheckBox.setEnabled(false);
204
205                 fileOptionsPanel.add(fileOptionsInsertCheckBox, new GridBagConstraints(0, 3, 5, 1, 0.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.NONE, new Insets(6, 18, 0, 0), 0, 0));
206
207                 fileOptionsCustomKeyTextField = new JTextField(45);
208                 fileOptionsCustomKeyTextField.setToolTipText(I18n.getMessage("jsite.project-files.custom-key.tooltip"));
209                 fileOptionsCustomKeyTextField.setEnabled(false);
210                 fileOptionsCustomKeyTextField.getDocument().addDocumentListener(this);
211
212                 final TLabel customKeyLabel = new TLabel(I18n.getMessage("jsite.project-files.custom-key") + ":", KeyEvent.VK_K, fileOptionsCustomKeyTextField);
213                 fileOptionsPanel.add(customKeyLabel, new GridBagConstraints(0, 4, 1, 1, 0.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.NONE, new Insets(6, 18, 0, 0), 0, 0));
214                 fileOptionsPanel.add(fileOptionsCustomKeyTextField, new GridBagConstraints(1, 4, 4, 1, 1.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL, new Insets(6, 6, 0, 0), 0, 0));
215
216                 fileOptionsMIMETypeComboBox = new JComboBox(DefaultMIMETypes.getAllMIMETypes());
217                 fileOptionsMIMETypeComboBox.setToolTipText(I18n.getMessage("jsite.project-files.mime-type.tooltip"));
218                 fileOptionsMIMETypeComboBox.setName("project-files.mime-type");
219                 fileOptionsMIMETypeComboBox.addActionListener(this);
220                 fileOptionsMIMETypeComboBox.setEnabled(false);
221
222                 final TLabel mimeTypeLabel = new TLabel(I18n.getMessage("jsite.project-files.mime-type") + ":", KeyEvent.VK_M, fileOptionsMIMETypeComboBox);
223                 fileOptionsPanel.add(mimeTypeLabel, 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(fileOptionsMIMETypeComboBox, new GridBagConstraints(1, 5, 4, 1, 1.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL, new Insets(6, 6, 0, 0), 0, 0));
225
226                 containerComboBoxModel = new DefaultComboBoxModel();
227                 fileOptionsContainerComboBox = new JComboBox(containerComboBoxModel);
228                 fileOptionsContainerComboBox.setToolTipText(I18n.getMessage("jsite.project-files.container.tooltip"));
229                 fileOptionsContainerComboBox.setName("project-files.container");
230                 fileOptionsContainerComboBox.addActionListener(this);
231                 fileOptionsContainerComboBox.setEnabled(false);
232
233                 final TLabel containerLabel = new TLabel(I18n.getMessage("jsite.project-files.container") + ":", KeyEvent.VK_C, fileOptionsContainerComboBox);
234                 fileOptionsPanel.add(containerLabel, new GridBagConstraints(0, 6, 1, 1, 0.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.NONE, new Insets(6, 18, 0, 0), 0, 0));
235                 fileOptionsPanel.add(fileOptionsContainerComboBox, new GridBagConstraints(1, 6, 1, 1, 1.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL, new Insets(6, 6, 0, 0), 0, 0));
236                 fileOptionsPanel.add(new JButton(addContainerAction), new GridBagConstraints(2, 6, 1, 1, 0.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL, new Insets(6, 6, 0, 0), 0, 0));
237                 fileOptionsPanel.add(new JButton(editContainerAction), new GridBagConstraints(3, 6, 1, 1, 0.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL, new Insets(6, 6, 0, 0), 0, 0));
238                 fileOptionsPanel.add(new JButton(deleteContainerAction), new GridBagConstraints(4, 6, 1, 1, 0.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL, new Insets(6, 6, 0, 0), 0, 0));
239
240                 JPanel fileOptionsReplacementPanel = new JPanel(new FlowLayout(FlowLayout.LEADING, 6, 6));
241                 fileOptionsReplacementPanel.setBorder(new EmptyBorder(-6, -6, -6, -6));
242
243                 replacementCheckBox = new JCheckBox(I18n.getMessage("jsite.project-files.replacement"));
244                 replacementCheckBox.setName("project-files.replace-edition");
245                 replacementCheckBox.setToolTipText(I18n.getMessage("jsite.project-files.replacement.tooltip"));
246                 replacementCheckBox.addActionListener(this);
247                 replacementCheckBox.setEnabled(false);
248                 fileOptionsReplacementPanel.add(replacementCheckBox);
249
250                 replaceEditionRangeSpinner = new JSpinner(new SpinnerNumberModel(0, 0, 99, 1));
251                 replaceEditionRangeSpinner.setName("project-files.replace-edition-range");
252                 replaceEditionRangeSpinner.setToolTipText(I18n.getMessage("jsite.project-files.replacement.edition-range.tooltip"));
253                 replaceEditionRangeSpinner.addChangeListener(this);
254                 replaceEditionRangeSpinner.setEnabled(false);
255                 final JLabel editionRangeLabel = new JLabel(I18n.getMessage("jsite.project-files.replacement.edition-range"));
256                 fileOptionsReplacementPanel.add(editionRangeLabel);
257                 fileOptionsReplacementPanel.add(replaceEditionRangeSpinner);
258
259                 fileOptionsPanel.add(fileOptionsReplacementPanel, new GridBagConstraints(0, 7, 5, 1, 1.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL, new Insets(6, 18, 0, 0), 0, 0));
260
261                 I18nContainer.getInstance().registerRunnable(new Runnable() {
262
263                         public void run() {
264                                 fileOptionsLabel.setText("<html><b>" + I18n.getMessage("jsite.project-files.file-options") + "</b></html>");
265                                 defaultFileCheckBox.setText(I18n.getMessage("jsite.project-files.default"));
266                                 defaultFileCheckBox.setToolTipText(I18n.getMessage("jsite.project-files.default.tooltip"));
267                                 fileOptionsInsertCheckBox.setText(I18n.getMessage("jsite.project-files.insert"));
268                                 fileOptionsInsertCheckBox.setToolTipText(I18n.getMessage("jsite.project-files.insert.tooltip"));
269                                 fileOptionsCustomKeyTextField.setToolTipText(I18n.getMessage("jsite.project-files.custom-key.tooltip"));
270                                 customKeyLabel.setText(I18n.getMessage("jsite.project-files.custom-key") + ":");
271                                 fileOptionsMIMETypeComboBox.setToolTipText(I18n.getMessage("jsite.project-files.mime-type.tooltip"));
272                                 mimeTypeLabel.setText(I18n.getMessage("jsite.project-files.mime-type") + ":");
273                                 fileOptionsContainerComboBox.setToolTipText(I18n.getMessage("jsite.project-files.container.tooltip"));
274                                 containerLabel.setText(I18n.getMessage("jsite.project-files.container") + ":");
275                                 replacementCheckBox.setText(I18n.getMessage("jsite.project-files.replacement"));
276                                 replacementCheckBox.setToolTipText(I18n.getMessage("jsite.project-files.replacement.tooltip"));
277                                 replaceEditionRangeSpinner.setToolTipText(I18n.getMessage("jsite.project-files.replacement.edition-range.tooltip"));
278                                 editionRangeLabel.setText(I18n.getMessage("jsite.project-files.replacement.edition-range"));
279                         }
280                 });
281
282                 return projectFilesPanel;
283         }
284
285         public void setProject(final Project project) {
286                 this.project = project;
287                 setHeading(MessageFormat.format(I18n.getMessage("jsite.project-files.heading"), project.getName()));
288                 setDescription(I18n.getMessage("jsite.project-files.description"));
289                 I18nContainer.getInstance().registerRunnable(new Runnable() {
290
291                         public void run() {
292                                 setHeading(MessageFormat.format(I18n.getMessage("jsite.project-files.heading"), project.getName()));
293                                 setDescription(I18n.getMessage("jsite.project-files.description"));
294                         }
295                 });
296         }
297
298         private List<String> getProjectFiles() {
299                 List<String> files = new ArrayList<String>();
300                 for (int index = 0, size = projectFileList.getModel().getSize(); index < size; index++) {
301                         files.add((String) projectFileList.getModel().getElementAt(index));
302                 }
303                 return files;
304         }
305
306         protected void rebuildContainerComboBox() {
307                 /* scan files for containers */
308                 List<String> files = getProjectFiles();
309                 List<String> containers = new ArrayList<String>(); // ComboBoxModel
310                 // sucks. No
311                 // contains()!
312                 containers.add("");
313                 for (String filename: files) {
314                         String container = project.getFileOption(filename).getContainer();
315                         if (!containers.contains(container)) {
316                                 containers.add(container);
317                         }
318                 }
319                 Collections.sort(containers);
320                 containerComboBoxModel.removeAllElements();
321                 for (String container: containers) {
322                         containerComboBoxModel.addElement(container);
323                 }
324         }
325
326         //
327         // ACTIONS
328         //
329
330         protected void actionScan() {
331                 projectFileList.clearSelection();
332                 projectFileList.setListData(new Object[0]);
333
334                 wizard.setNextEnabled(false);
335                 wizard.setPreviousEnabled(false);
336                 wizard.setQuitEnabled(false);
337
338                 FileScanner fileScanner = new FileScanner(project);
339                 fileScanner.addFileScannerListener(this);
340                 new Thread(fileScanner).start();
341         }
342
343         protected void actionAddContainer() {
344                 String containerName = JOptionPane.showInputDialog(wizard, I18n.getMessage("jsite.project-files.action.add-container.message") + ":", null, JOptionPane.INFORMATION_MESSAGE);
345                 if (containerName == null) {
346                         return;
347                 }
348                 containerName = containerName.trim();
349                 String filename = (String) projectFileList.getSelectedValue();
350                 FileOption fileOption = project.getFileOption(filename);
351                 fileOption.setContainer(containerName);
352                 rebuildContainerComboBox();
353                 fileOptionsContainerComboBox.setSelectedItem(containerName);
354         }
355
356         protected void actionEditContainer() {
357                 String selectedFilename = (String) projectFileList.getSelectedValue();
358                 FileOption fileOption = project.getFileOption(selectedFilename);
359                 String oldContainerName = fileOption.getContainer();
360                 String containerName = JOptionPane.showInputDialog(wizard, I18n.getMessage("jsite.project-files.action.edit-container.message") + ":", oldContainerName);
361                 if (containerName == null) {
362                         return;
363                 }
364                 if (containerName.equals("")) {
365                         fileOption.setContainer("");
366                         fileOptionsContainerComboBox.setSelectedItem("");
367                         return;
368                 }
369                 List<String> files = getProjectFiles();
370                 for (String filename: files) {
371                         fileOption = project.getFileOption(filename);
372                         if (fileOption.getContainer().equals(oldContainerName)) {
373                                 fileOption.setContainer(containerName);
374                         }
375                 }
376                 rebuildContainerComboBox();
377                 fileOptionsContainerComboBox.setSelectedItem(containerName);
378         }
379
380         protected void actionDeleteContainer() {
381                 if (JOptionPane.showConfirmDialog(wizard, I18n.getMessage("jsite.project-files.action.delete-container.message"), null, JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE) == JOptionPane.OK_OPTION) {
382                         String containerName = (String) fileOptionsContainerComboBox.getSelectedItem();
383                         List<String> files = getProjectFiles();
384                         for (String filename: files) {
385                                 FileOption fileOption = project.getFileOption(filename);
386                                 if (fileOption.getContainer().equals(containerName)) {
387                                         fileOption.setContainer("");
388                                 }
389                         }
390                         fileOptionsContainerComboBox.setSelectedItem("");
391                 }
392         }
393
394         public void fileScannerFinished(FileScanner fileScanner) {
395                 final boolean error = fileScanner.isError();
396                 if (!error) {
397                         final List<String> files = fileScanner.getFiles();
398                         SwingUtilities.invokeLater(new Runnable() {
399
400                                 public void run() {
401                                         projectFileList.setListData(files.toArray(new String[files.size()]));
402                                         projectFileList.clearSelection();
403                                         rebuildContainerComboBox();
404                                 }
405                         });
406                         Set<String> entriesToRemove = new HashSet<String>();
407                         Iterator<String> filenames = project.getFileOptions().keySet().iterator();
408                         while (filenames.hasNext()) {
409                                 String filename = filenames.next();
410                                 if (!files.contains(filename)) {
411                                         entriesToRemove.add(filename);
412                                 }
413                         }
414                         for (String filename: entriesToRemove) {
415                                 project.setFileOption(filename, null);
416                         }
417                 } else {
418                         JOptionPane.showMessageDialog(wizard, I18n.getMessage("jsite.project-files.scan-error"), null, JOptionPane.ERROR_MESSAGE);
419                 }
420                 SwingUtilities.invokeLater(new Runnable() {
421
422                         public void run() {
423                                 wizard.setPreviousEnabled(true);
424                                 wizard.setNextEnabled(!error);
425                                 wizard.setQuitEnabled(true);
426                         }
427                 });
428         }
429
430         //
431         // INTERFACE ActionListener
432         //
433
434         /**
435          * {@inheritDoc}
436          */
437         public void actionPerformed(ActionEvent actionEvent) {
438                 String filename = (String) projectFileList.getSelectedValue();
439                 if (filename == null) {
440                         return;
441                 }
442                 FileOption fileOption = project.getFileOption(filename);
443                 Object source = actionEvent.getSource();
444                 if (source instanceof JCheckBox) {
445                         JCheckBox checkBox = (JCheckBox) source;
446                         if ("default-file".equals(checkBox.getName())) {
447                                 if (checkBox.isSelected()) {
448                                         project.setIndexFile(filename);
449                                 } else {
450                                         project.setIndexFile(null);
451                                 }
452                         } else if ("insert".equals(checkBox.getName())) {
453                                 boolean isInsert = checkBox.isSelected();
454                                 fileOptionsCustomKeyTextField.setEnabled(!isInsert);
455                                 fileOption.setInsert(isInsert);
456                                 if (!isInsert) {
457                                         fileOptionsContainerComboBox.setSelectedItem("");
458                                 }
459                         } else if ("project-files.replace-edition".equals(checkBox.getName())) {
460                                 boolean replaceEdition = checkBox.isSelected();
461                                 fileOption.setReplaceEdition(replaceEdition);
462                                 replaceEditionRangeSpinner.setEnabled(replaceEdition);
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                         } else if ("project-files.container".equals(comboBox.getName())) {
469                                 String containerName = (String) comboBox.getSelectedItem();
470                                 fileOption.setContainer(containerName);
471                                 boolean enabled = !"".equals(containerName);
472                                 editContainerAction.setEnabled(enabled);
473                                 deleteContainerAction.setEnabled(enabled);
474                                 if (enabled) {
475                                         fileOptionsInsertCheckBox.setSelected(true);
476                                 }
477                         }
478                 }
479         }
480
481         //
482         // INTERFACE ListSelectionListener
483         //
484
485         /**
486          * {@inheritDoc}
487          */
488         public void valueChanged(ListSelectionEvent e) {
489                 String filename = (String) projectFileList.getSelectedValue();
490                 boolean enabled = filename != null;
491                 boolean insert = fileOptionsInsertCheckBox.isSelected();
492                 defaultFileCheckBox.setEnabled(enabled);
493                 fileOptionsInsertCheckBox.setEnabled(enabled);
494                 fileOptionsCustomKeyTextField.setEnabled(enabled && !insert);
495                 fileOptionsMIMETypeComboBox.setEnabled(enabled);
496                 fileOptionsContainerComboBox.setEnabled(enabled);
497                 addContainerAction.setEnabled(enabled);
498                 editContainerAction.setEnabled(enabled);
499                 deleteContainerAction.setEnabled(enabled);
500                 replacementCheckBox.setEnabled(enabled && insert);
501                 if (filename != null) {
502                         FileOption fileOption = project.getFileOption(filename);
503                         defaultFileCheckBox.setSelected(filename.equals(project.getIndexFile()));
504                         fileOptionsInsertCheckBox.setSelected(fileOption.isInsert());
505                         fileOptionsCustomKeyTextField.setText(fileOption.getCustomKey());
506                         fileOptionsMIMETypeComboBox.getModel().setSelectedItem(fileOption.getMimeType());
507                         fileOptionsContainerComboBox.setSelectedItem(fileOption.getContainer());
508                         replacementCheckBox.setSelected(fileOption.getReplaceEdition());
509                         replaceEditionRangeSpinner.setValue(fileOption.getEditionRange());
510                         replaceEditionRangeSpinner.setEnabled(fileOption.getReplaceEdition());
511                 } else {
512                         defaultFileCheckBox.setSelected(false);
513                         fileOptionsInsertCheckBox.setSelected(true);
514                         fileOptionsCustomKeyTextField.setText("CHK@");
515                         fileOptionsMIMETypeComboBox.getModel().setSelectedItem(DefaultMIMETypes.DEFAULT_MIME_TYPE);
516                         fileOptionsContainerComboBox.setSelectedItem("");
517                         replacementCheckBox.setSelected(false);
518                         replaceEditionRangeSpinner.setValue(0);
519                 }
520         }
521
522         //
523         // INTERFACE DocumentListener
524         //
525
526         private void processDocumentUpdate(DocumentEvent documentEvent) {
527                 String filename = (String) projectFileList.getSelectedValue();
528                 if (filename == null) {
529                         return;
530                 }
531                 FileOption fileOption = project.getFileOption(filename);
532                 Document document = documentEvent.getDocument();
533                 try {
534                         String text = document.getText(0, document.getLength());
535                         fileOption.setCustomKey(text);
536                 } catch (BadLocationException ble1) {
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         //
562         // INTERFACE ChangeListener
563         //
564
565         /**
566          * {@inheritDoc}
567          */
568         public void stateChanged(ChangeEvent changeEvent) {
569                 String filename = (String) projectFileList.getSelectedValue();
570                 if (filename == null) {
571                         return;
572                 }
573                 FileOption fileOption = project.getFileOption(filename);
574                 Object source = changeEvent.getSource();
575                 if (source instanceof JSpinner) {
576                         JSpinner spinner = (JSpinner) source;
577                         fileOption.setEditionRange((Integer) spinner.getValue());
578                 }
579         }
580
581 }