/*******************************************************************************
* GenPlay, Einstein Genome Analyzer
* Copyright (C) 2009, 2014 Albert Einstein College of Medicine
*
* This program 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.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
* Authors: Julien Lajugie <julien.lajugie@einstein.yu.edu>
* Nicolas Fourel <nicolas.fourel@einstein.yu.edu>
* Eric Bouhassira <eric.bouhassira@einstein.yu.edu>
*
* Website: <http://genplay.einstein.yu.edu>
******************************************************************************/
package edu.yu.einstein.genplay.util;
import java.awt.Component;
import java.awt.FileDialog;
import java.awt.Frame;
import java.io.File;
import java.io.FilenameFilter;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.filechooser.FileFilter;
import edu.yu.einstein.genplay.core.manager.application.ConfigurationManager;
import edu.yu.einstein.genplay.gui.fileFilter.ExtendedFileFilter;
/**
* Class providing file choosers to save or load files or directories
* @author Julien Lajugie
*/
public class FileChooser {
/** Show a file chooser dialog to open a single file */
public static final int OPEN_FILE_MODE = 0;
/** Show a file chooser dialog to open a single directory */
public static final int OPEN_DIRECTORY_MODE = 1;
/** Show a file chooser dialog to save a file */
public static final int SAVE_FILE_MODE = 2;
/** True to use a AWT file chooser component, false to use a swing one*/
private static final boolean USE_AWT_CHOOSER = Utils.isMacOS();
/**
* Opens a dialog box asking the user to choose a file or a directory to load or to save
* @param parentComponent determines the Frame in which the dialog is displayed; if null, or if the parentComponent has no Frame, a default Frame is used
* @param mode one of {@link #OPEN_FILE_MODE}, {@link #OPEN_DIRECTORY_MODE} or {@link #SAVE_FILE_MODE}
* @param title title of the open dialog
* @param choosableFileFilters {@link FileFilter} available
* @param allFiles allow the selection of every kind of file if true, disable the all file selection if false
* @return a file or a directory
*/
public final static File chooseFile(Component parentComponent, int mode, String title, FileFilter[] choosableFileFilters, boolean allFiles) {
return chooseFile(parentComponent, mode, title, choosableFileFilters, allFiles, null);
}
/**
* Opens a dialog box asking the user to choose a file or a directory to load or to save
* @param parentComponent determines the Frame in which the dialog is displayed; if null, or if the parentComponent has no Frame, a default Frame is used
* @param mode one of {@link #OPEN_FILE_MODE}, {@link #OPEN_DIRECTORY_MODE} or {@link #SAVE_FILE_MODE}
* @param title title of the open dialog
* @param choosableFileFilters {@link FileFilter} available
* @param allFiles allow the selection of every kind of file if true, disable the all file selection if false
* @param selectedFile file preselected when the chooser pops up
* @return a file or a directory
*/
public final static File chooseFile(Component parentComponent, int mode, String title, FileFilter[] choosableFileFilters, boolean allFiles, File selectedFile) {
if (USE_AWT_CHOOSER) {
selectedFile = chooseFileUsingAWT(parentComponent, mode, choosableFileFilters, selectedFile);
} else {
selectedFile = chooseFileUsingSwing(parentComponent, mode, title, choosableFileFilters, allFiles, selectedFile);
}
if (selectedFile == null) {
return null;
} else if (((mode == OPEN_FILE_MODE) || (mode == OPEN_DIRECTORY_MODE)) && !selectedFile.canRead()) {
JOptionPane.showMessageDialog(parentComponent,
"You don't have the permission to read the selected file.", "Incorrect File", JOptionPane.ERROR_MESSAGE, null);
return null;
} else if (mode == SAVE_FILE_MODE) {
if (!(USE_AWT_CHOOSER && Utils.isMacOS()) && Utils.cancelBecauseFileExist(parentComponent, selectedFile)) {
return null;
}
}
return selectedFile;
}
/**
* Opens a dialog box asking the user to choose a file or a directory to load or to save using a AWT component file chooser
* @param parentComponent determines the Frame in which the dialog is displayed; if null, or if the parentComponent has no Frame, a default Frame is used
* @param mode one of {@link #OPEN_FILE_MODE}, {@link #OPEN_DIRECTORY_MODE} or {@link #SAVE_FILE_MODE}
* @param choosableFileFilters {@link FileFilter} available
* @param selectedFile file preselected when the chooser pops up
* @return a file or a directory
*/
private static final File chooseFileUsingAWT(Component parentComponent, int mode, FileFilter[] choosableFileFilters, File selectedFile) {
if (mode == OPEN_DIRECTORY_MODE) {
System.setProperty("apple.awt.fileDialogForDirectories", "true");
}
Frame parentFrame = null;
if (parentComponent instanceof JComponent) {
JComponent jComponent = (JComponent) parentComponent;
if ((jComponent.getTopLevelAncestor() != null) && (jComponent.getTopLevelAncestor() instanceof Frame)) {
parentFrame = (Frame) jComponent.getTopLevelAncestor();
}
}
FileDialog fd = new FileDialog(parentFrame);
String defaultDirectory = ConfigurationManager.getInstance().getDefaultDirectory();
fd.setDirectory(defaultDirectory);
if (selectedFile != null) {
fd.setFile(selectedFile.getName());
}
if (mode == SAVE_FILE_MODE) {
fd.setMode(FileDialog.SAVE);
} else {
fd.setMode(FileDialog.LOAD);
}
if (mode == OPEN_DIRECTORY_MODE) {
// set file filter that only accepts directories
fd.setFilenameFilter(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return new File(dir,name).isDirectory();
}
});
} else if (choosableFileFilters != null) {
fd.setFilenameFilter(unionFilter(choosableFileFilters));
}
fd.setVisible(true);
if (mode == OPEN_DIRECTORY_MODE) {
System.setProperty("apple.awt.fileDialogForDirectories", "false");
}
if (fd.getFile() != null) {
return new File(fd.getDirectory(), fd.getFile());
} else {
return null;
}
}
/**
* Opens a dialog box asking the user to choose a file or a directory to load or to save using a swing component file chooser
* @param parentComponent determines the Frame in which the dialog is displayed; if null, or if the parentComponent has no Frame, a default Frame is used
* @param mode one of {@link #OPEN_FILE_MODE}, {@link #OPEN_DIRECTORY_MODE} or {@link #SAVE_FILE_MODE}
* @param title title of the open dialog
* @param choosableFileFilters {@link FileFilter} available
* @param allFiles allow the selection of every kind of file if true, disable the all file selection if false
* @param selectedFile file preselected when the chooser pops up
* @return a file or a directory
*/
private final static File chooseFileUsingSwing(Component parentComponent, int mode, String title, FileFilter[] choosableFileFilters, boolean allFiles, File selectedFile) {
JFileChooser jfc = new JFileChooser();
setFileChooserSelectedDirectory(jfc);
if (selectedFile != null) {
jfc.setSelectedFile(selectedFile);
}
if (mode == OPEN_DIRECTORY_MODE) {
jfc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
} else {
jfc.setFileSelectionMode(JFileChooser.FILES_ONLY);
if (choosableFileFilters != null) {
for (FileFilter currentFilter: choosableFileFilters) {
jfc.addChoosableFileFilter(currentFilter);
}
jfc.setFileFilter(choosableFileFilters[0]);
}
}
jfc.setDialogTitle(title);
if (allFiles) {
jfc.addChoosableFileFilter(jfc.getAcceptAllFileFilter());
}
int returnVal;
if (mode == SAVE_FILE_MODE) {
returnVal = jfc.showSaveDialog(parentComponent);
} else {
returnVal = jfc.showOpenDialog(parentComponent);
}
if (returnVal == JFileChooser.APPROVE_OPTION) {
if ((mode == SAVE_FILE_MODE) && (choosableFileFilters != null) && (jfc.getFileFilter() instanceof ExtendedFileFilter)) {
// add the extension of the file if needed
return Utils.addExtension(jfc.getSelectedFile(), ((ExtendedFileFilter) jfc.getFileFilter()).getExtensions());
} else {
return jfc.getSelectedFile();
}
} else {
return null;
}
}
/**
* Sets the specified {@link JFileChooser} to the default directory
* @param jfc
*/
private static void setFileChooserSelectedDirectory(JFileChooser jfc) {
String defaultDirectory = ConfigurationManager.getInstance().getDefaultDirectory();
if (Utils.isMacOS()) {
jfc.setSelectedFile(new File(defaultDirectory));
} else {
jfc.setCurrentDirectory(new File(defaultDirectory));
}
}
/**
* Creates a {@link FilenameFilter} that accept all the files of the specified file filters
* @param filters variable number of {@link FileFilter} objects
* @return a new {@link FilenameFilter}
*/
private static final FilenameFilter unionFilter(final FileFilter... filters) {
FilenameFilter nameFilter = new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
File file = new File(dir,name);
if (file.isDirectory()) {
return false;
}
for (FileFilter ff: filters) {
if (ff.accept(file)) {
return true;
}
}
return false;
}
};
return nameFilter;
}
}