/* * Copyright 2011 Christian Thiemann <christian@spato.net> * Developed at Northwestern University <http://rocs.northwestern.edu> * * This file is part of the SPaTo Visual Explorer (SPaTo). * * SPaTo is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * SPaTo is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with SPaTo. If not, see <http://www.gnu.org/licenses/>. */ package net.spato.sve.app.util; import java.awt.FileDialog; import java.io.File; import java.io.FilenameFilter; import javax.swing.JFileChooser; import javax.swing.SwingUtilities; import javax.swing.filechooser.FileFilter; import processing.core.PApplet; import net.spato.sve.app.SPaTo_Visual_Explorer; public class FileDialogUtils { public static FileFilter createFileFilter(final String ext, final String desc) { return createFileFilter(new String[] { ext }, desc); } public static FileFilter createFileFilter(final String exts[], final String desc) { return new FileFilter() { public String getDescription() { return desc; } public boolean accept(File f) { if (f.isDirectory()) return false; for (String ext : exts) if (f.getName().endsWith("." + ext)) return true; return false; } }; } // Yeah, nice... JFileChooser uses a different way of filtering files (FileFilter) than FileDialog (FilenameFilter). // This class acts as a FilenameFilter, but with a FileFilter the decision-making backend. public static class FilenameFileFilterAdapter implements FilenameFilter { private FileFilter ff = null; public FilenameFileFilterAdapter(FileFilter ff) { this.ff = ff; } public boolean accept(File dir, String name) { return ff.accept(new File(dir, name)); } } // And also nice: JFileChooser on Windows does not display directories at all if they are rejected by // the FileFilter, which means you cannot change into them, which means you most probably cannot reach // any of the files of interest. So, this class accepts all directories before asking the real filter. // The selectFiles method will sort out selected, non-acceptable directories afterwards. public static class WindowsFileFilterAdapter extends FileFilter { private FileFilter ff = null; public WindowsFileFilterAdapter(FileFilter ff) { this.ff = ff; } public String getDescription() { return ff.getDescription(); } public boolean accept(File f) { return f.isDirectory() ? true : ff.accept(f); } } public static File ensureExtension(String ext, File file) { if ((ext == null) || (file == null)) return null; return file.getName().endsWith("." + ext) ? file : new File(file.getAbsolutePath() + "." + ext); } public static final int OPEN = 0; public static final int OPENMULTIPLE = 1; public static final int SAVE = 2; public static File selectFile(SPaTo_Visual_Explorer app, int mode) { return selectFile(app, mode, null, null, null); } public static File selectFile(SPaTo_Visual_Explorer app, int mode, String title) { return selectFile(app, mode, title, null, null); } public static File selectFile(SPaTo_Visual_Explorer app, int mode, String title, FileFilter ff) { return selectFile(app, mode, title, ff, null); } public static File selectFile(SPaTo_Visual_Explorer app, int mode, String title, FileFilter ff, File selectedFile) { File res[] = selectFiles(app, mode, title, ff, selectedFile); return ((res != null) && (res.length > 0)) ? res[0] : null; } private static File selectFilesResult[]; // FIXME: there must be a better way than using this static variable public static File[] selectFiles(SPaTo_Visual_Explorer app, int mode) { return selectFiles(app, mode, null, null, null); } public static File[] selectFiles(SPaTo_Visual_Explorer app, int mode, String title) { return selectFiles(app, mode, title, null, null); } public static File[] selectFiles(SPaTo_Visual_Explorer app, int mode, String title, FileFilter ff) { return selectFiles(app, mode, title, ff, null); } public static File[] selectFiles(final SPaTo_Visual_Explorer app, final int mode, final String title, final FileFilter ff, final File selectedFile) { try { selectFilesResult = null; SwingUtilities.invokeAndWait(new Runnable() { public void run() { File lastDir = new File(app.prefs.get("workspace.lastDirectory", "")); if (lastDir.getAbsolutePath().equals("")) lastDir = null; if (app.platform == PApplet.MACOSX) { // use FileDialog instead of JFileChooser as per Apple recommendation FileDialog fd = new FileDialog(app.getParentFrame(), (title != null) ? title : (mode == SAVE) ? "Save..." : "Open...", (mode == SAVE) ? FileDialog.SAVE : FileDialog.LOAD); fd.setFilenameFilter(new FilenameFileFilterAdapter(ff)); String dirname = null; if (selectedFile != null) dirname = selectedFile.getParent(); else if (lastDir != null) dirname = lastDir.getAbsolutePath(); fd.setDirectory(dirname); fd.setFile((selectedFile != null) ? selectedFile.getAbsolutePath() : null); fd.setVisible(true); selectFilesResult = new File[0]; if ((fd.getFile() != null) && ((mode == SAVE) || ff.accept(new File(fd.getDirectory(), fd.getFile())))) selectFilesResult = new File[] { new File(fd.getDirectory(), fd.getFile()) }; } else { JFileChooser fc = new JFileChooser(); // set initial directory and possibly initially selected file fc.setCurrentDirectory((selectedFile != null) ? selectedFile.getParentFile() : lastDir); if (selectedFile != null) fc.setSelectedFile(selectedFile); // setup dialog look and feel fc.setDialogTitle((title != null) ? title : (mode == SAVE) ? "Save..." : "Open..."); fc.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); fc.setMultiSelectionEnabled(mode == OPENMULTIPLE); // allow selecting multiple documents to load fc.setAcceptAllFileFilterUsed(ff == null); if (ff != null) fc.setFileFilter((app.platform == PApplet.WINDOWS) ? new WindowsFileFilterAdapter(ff) : ff); // run dialog if (fc.showDialog(app.getParentFrame(), (mode == SAVE) ? "Save" : "Open") == JFileChooser.APPROVE_OPTION) { // save current directory to preferences File dir = fc.getCurrentDirectory(); app.prefs.put("workspace.lastDirectory", (dir != null) ? dir.getAbsolutePath() : null); // evaluate selection File files[] = fc.isMultiSelectionEnabled() ? fc.getSelectedFiles() : new File[] { fc.getSelectedFile() }; if (mode != SAVE) for (int i = 0; i < files.length; i++) if ((ff != null) && !ff.accept(files[i])) files[i] = null; // transcribe selection into result array selectFilesResult = new File[0]; for (int i = 0; i < files.length; i++) if (files[i] != null) selectFilesResult = (File[])PApplet.append(selectFilesResult, files[i]); } } } }); return selectFilesResult; } catch (Exception e) { app.console.logError("Something went wrong: ", e); e.printStackTrace(); return null; } } public static File selectDirectory(SPaTo_Visual_Explorer app) { return selectDirectory(app, null, null); } public static File selectDirectory(SPaTo_Visual_Explorer app, String title) { return selectDirectory(app, title, null); } public static File selectDirectory(SPaTo_Visual_Explorer app, File selected) { return selectDirectory(app, null, selected); } public static File selectDirectory(final SPaTo_Visual_Explorer app, final String title, final File selected) { try { selectFilesResult = new File[1]; SwingUtilities.invokeAndWait(new Runnable() { public void run() { if (app.platform == PApplet.MACOSX) { // use FileDialog instead of JFileChooser as per Apple recommendation System.setProperty("apple.awt.fileDialogForDirectories", "true"); FileDialog fd = new FileDialog(app.getParentFrame(), (title != null) ? title : "Select directory"); if (selected != null) fd.setDirectory(selected.getAbsolutePath()); fd.setVisible(true); selectFilesResult[0] = new File(fd.getDirectory(), fd.getFile()); System.setProperty("apple.awt.fileDialogForDirectories", "false"); } else { JFileChooser fc = new JFileChooser(); fc.setDialogTitle((title != null) ? title : "Select directory"); fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); if (selected != null) fc.setSelectedFile(selected); if (fc.showDialog(app.getParentFrame(), "Select") == JFileChooser.APPROVE_OPTION) selectFilesResult[0] = fc.getSelectedFile(); } } }); return selectFilesResult[0]; } catch (Exception e) { app.console.logError("Something went wrong: ", e); e.printStackTrace(); return null; } } }