2 * jSite - ProjectFilesPage.java - Copyright © 2006–2014 David Roden
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.
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.
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.
19 package de.todesbaum.jsite.gui;
21 import static java.util.Optional.ofNullable;
23 import java.awt.BorderLayout;
24 import java.awt.Dimension;
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.awt.event.WindowAdapter;
32 import java.awt.event.WindowEvent;
33 import java.text.MessageFormat;
34 import java.util.Collection;
35 import java.util.HashSet;
36 import java.util.Iterator;
37 import java.util.Optional;
39 import java.util.function.Consumer;
40 import javax.swing.AbstractAction;
41 import javax.swing.Action;
42 import javax.swing.BorderFactory;
43 import javax.swing.JButton;
44 import javax.swing.JCheckBox;
45 import javax.swing.JComboBox;
46 import javax.swing.JComponent;
47 import javax.swing.JDialog;
48 import javax.swing.JLabel;
49 import javax.swing.JList;
50 import javax.swing.JOptionPane;
51 import javax.swing.JPanel;
52 import javax.swing.JProgressBar;
53 import javax.swing.JScrollPane;
54 import javax.swing.JTextField;
55 import javax.swing.ListSelectionModel;
56 import javax.swing.SwingConstants;
57 import javax.swing.SwingUtilities;
58 import javax.swing.WindowConstants;
59 import javax.swing.event.DocumentEvent;
60 import javax.swing.event.DocumentListener;
61 import javax.swing.event.ListSelectionEvent;
62 import javax.swing.event.ListSelectionListener;
63 import javax.swing.text.BadLocationException;
64 import javax.swing.text.Document;
65 import javax.swing.text.JTextComponent;
67 import net.pterodactylus.util.io.MimeTypes;
68 import net.pterodactylus.util.swing.SwingUtils;
69 import net.pterodactylus.util.thread.StoppableDelay;
71 import de.todesbaum.jsite.application.FileOption;
72 import de.todesbaum.jsite.application.Project;
73 import de.todesbaum.jsite.i18n.I18n;
74 import de.todesbaum.jsite.i18n.I18nContainer;
75 import de.todesbaum.util.swing.TLabel;
76 import de.todesbaum.util.swing.TWizard;
77 import de.todesbaum.util.swing.TWizardPage;
80 * Wizard page that lets the user manage the files of a project.
82 * @author David ‘Bombe’ Roden <bombe@freenetproject.org>
84 public class ProjectFilesPage extends TWizardPage implements ActionListener, ListSelectionListener, DocumentListener, FileScannerListener {
87 private Project project;
89 /** The “scan files” action. */
90 private Action scanAction;
92 /** The “always force insert” checkbox. */
93 private JCheckBox alwaysForceInsertCheckBox;
95 /** The “ignore hidden files” checkbox. */
96 private JCheckBox ignoreHiddenFilesCheckBox;
98 /** The list of project files. */
99 private JList projectFileList;
101 /** The “default file” checkbox. */
102 private JCheckBox defaultFileCheckBox;
104 /** The “insert” checkbox. */
105 private JCheckBox fileOptionsInsertCheckBox;
107 /** The “force insert” checkbox. */
108 private JCheckBox fileOptionsForceInsertCheckBox;
110 /** The “insert redirect” checkbox. */
111 private JCheckBox fileOptionsInsertRedirectCheckBox;
113 /** The “custom key” textfield. */
114 private JTextField fileOptionsCustomKeyTextField;
116 /** The “rename” check box. */
117 private JCheckBox fileOptionsRenameCheckBox;
119 /** The “new name” text field. */
120 private JTextField fileOptionsRenameTextField;
122 /** The “mime type” combo box. */
123 private JComboBox fileOptionsMIMETypeComboBox;
125 /** Delayed notification for file scanning. */
126 private StoppableDelay delayedNotification;
128 /** Dialog to display while scanning. */
129 private JDialog scanningFilesDialog;
131 /** The file scanner. */
132 private FileScanner fileScanner;
134 /** The progress bar. */
135 private JProgressBar progressBar;
138 * Creates a new project file page.
141 * The wizard the page belongs to
143 public ProjectFilesPage(final TWizard wizard) {
149 * Initializes the page and all its actions and components.
151 private void pageInit() {
153 setLayout(new BorderLayout(12, 12));
154 add(createProjectFilesPanel(), BorderLayout.CENTER);
158 * Creates all actions.
160 private void createActions() {
161 scanAction = new AbstractAction(I18n.getMessage("jsite.project-files.action.rescan")) {
164 @SuppressWarnings("synthetic-access")
165 public void actionPerformed(ActionEvent actionEvent) {
169 scanAction.putValue(Action.MNEMONIC_KEY, KeyEvent.VK_S);
170 scanAction.putValue(Action.SHORT_DESCRIPTION, I18n.getMessage("jsite.project-files.action.rescan.tooltip"));
172 I18nContainer.getInstance().registerRunnable(new Runnable() {
175 @SuppressWarnings("synthetic-access")
177 scanAction.putValue(Action.NAME, I18n.getMessage("jsite.project-files.action.rescan"));
178 scanAction.putValue(Action.SHORT_DESCRIPTION, I18n.getMessage("jsite.project-files.action.rescan.tooltip"));
187 public void pageAdded(TWizard wizard) {
188 /* create file scanner. */
189 fileScanner = new FileScanner(project, this);
192 this.wizard.setPreviousName(I18n.getMessage("jsite.wizard.previous"));
193 this.wizard.setNextName(I18n.getMessage("jsite.project-files.insert-now"));
194 this.wizard.setQuitName(I18n.getMessage("jsite.wizard.quit"));
198 * Creates the panel contains the project file list and options.
200 * @return The created panel
202 private JComponent createProjectFilesPanel() {
203 JPanel projectFilesPanel = new JPanel(new BorderLayout(12, 12));
205 projectFileList = new JList();
206 projectFileList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
207 projectFileList.setMinimumSize(new Dimension(250, projectFileList.getPreferredSize().height));
208 projectFileList.addListSelectionListener(this);
210 projectFilesPanel.add(new JScrollPane(projectFileList), BorderLayout.CENTER);
212 JPanel fileOptionsAlignmentPanel = new JPanel(new BorderLayout(12, 12));
213 projectFilesPanel.add(fileOptionsAlignmentPanel, BorderLayout.PAGE_END);
214 JPanel fileOptionsPanel = new JPanel(new GridBagLayout());
215 fileOptionsAlignmentPanel.add(fileOptionsPanel, BorderLayout.PAGE_START);
217 alwaysForceInsertCheckBox = new JCheckBox(I18n.getMessage("jsite.project-files.always-force-insert"));
218 alwaysForceInsertCheckBox.setToolTipText(I18n.getMessage("jsite.project-files.always-force-insert.tooltip"));
219 alwaysForceInsertCheckBox.setName("always-force-insert");
220 alwaysForceInsertCheckBox.addActionListener(this);
221 fileOptionsPanel.add(alwaysForceInsertCheckBox, new GridBagConstraints(0, 0, 5, 1, 1.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
223 ignoreHiddenFilesCheckBox = new JCheckBox(I18n.getMessage("jsite.project-files.ignore-hidden-files"));
224 ignoreHiddenFilesCheckBox.setToolTipText(I18n.getMessage("jsite.project-files.ignore-hidden-files.tooltip"));
225 ignoreHiddenFilesCheckBox.setName("ignore-hidden-files");
226 ignoreHiddenFilesCheckBox.addActionListener(this);
227 fileOptionsPanel.add(ignoreHiddenFilesCheckBox, new GridBagConstraints(0, 1, 5, 1, 1.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
229 fileOptionsPanel.add(new JButton(scanAction), new GridBagConstraints(0, 2, 5, 1, 1.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.NONE, new Insets(6, 0, 0, 0), 0, 0));
231 final JLabel fileOptionsLabel = new JLabel("<html><b>" + I18n.getMessage("jsite.project-files.file-options") + "</b></html>");
232 fileOptionsPanel.add(fileOptionsLabel, new GridBagConstraints(0, 3, 5, 1, 1.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.NONE, new Insets(6, 0, 0, 0), 0, 0));
234 defaultFileCheckBox = new JCheckBox(I18n.getMessage("jsite.project-files.default"));
235 defaultFileCheckBox.setToolTipText(I18n.getMessage("jsite.project-files.default.tooltip"));
236 defaultFileCheckBox.setName("default-file");
237 defaultFileCheckBox.addActionListener(this);
238 defaultFileCheckBox.setEnabled(false);
240 fileOptionsPanel.add(defaultFileCheckBox, new GridBagConstraints(0, 4, 5, 1, 0.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL, new Insets(6, 18, 0, 0), 0, 0));
242 fileOptionsInsertCheckBox = new JCheckBox(I18n.getMessage("jsite.project-files.insert"), true);
243 fileOptionsInsertCheckBox.setToolTipText(I18n.getMessage("jsite.project-files.insert.tooltip"));
244 fileOptionsInsertCheckBox.setName("insert");
245 fileOptionsInsertCheckBox.setMnemonic(KeyEvent.VK_I);
246 fileOptionsInsertCheckBox.addActionListener(this);
247 fileOptionsInsertCheckBox.setEnabled(false);
249 fileOptionsPanel.add(fileOptionsInsertCheckBox, new GridBagConstraints(0, 5, 5, 1, 0.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.NONE, new Insets(6, 18, 0, 0), 0, 0));
251 fileOptionsForceInsertCheckBox = new JCheckBox(I18n.getMessage("jsite.project-files.force-insert"));
252 fileOptionsForceInsertCheckBox.setToolTipText(I18n.getMessage("jsite.project-files.force-insert.tooltip"));
253 fileOptionsForceInsertCheckBox.setName("force-insert");
254 fileOptionsForceInsertCheckBox.setMnemonic(KeyEvent.VK_F);
255 fileOptionsForceInsertCheckBox.addActionListener(this);
256 fileOptionsForceInsertCheckBox.setEnabled(false);
258 fileOptionsPanel.add(fileOptionsForceInsertCheckBox, new GridBagConstraints(0, 6, 5, 1, 0.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.NONE, new Insets(6, 18, 0, 0), 0, 0));
260 fileOptionsCustomKeyTextField = new JTextField(45);
261 fileOptionsCustomKeyTextField.setToolTipText(I18n.getMessage("jsite.project-files.custom-key.tooltip"));
262 fileOptionsCustomKeyTextField.setEnabled(false);
263 fileOptionsCustomKeyTextField.getDocument().addDocumentListener(this);
265 fileOptionsInsertRedirectCheckBox = new JCheckBox(I18n.getMessage("jsite.project-files.insert-redirect"), false);
266 fileOptionsInsertRedirectCheckBox.setToolTipText(I18n.getMessage("jsite.project-files.insert-redirect.tooltip"));
267 fileOptionsInsertRedirectCheckBox.setName("insert-redirect");
268 fileOptionsInsertRedirectCheckBox.setMnemonic(KeyEvent.VK_R);
269 fileOptionsInsertRedirectCheckBox.addActionListener(this);
270 fileOptionsInsertRedirectCheckBox.setEnabled(false);
272 final TLabel customKeyLabel = new TLabel(I18n.getMessage("jsite.project-files.custom-key") + ":", KeyEvent.VK_K, fileOptionsCustomKeyTextField);
273 fileOptionsPanel.add(fileOptionsInsertRedirectCheckBox, new GridBagConstraints(0, 7, 1, 1, 0.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.NONE, new Insets(6, 18, 0, 0), 0, 0));
274 fileOptionsPanel.add(customKeyLabel, new GridBagConstraints(1, 7, 1, 1, 0.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.NONE, new Insets(6, 6, 0, 0), 0, 0));
275 fileOptionsPanel.add(fileOptionsCustomKeyTextField, new GridBagConstraints(2, 7, 3, 1, 1.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL, new Insets(6, 6, 0, 0), 0, 0));
277 fileOptionsRenameCheckBox = new JCheckBox(I18n.getMessage("jsite.project-files.rename"), false);
278 fileOptionsRenameCheckBox.setToolTipText(I18n.getMessage("jsite.project-files.rename.tooltip"));
279 fileOptionsRenameCheckBox.setName("rename");
280 fileOptionsRenameCheckBox.setMnemonic(KeyEvent.VK_N);
281 fileOptionsRenameCheckBox.addActionListener(this);
282 fileOptionsRenameCheckBox.setEnabled(false);
284 fileOptionsRenameTextField = new JTextField();
285 fileOptionsRenameTextField.setEnabled(false);
286 fileOptionsRenameTextField.getDocument().addDocumentListener(new StoreDocument(this::updateChangedName));
288 fileOptionsPanel.add(fileOptionsRenameCheckBox, new GridBagConstraints(0, 8, 2, 1, 0.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.NONE, new Insets(6, 18, 0, 0), 0, 0));
289 fileOptionsPanel.add(fileOptionsRenameTextField, new GridBagConstraints(2, 8, 3, 1, 1.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL, new Insets(6, 6, 0, 0), 0, 0));
291 fileOptionsMIMETypeComboBox = new JComboBox(MimeTypes.getAllMimeTypes().toArray());
292 fileOptionsMIMETypeComboBox.setToolTipText(I18n.getMessage("jsite.project-files.mime-type.tooltip"));
293 fileOptionsMIMETypeComboBox.setName("project-files.mime-type");
294 fileOptionsMIMETypeComboBox.addActionListener(this);
295 fileOptionsMIMETypeComboBox.setEditable(true);
296 fileOptionsMIMETypeComboBox.setEnabled(false);
297 ((JTextComponent) fileOptionsMIMETypeComboBox.getEditor().getEditorComponent())
299 .addDocumentListener(new StoreDocument(this::updateMimeType));
301 final TLabel mimeTypeLabel = new TLabel(I18n.getMessage("jsite.project-files.mime-type") + ":", KeyEvent.VK_M, fileOptionsMIMETypeComboBox);
302 fileOptionsPanel.add(mimeTypeLabel, new GridBagConstraints(0, 9, 1, 1, 0.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.NONE, new Insets(6, 18, 0, 0), 0, 0));
303 fileOptionsPanel.add(fileOptionsMIMETypeComboBox, new GridBagConstraints(1, 9, 4, 1, 1.0, 0.0, GridBagConstraints.LINE_START, GridBagConstraints.HORIZONTAL, new Insets(6, 6, 0, 0), 0, 0));
305 /* create dialog to show while scanning. */
306 scanningFilesDialog = new JDialog(wizard);
307 scanningFilesDialog.setModal(true);
308 scanningFilesDialog.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
310 JPanel progressPanel = new JPanel(new BorderLayout(12, 12));
311 scanningFilesDialog.getContentPane().add(progressPanel, BorderLayout.CENTER);
312 progressPanel.setBorder(BorderFactory.createEmptyBorder(12, 12, 12, 12));
314 final JLabel scanningLabel = new JLabel(I18n.getMessage("jsite.project-files.scanning"), SwingConstants.CENTER);
315 progressPanel.add(scanningLabel, BorderLayout.NORTH);
316 progressBar = new JProgressBar(SwingConstants.HORIZONTAL);
317 progressPanel.add(progressBar, BorderLayout.SOUTH);
318 progressBar.setIndeterminate(true);
319 progressBar.setStringPainted(true);
320 progressBar.setPreferredSize(new Dimension(progressBar.getPreferredSize().width * 2, progressBar.getPreferredSize().height));
322 scanningFilesDialog.pack();
323 scanningFilesDialog.addWindowListener(new WindowAdapter() {
329 @SuppressWarnings("synthetic-access")
330 public void windowOpened(WindowEvent e) {
331 SwingUtils.center(scanningFilesDialog, wizard);
335 I18nContainer.getInstance().registerRunnable(new Runnable() {
338 @SuppressWarnings("synthetic-access")
340 alwaysForceInsertCheckBox.setText(I18n.getMessage("jsite.project-files.always-force-insert"));
341 alwaysForceInsertCheckBox.setToolTipText(I18n.getMessage("jsite.project-files.always-force-insert.tooltip"));
342 ignoreHiddenFilesCheckBox.setText(I18n.getMessage("jsite.project-files.ignore-hidden-files"));
343 ignoreHiddenFilesCheckBox.setToolTipText(I18n.getMessage("jsite.projet-files.ignore-hidden-files.tooltip"));
344 fileOptionsLabel.setText("<html><b>" + I18n.getMessage("jsite.project-files.file-options") + "</b></html>");
345 defaultFileCheckBox.setText(I18n.getMessage("jsite.project-files.default"));
346 defaultFileCheckBox.setToolTipText(I18n.getMessage("jsite.project-files.default.tooltip"));
347 fileOptionsInsertCheckBox.setText(I18n.getMessage("jsite.project-files.insert"));
348 fileOptionsInsertCheckBox.setToolTipText(I18n.getMessage("jsite.project-files.insert.tooltip"));
349 fileOptionsForceInsertCheckBox.setText(I18n.getMessage("jsite.project-files.force-insert"));
350 fileOptionsForceInsertCheckBox.setToolTipText(I18n.getMessage("jsite.project-files.force-insert.tooltip"));
351 fileOptionsInsertRedirectCheckBox.setText(I18n.getMessage("jsite.project-files.insert-redirect"));
352 fileOptionsInsertRedirectCheckBox.setToolTipText(I18n.getMessage("jsite.project-files.insert-redirect.tooltip"));
353 fileOptionsCustomKeyTextField.setToolTipText(I18n.getMessage("jsite.project-files.custom-key.tooltip"));
354 customKeyLabel.setText(I18n.getMessage("jsite.project-files.custom-key") + ":");
355 fileOptionsRenameCheckBox.setText("jsite.project-files.rename");
356 fileOptionsRenameCheckBox.setToolTipText("jsite.project-files.rename.tooltip");
357 fileOptionsMIMETypeComboBox.setToolTipText(I18n.getMessage("jsite.project-files.mime-type.tooltip"));
358 mimeTypeLabel.setText(I18n.getMessage("jsite.project-files.mime-type") + ":");
359 scanningLabel.setText(I18n.getMessage("jsite.project-files.scanning"));
363 return projectFilesPanel;
367 * Sets the project whose files to manage.
370 * The project whose files to manage
372 public void setProject(final Project project) {
373 this.project = project;
374 setHeading(MessageFormat.format(I18n.getMessage("jsite.project-files.heading"), project.getName()));
375 setDescription(I18n.getMessage("jsite.project-files.description"));
376 ignoreHiddenFilesCheckBox.setSelected(project.isIgnoreHiddenFiles());
377 alwaysForceInsertCheckBox.setSelected(project.isAlwaysForceInsert());
378 I18nContainer.getInstance().registerRunnable(new Runnable() {
382 setHeading(MessageFormat.format(I18n.getMessage("jsite.project-files.heading"), project.getName()));
383 setDescription(I18n.getMessage("jsite.project-files.description"));
393 * Rescans the project’s files.
395 private void actionScan() {
396 projectFileList.clearSelection();
397 projectFileList.setListData(new Object[0]);
399 wizard.setNextEnabled(false);
400 wizard.setPreviousEnabled(false);
401 wizard.setQuitEnabled(false);
403 ignoreHiddenFilesCheckBox.setEnabled(false);
404 scanAction.setEnabled(false);
406 delayedNotification = new StoppableDelay(new Runnable() {
409 @SuppressWarnings("synthetic-access")
411 scanningFilesDialog.setVisible(true);
416 @SuppressWarnings("synthetic-access")
418 scanningFilesDialog.setVisible(false);
421 fileScanner.startInBackground();
422 new Thread(delayedNotification).start();
423 new Thread(new Runnable() {
426 @SuppressWarnings("synthetic-access")
428 while (!delayedNotification.isFinished()) {
431 } catch (InterruptedException ie1) {
434 progressBar.setString(fileScanner.getLastFilename());
443 * Updates the file list.
446 public void fileScannerFinished(boolean error, Collection<ScannedFile> files) {
447 delayedNotification.finish();
449 SwingUtilities.invokeLater(new Runnable() {
452 @SuppressWarnings("synthetic-access")
454 projectFileList.setListData(files.toArray());
455 projectFileList.clearSelection();
458 Set<String> entriesToRemove = new HashSet<String>();
459 Iterator<String> filenames = new HashSet<String>(project.getFileOptions().keySet()).iterator();
460 while (filenames.hasNext()) {
461 String filename = filenames.next();
462 boolean found = false;
463 for (ScannedFile scannedFile : files) {
464 if (scannedFile.getFilename().equals(filename)) {
470 entriesToRemove.add(filename);
473 for (String filename : entriesToRemove) {
474 project.setFileOption(filename, null);
477 JOptionPane.showMessageDialog(wizard, I18n.getMessage("jsite.project-files.scan-error"), null, JOptionPane.ERROR_MESSAGE);
479 SwingUtilities.invokeLater(new Runnable() {
482 @SuppressWarnings("synthetic-access")
484 wizard.setPreviousEnabled(true);
485 wizard.setNextEnabled(!error);
486 wizard.setQuitEnabled(true);
487 ignoreHiddenFilesCheckBox.setEnabled(true);
488 scanAction.setEnabled(true);
493 private Optional<FileOption> getSelectedFile() {
494 return ofNullable(((ScannedFile) projectFileList.getSelectedValue()))
495 .map(scannedFile -> project.getFileOption(scannedFile.getFilename()));
499 // INTERFACE ActionListener
506 public void actionPerformed(ActionEvent actionEvent) {
507 Object source = actionEvent.getSource();
508 if (source instanceof JCheckBox) {
509 String checkboxName = ((JCheckBox) source).getName();
510 if ("ignore-hidden-files".equals(checkboxName)) {
511 project.setIgnoreHiddenFiles(((JCheckBox) source).isSelected());
514 } else if ("always-force-insert".equals(checkboxName)) {
515 project.setAlwaysForceInsert(((JCheckBox) source).isSelected());
520 ScannedFile scannedFile = (ScannedFile) projectFileList.getSelectedValue();
521 if (scannedFile == null) {
524 String filename = scannedFile.getFilename();
525 FileOption fileOption = project.getFileOption(filename);
526 if (source instanceof JCheckBox) {
527 JCheckBox checkBox = (JCheckBox) source;
528 if ("default-file".equals(checkBox.getName())) {
529 if (checkBox.isSelected()) {
530 if (filename.indexOf('/') > -1) {
531 JOptionPane.showMessageDialog(wizard, I18n.getMessage("jsite.project-files.invalid-default-file"), null, JOptionPane.ERROR_MESSAGE);
532 checkBox.setSelected(false);
534 project.setIndexFile(filename);
537 if (filename.equals(project.getIndexFile())) {
538 project.setIndexFile(null);
541 } else if ("insert".equals(checkBox.getName())) {
542 boolean isInsert = checkBox.isSelected();
543 fileOption.setInsert(isInsert);
544 fileOptionsInsertRedirectCheckBox.setEnabled(!isInsert);
545 } else if ("force-insert".equals(checkBox.getName())) {
546 boolean isForceInsert = checkBox.isSelected();
547 fileOption.setForceInsert(isForceInsert);
548 } else if ("insert-redirect".equals(checkBox.getName())) {
549 boolean isInsertRedirect = checkBox.isSelected();
550 fileOption.setInsertRedirect(isInsertRedirect);
551 fileOptionsCustomKeyTextField.setEnabled(isInsertRedirect);
552 } else if ("rename".equals(checkBox.getName())) {
553 boolean isRenamed = checkBox.isSelected();
554 fileOptionsRenameTextField.setEnabled(isRenamed);
555 fileOption.setChangedName(isRenamed ? fileOptionsRenameTextField.getText() : "");
557 } else if (source instanceof JComboBox) {
558 JComboBox comboBox = (JComboBox) source;
559 if ("project-files.mime-type".equals(comboBox.getName())) {
560 updateMimeType((String) comboBox.getSelectedItem());
565 private void updateMimeType(String mimeType) {
566 getSelectedFile().ifPresent(fileOption -> fileOption.setMimeType(mimeType));
569 private void updateChangedName(String changedName) {
570 getSelectedFile().ifPresent(fileOption -> fileOption.setChangedName(changedName));
574 // INTERFACE ListSelectionListener
581 @SuppressWarnings("null")
582 public void valueChanged(ListSelectionEvent e) {
583 ScannedFile scannedFile = (ScannedFile) projectFileList.getSelectedValue();
584 boolean enabled = scannedFile != null;
585 String filename = (scannedFile == null) ? null : scannedFile.getFilename();
586 defaultFileCheckBox.setEnabled(enabled);
587 fileOptionsInsertCheckBox.setEnabled(enabled);
588 fileOptionsRenameCheckBox.setEnabled(enabled);
589 fileOptionsMIMETypeComboBox.setEnabled(enabled);
590 if (filename != null) {
591 FileOption fileOption = project.getFileOption(filename);
592 defaultFileCheckBox.setSelected(filename.equals(project.getIndexFile()));
593 fileOptionsInsertCheckBox.setSelected(fileOption.isInsert());
594 fileOptionsForceInsertCheckBox.setEnabled(!project.isAlwaysForceInsert() && scannedFile.getHash().equals(fileOption.getLastInsertHash()));
595 fileOptionsForceInsertCheckBox.setSelected(fileOption.isForceInsert());
596 fileOptionsInsertRedirectCheckBox.setEnabled(!fileOption.isInsert());
597 fileOptionsInsertRedirectCheckBox.setSelected(fileOption.isInsertRedirect());
598 fileOptionsCustomKeyTextField.setEnabled(fileOption.isInsertRedirect());
599 fileOptionsCustomKeyTextField.setText(fileOption.getCustomKey());
600 fileOptionsRenameCheckBox.setSelected(fileOption.getChangedName().isPresent());
601 fileOptionsRenameTextField.setEnabled(fileOption.getChangedName().isPresent());
602 fileOptionsRenameTextField.setText(fileOption.getChangedName().orElse(""));
603 fileOptionsMIMETypeComboBox.getModel().setSelectedItem(fileOption.getMimeType());
605 defaultFileCheckBox.setSelected(false);
606 fileOptionsInsertCheckBox.setSelected(true);
607 fileOptionsForceInsertCheckBox.setEnabled(false);
608 fileOptionsForceInsertCheckBox.setSelected(false);
609 fileOptionsInsertRedirectCheckBox.setEnabled(false);
610 fileOptionsInsertRedirectCheckBox.setSelected(false);
611 fileOptionsCustomKeyTextField.setEnabled(false);
612 fileOptionsCustomKeyTextField.setText("CHK@");
613 fileOptionsRenameCheckBox.setEnabled(false);
614 fileOptionsRenameCheckBox.setSelected(false);
615 fileOptionsRenameTextField.setEnabled(false);
616 fileOptionsRenameTextField.setText("");
617 fileOptionsMIMETypeComboBox.getModel().setSelectedItem(MimeTypes.DEFAULT_CONTENT_TYPE);
622 // INTERFACE DocumentListener
626 * Updates the options of the currently selected file with the changes made
627 * in the “custom key” textfield.
629 * @param documentEvent
630 * The document event to process
632 private void processDocumentUpdate(DocumentEvent documentEvent) {
633 ScannedFile scannedFile = (ScannedFile) projectFileList.getSelectedValue();
634 if (scannedFile == null) {
637 FileOption fileOption = project.getFileOption(scannedFile.getFilename());
638 Document document = documentEvent.getDocument();
640 String text = document.getText(0, document.getLength());
641 fileOption.setCustomKey(text);
642 } catch (BadLocationException ble1) {
651 public void changedUpdate(DocumentEvent documentEvent) {
652 processDocumentUpdate(documentEvent);
659 public void insertUpdate(DocumentEvent documentEvent) {
660 processDocumentUpdate(documentEvent);
667 public void removeUpdate(DocumentEvent documentEvent) {
668 processDocumentUpdate(documentEvent);
671 private static class StoreDocument implements DocumentListener {
673 private final Consumer<String> consumer;
675 public StoreDocument(Consumer<String> consumer) {
676 this.consumer = consumer;
679 private void storeDocument(DocumentEvent e) {
681 consumer.accept(e.getDocument().getText(0, e.getDocument().getLength()));
682 } catch (BadLocationException e1) {
683 e1.printStackTrace();
688 public void insertUpdate(DocumentEvent e) {
693 public void removeUpdate(DocumentEvent e) {
698 public void changedUpdate(DocumentEvent e) {