/* ViewerFileChooser.java created 2007-09-13 * */ package org.signalml.app.view.workspace; import static org.signalml.app.util.i18n.SvarogI18n._; import java.awt.Component; import java.awt.Dimension; import java.io.File; import java.util.Arrays; import java.util.regex.Pattern; import javax.swing.JFileChooser; import javax.swing.filechooser.FileFilter; import javax.swing.filechooser.FileNameExtensionFilter; import org.apache.log4j.Logger; import org.signalml.app.config.ApplicationConfiguration; import org.signalml.app.document.ManagedDocumentType; import org.signalml.app.document.TagDocument; import org.signalml.app.view.common.components.filechooser.EmbeddedFileChooserFavorites; import org.signalml.app.view.common.dialogs.OptionPane; import org.signalml.plugin.export.signal.Document; import org.signalml.util.Util; /** ViewerFileChooser * * Not thread safe! Use from event dispatcher thread only! * * @author Michał Dobaczewski © 2007-2008 CC Otwarte Systemy Komputerowe Sp. z o.o. * @author Zbigniew Jędrzejewski-Szmek © 2010 */ public class ViewerFileChooser extends JFileChooser implements org.signalml.plugin.export.view.FileChooser { private static final long serialVersionUID = 1L; protected static final Logger logger = Logger.getLogger(ViewerFileChooser.class); private ApplicationConfiguration applicationConfig; public ViewerFileChooser() { super(); this.setPreferredSize(new Dimension(500, 380)); } public void initialize() { FileNameExtensionFilter text = new FileNameExtensionFilter(_("Text files (*.txt)"), "txt"); FileNameExtensionFilter csv = new FileNameExtensionFilter(_("Comma-separated values (*.csv)"), "csv"); FileNameExtensionFilter binary = new FileNameExtensionFilter(_("Binary files (*.bin)"), "bin"); FileNameExtensionFilter ascii = new FileNameExtensionFilter(_("ASCII files (*.ascii)"), "ascii"); FileNameExtensionFilter eeglabDataset = new FileNameExtensionFilter(_("EEGLab datasets (*.set)"), "set"); FileNameExtensionFilter matlab = new FileNameExtensionFilter(_("MATLAB MAT-files (*.mat)"), "mat"); FileNameExtensionFilter xml = new FileNameExtensionFilter(_("XML files (*.xml)"), "xml"); FileNameExtensionFilter book = new FileNameExtensionFilter(_("Book files (*.b)"), "b"); FileNameExtensionFilter png = new FileNameExtensionFilter(_("PNG graphic files (*.png)"), "png"); FileNameExtensionFilter config = new FileNameExtensionFilter(_("Config files (*.cfg)"), "cfg"); FileNameExtensionFilter exe = new FileNameExtensionFilter(_("Executable files (*.exe)"), "exe"); FileNameExtensionFilter jar = new FileNameExtensionFilter(_("Jar files (*.jar)"), "jar"); FileNameExtensionFilter jar_class = new FileNameExtensionFilter(_("Code files (*.java, *.class)"), "java", "class"); OptionSet.consoleSaveAsText.setFilters(text); OptionSet.saveAsCSV.setFilters(csv); OptionSet.tableSaveAsText.setFilters(text); OptionSet.samplesSaveAsText.setFilters(text); OptionSet.samplesSaveAsFloat.setFilters(binary); OptionSet.chartSaveAsPng.setFilters(png); OptionSet.saveMP5Config.setFilters(config); OptionSet.saveMP5Signal.setFilters(binary); FileNameExtensionFilter managedTagFilters[] = ManagedDocumentType.TAG.getFileFilters(); OptionSet.saveTag.setFilters(managedTagFilters); OptionSet.openTag.setFilters(managedTagFilters); OptionSet.saveTag.setFilters(managedTagFilters); OptionSet.expertTag.setFilters(managedTagFilters); OptionSet.readXMLManifest.setFilters(xml); OptionSet.exportSignal.setFilters(binary); OptionSet.exportASCIISignal.setFilters(ascii); OptionSet.exportEEGLabSignal.setFilters(eeglabDataset); OptionSet.exportMatlabSignal.setFilters(matlab); OptionSet.exportBook.setFilters(book); OptionSet.openBook.setFilters(book); OptionSet.savePreset.setFilters(xml); OptionSet.loadPreset.setFilters(xml); if (Pattern.matches(".*[Ww]indows.*", System.getProperty("os.name"))) OptionSet.executablePreset.setFilters(exe); OptionSet.bookFilePreset.setFilters(book); OptionSet.bookSavePreset.setFilters(book); OptionSet.jarFilePreset.setFilters(jar); OptionSet.codeFilePreset.setFilters(jar_class); } protected synchronized int showDialog(Component parent, OptionSet options) { options.use(this); return showDialog(parent, options.buttonLabel); } public synchronized File chooseForReadOrWrite(Component parent, OptionSet options) { do { int result = showDialog(parent, options); if (result != APPROVE_OPTION) return null; File file = getSelectedFile(); boolean good = options.operation.verify(parent, file); if (!good) continue; file = options.fixExtensionIfNecessary(this, file); return file; } while (true); } public synchronized File[] chooseFilesOrDirectoriesForRead(Component parent, OptionSet options) { int result = showDialog(parent, options); if (result != APPROVE_OPTION) return null; File[] files = getSelectedFiles(); File[] okFiles = new File[files.length]; int cnt = 0; for (File file : files) { boolean good = options.operation.verify(parent, file); if (!good) continue; okFiles[cnt] = file; cnt++; } okFiles = Arrays.copyOf(okFiles, cnt); return okFiles; } public synchronized File chooseFile(Component parent, OptionSet optionset, File fileSuggestion) { String path = applicationConfig.getPath(optionset.path); if (path != null) setCurrentDirectory(new File(path)); if (fileSuggestion == null) setSelectedFile(new File("")); else setSelectedFile(fileSuggestion); File file = chooseForReadOrWrite(parent, optionset); if (file != null) { applicationConfig.setPath(optionset.path, getCurrentDirectory().getAbsolutePath()); if (file.exists() && getAccessory() != null) getAccessory().lastDirectoryChanged(file.getParent()); } return file; } public synchronized File chooseFile(Component parent, OptionSet optionset, File directory, File fileSuggestion) { return chooseFile(parent, optionset, fileSuggestion); } public synchronized File chooseFile(Component parent, OptionSet optionset) { return chooseFile(parent, optionset, null); } public synchronized File[] chooseFiles(Component parent, OptionSet options) { setSelectedFile(new File("")); String path = applicationConfig.getLastLibraryPath(); if (path != null) setCurrentDirectory(new File(path)); File[] files = chooseFilesOrDirectoriesForRead(parent, options); if (files != null) applicationConfig.setLastLibraryPath(getCurrentDirectory().getAbsolutePath()); return files; } public synchronized File chooseConsoleSaveAsTextFile(Component parent) { return chooseFile(parent, OptionSet.consoleSaveAsText); } public synchronized File chooseSaveAsCSVFile(Component parent) { return chooseFile(parent, OptionSet.saveAsCSV); } public synchronized File chooseTableSaveAsTextFile(Component parent) { return chooseFile(parent, OptionSet.tableSaveAsText); } public synchronized File chooseSamplesSaveAsTextFile(Component parent) { return chooseFile(parent, OptionSet.samplesSaveAsText); } public synchronized File chooseSamplesSaveAsFloatFile(Component parent) { return chooseFile(parent, OptionSet.samplesSaveAsFloat); } @Override public synchronized File chooseExportSignalFile(Component parent, File fileSuggestion) { return chooseFile(parent, OptionSet.exportSignal, fileSuggestion); } public synchronized File chooseExportASCIISignalFile(Component parent, File fileSuggestion) { return chooseFile(parent, OptionSet.exportASCIISignal, fileSuggestion); } public synchronized File chooseExportEEGLabSignalFile(Component parent, File fileSuggestion) { return chooseFile(parent, OptionSet.exportEEGLabSignal, fileSuggestion); } public synchronized File chooseExportMatlabSignalFile(Component parent, File fileSuggestion) { return chooseFile(parent, OptionSet.exportMatlabSignal, fileSuggestion); } public synchronized File chooseExportBookFile(Component parent, File fileSuggestion) { return chooseFile(parent, OptionSet.exportBook, fileSuggestion); } public synchronized File chooseChartSaveAsPngFile(Component parent) { return chooseFile(parent, OptionSet.chartSaveAsPng); } public synchronized File chooseSaveMP5ConfigFile(Component parent) { return chooseFile(parent, OptionSet.saveMP5Config); } public synchronized File chooseSaveMP5SignalFile(Component parent) { File selFile = getSelectedFile(); boolean resetDir = false; if (selFile == null || selFile.getName().isEmpty()) { String path = applicationConfig.getLastSaveMP5ConfigPath(); if (path != null) { setCurrentDirectory(new File(path)); resetDir = true; } } File file = chooseForReadOrWrite(parent, OptionSet.saveMP5Signal); if (file != null && resetDir) applicationConfig.setLastSaveMP5ConfigPath(getCurrentDirectory().getAbsolutePath()); return file; } public synchronized File chooseSaveDocument(Component parent, Document document, FileFilter[] filters) { // XXX: filters? if (document instanceof TagDocument) { return chooseSaveTag(parent); } return chooseFile(parent, OptionSet.saveDocument); } @Override public synchronized File chooseSaveTag(Component parent) { return chooseFile(parent, OptionSet.saveTag); } @Override public synchronized File chooseOpenTag(Component parent) { return chooseFile(parent, OptionSet.openTag); } @Override public synchronized File chooseExpertTag(Component parent) { return chooseFile(parent, OptionSet.expertTag); } @Override public synchronized File chooseImportTag(Component parent) { return chooseFile(parent, OptionSet.importTag); } @Override public synchronized File chooseExportTag(Component parent) { return chooseFile(parent, OptionSet.exportTag); } public synchronized File chooseOpenBook(Component parent) { return chooseFile(parent, OptionSet.openBook); } public synchronized File chooseReadXMLManifest(File directory, File fileSuggestion, Component parent) { return chooseFile(parent, OptionSet.readXMLManifest, fileSuggestion, directory); } @Override public synchronized File chooseSavePresetFile(Component parent) { return chooseFile(parent, OptionSet.savePreset); } @Override public synchronized File chooseLoadPresetFile(Component parent) { return chooseFile(parent, OptionSet.loadPreset); } public synchronized File chooseArtifactProjectDirectory(Component parent) { return chooseFile(parent, OptionSet.artifactProjectPreset); } @Override public synchronized File chooseExecutableFile(Component parent) { setSelectedFile(new File("")); setCurrentDirectory(new File(System.getProperty("user.dir"))); return chooseForReadOrWrite(parent, OptionSet.executablePreset); } @Override public synchronized File chooseBookFile(Component parent) { return chooseFile(parent, OptionSet.bookFilePreset); } public synchronized File chooseBookFileForWrite(Component parent) { return chooseFile(parent, OptionSet.bookSavePreset); } @Override public synchronized File chooseWorkingDirectory(Component parent, File currentDirectory) { boolean dirSet = false; if (currentDirectory != null) { if (currentDirectory.exists()) { setSelectedFile(currentDirectory); dirSet = true; } else { File parentDir = currentDirectory.getParentFile(); if (parentDir.exists()) { dirSet = true; setSelectedFile(new File("")); setCurrentDirectory(parentDir); } } } if (!dirSet) { setSelectedFile(new File("")); setCurrentDirectory(new File(System.getProperty("user.dir"))); } File file = chooseForReadOrWrite(parent, OptionSet.workingDirectoryPreset); return file; } @Override public synchronized File[] chooseClassPathDirectories(Component parent) { return chooseFiles(parent, OptionSet.classPathDirectoryPreset); } @Override public synchronized File[] chooseJarFiles(Component parent) { return chooseFiles(parent, OptionSet.classPathDirectoryPreset); } @Override public synchronized File chooseCodeFile(Component parent) { return chooseFile(parent, OptionSet.codeFilePreset); } public synchronized ApplicationConfiguration getApplicationConfig() { return applicationConfig; } protected synchronized void setApplicationConfig(ApplicationConfiguration applicationConfig) { this.applicationConfig = applicationConfig; EmbeddedFileChooserFavorites f = new EmbeddedFileChooserFavorites(this); this.setAccessory(f); } @Override public EmbeddedFileChooserFavorites getAccessory() { return (EmbeddedFileChooserFavorites) super.getAccessory(); } protected static abstract class Operation { public abstract boolean verify(Component parent, File file); public abstract File fixExtensionIfNecessary(JFileChooser fileChooser, File file); private static class Open extends Operation { @Override public boolean verify(Component parent, File file) { boolean good = file.exists() && file.canRead(); if (!good) OptionPane.showFileNotFound(parent, file); return good; } @Override public File fixExtensionIfNecessary(JFileChooser fileChooser, File file) { return file; } } private static class Save extends Operation { @Override public boolean verify(Component parent, File file) { File dir = file.getParentFile(); boolean good = dir != null && dir.exists() && dir.canRead() && dir.canWrite(); // XXX: when dir == null? if (!good) OptionPane.showDirectoryNotFound(parent, dir); return good; } @Override public File fixExtensionIfNecessary(JFileChooser fileChooser, File file) { FileFilter selectedFilter = fileChooser.getFileFilter(); if (Util.getFileExtension(file, false) != null) //the user added his own extension, let's stick to it. return file; if (selectedFilter instanceof FileNameExtensionFilter) { FileNameExtensionFilter filter = (FileNameExtensionFilter) selectedFilter; String extension = filter.getExtensions()[0]; return Util.changeOrAddFileExtension(file, extension); } return file; } } private static class Execute extends Operation { @Override public boolean verify(Component parent, File file) { boolean good = file.exists() && file.canRead() && file.canExecute(); if (!good) OptionPane.showFileNotFound(parent, file); return good; } @Override public File fixExtensionIfNecessary(JFileChooser fileChooser, File file) { return file; } } private static class UseDirectory extends Operation { @Override public boolean verify(Component parent, File file) { if (!file.exists()) { int ans = OptionPane.showDirectoryDoesntExistCreate(parent, file); if (ans != OptionPane.YES_OPTION) return false; boolean createOk = file.mkdirs(); if (!createOk) { OptionPane.showDirectoryNotCreated(parent, file); return false; } } boolean good = file.canRead() && file.canWrite(); if (!good) OptionPane.showDirectoryNotAccessible(parent, file); return good; } @Override public File fixExtensionIfNecessary(JFileChooser fileChooser, File file) { return file; } } static Operation open = new Open(), save = new Save(), execute = new Execute(), usedir = new UseDirectory(); } protected enum OptionSet { consoleSaveAsText(Operation.save, _("Choose text file to save"), null, _("Save")), saveAsCSV(Operation.save, _("Choose CSV file to save"), null, _("Save")), tableSaveAsText(Operation.save, _("Choose text file to save"), null, _("Save")), samplesSaveAsText(Operation.save, _("Choose text file to save"), null, _("Save")), samplesSaveAsFloat(Operation.save, _("Choose binary file to save"), null, _("Save")), chartSaveAsPng(Operation.save, _("Choose png file to save"), null, _("Save")), saveMP5Config(Operation.save, _("Choose MP5 config file to save"), null, _("Save")), saveMP5Signal(Operation.save, _("Choose MP5 signal file to save"), null, _("Save")), saveDocument(Operation.save, _("Save document"), null, _("Save")), saveTag(Operation.save, _("Save tag"), null, _("Save")), openTag(Operation.open, _("Open tag"), null, _("Open")), expertTag(Operation.open, _("Choose expert tag"), null, _("Choose")), importTag(Operation.open, _("Import legacy tag"), null, _("Import")), exportTag(Operation.save, _("Export legacy tag"), null, _("Export")), openBook(Operation.open, _("Choose a book file"), null, _("Choose")), savePreset(Operation.save, _("Save preset to file"), "LastPresetPath", _("Save")), loadPreset(Operation.open, _("Load preset from file"), "LastPresetPath", _("Load")), executablePreset(Operation.open, _("Choose executable"), null, _("Choose")), bookFilePreset(Operation.open, _("Choose a book file"), null, _("Choose")), bookSavePreset(Operation.save, _("Choose a book file"), null, _("Save")), artifactProjectPreset(Operation.usedir, "filechooser.artifactProjectPreset.title", null, _("Choose"), false, false, FILES_ONLY), exportSignal(Operation.save, _("Choose file to save to"), null, _("Export")), exportASCIISignal(Operation.save, _("Choose file to save to"), null, _("Export")), exportEEGLabSignal(Operation.save, _("Choose file to save to"), null, _("Export")), exportMatlabSignal(Operation.save, _("Choose file to save to"), null, _("Export")), exportBook(Operation.save, _("Export book"), null, _("Export")), readXMLManifest(Operation.open, _("Read XML manifest"), null, _("Read")), workingDirectoryPreset(Operation.usedir, _("Choose working directory"), null, _("Choose"), false, false, DIRECTORIES_ONLY), classPathDirectoryPreset(Operation.open, _("Choose class path directories"), null, _("Choose"), false, true, DIRECTORIES_ONLY), jarFilePreset(Operation.open, _("Choose jar files"), null, _("Choose"), true, true, FILES_ONLY), codeFilePreset(Operation.open, _("Choose code file"), "LastLibraryPath" /* sic */, _("Choose")); final Operation operation; final String title, buttonLabel; final String path; final boolean acceptAllUsed; final boolean multiSelectionEnabled; final int fileSelectionMode; private FileNameExtensionFilter[] fileFilters; private OptionSet(Operation operation, String title, String path, String buttonLabel, boolean acceptAllUsed, boolean multiSelectionEnabled, int fileSelectionMode) { this.operation = operation; this.title = title; this.buttonLabel = buttonLabel; this.path = path; this.acceptAllUsed = acceptAllUsed; this.multiSelectionEnabled = multiSelectionEnabled; this.fileSelectionMode = fileSelectionMode; logger.debug("added OptionSet \"" + title + "\" (" + operation.getClass().getSimpleName() + " \"" + buttonLabel + "\" / " + path + ")"); } /** * Changes the extension for a file to fit the selected filter. * Does so only for Save operations. * @param fileChooser * @param file */ public File fixExtensionIfNecessary(JFileChooser fileChooser, File file) { return operation.fixExtensionIfNecessary(fileChooser, file); } private OptionSet(Operation operation, String title, String path, String buttonLabel) { this(operation, title, path, buttonLabel, true, false, FILES_ONLY); } void use(ViewerFileChooser chooser) { chooser.setDialogTitle(this.title); chooser.setApproveButtonText(this.buttonLabel); chooser.setAcceptAllFileFilterUsed(this.acceptAllUsed); chooser.resetChoosableFileFilters(); chooser.setMultiSelectionEnabled(this.multiSelectionEnabled); chooser.setFileSelectionMode(this.fileSelectionMode); if (this.fileFilters != null) { for (int i=this.fileFilters.length-1; i>= 0; i--) chooser.addChoosableFileFilter(this.fileFilters[i]); if (fileFilters.length > 0) chooser.setFileFilter(fileFilters[0]); } } void setFilters(FileNameExtensionFilter ... fileFilters) { this.fileFilters = fileFilters; } } }