/*
* Copyright (C) 2004 The Concord Consortium, Inc.,
* 10 Concord Crossing, Concord, MA 01742
*
* Web Site: http://www.concord.org
* Email: info@concord.org
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* END LICENSE */
package org.concord.swing;
import java.awt.Component;
import java.awt.FileDialog;
import java.awt.Frame;
import java.io.File;
import java.io.FilenameFilter;
import java.util.prefs.Preferences;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import javax.swing.filechooser.FileFilter;
public class MostRecentFileDialog
{
/**
* Return value if cancel is chosen.
*/
public static final int CANCEL_OPTION = JFileChooser.CANCEL_OPTION;
/**
* Return value if approve (yes, ok) is chosen.
*/
public static final int APPROVE_OPTION = JFileChooser.APPROVE_OPTION;
/**
* Return value if an error occured.
*/
public static final int ERROR_OPTION = JFileChooser.ERROR_OPTION;
/** Instruction to display only files. */
public static final int FILES_ONLY = JFileChooser.FILES_ONLY;
/** Instruction to display only directories. */
public static final int DIRECTORIES_ONLY = JFileChooser.DIRECTORIES_ONLY;
public static final int ACCESS_MODE_READ = 0;
public static final int ACCESS_MODE_WRITE = 1;
/** Instruction to display both files and directories. */
public static final int FILES_AND_DIRECTORIES = JFileChooser.FILES_AND_DIRECTORIES;
final static String PREFERENCE_DOMAIN ="org/concord/swing/MostRecentFileDialog";
final static String DEFAULT_PREFERENCES_KEY ="org.concord.swing.MostRecentFileDialog";
// you can change this to false if you want to debug the awt
// version of the code on a platform that usually uses swing
public static boolean USE_SWING_DIALOG_DEFAULT = true;
String preferencesKey;
String extension;
boolean swingOnly = false;
File currentDirectory;
File selectedFile;
private int fileSelectionMode = FILES_ONLY;
private int fileAccessMode = ACCESS_MODE_READ;
private Component parent;
private String title;
public MostRecentFileDialog(String preferencesKey, boolean swingOnly)
{
this.preferencesKey = preferencesKey;
this.swingOnly = swingOnly;
initCurrentDirectory();
}
public MostRecentFileDialog(String preferencesKey)
{
this(preferencesKey, false);
}
public MostRecentFileDialog(boolean swingOnly)
{
this(null, swingOnly);
}
public MostRecentFileDialog()
{
this(null, false);
}
public void setFileSelectionMode(int fileSelectionMode)
{
if(fileSelectionMode != FILES_ONLY &&
fileSelectionMode != FILES_AND_DIRECTORIES &&
fileSelectionMode != DIRECTORIES_ONLY)
throw new IllegalArgumentException(
"Must be either MostRecentFileDialog.FILES_ONLY, " +
"MostRecentFileDialog.FILES_AND_DIRECTORIES, or " +
"MostRecentFileDialog.DIRECTORIES_ONLY");
this.fileSelectionMode = fileSelectionMode;
}
public void setFilenameFilter(String extension)
{
this.extension = extension.toLowerCase();
}
protected void setCurrentDirectoryInternal(File directory)
{
currentDirectory = directory;
}
public void setCurrentDirectory(File directory)
{
currentDirectory = directory;
saveCurrentDirectory(currentDirectory);
}
public void setSelectedFile(File currentFile)
{
if(useSwingDialog() && fileAccessMode == ACCESS_MODE_WRITE) {
if(currentFile.exists()) {
int retval = JOptionPane.showConfirmDialog(parent,
"The file " + currentFile.getName() + " exists. " +
"Do you want to overwrite it?",
"Warning", JOptionPane.WARNING_MESSAGE);
if(retval == JOptionPane.NO_OPTION ||
retval == JOptionPane.CANCEL_OPTION)
showSaveDialog(parent, title);
else
selectedFile = currentFile;
} else {
String name = currentFile.getAbsolutePath();
if(extension != null && !name.endsWith(extension))
name = name + "." + extension;
File temp = new File(name);
if(temp.exists())
setSelectedFile(temp);
else selectedFile = temp;
}
} else {
selectedFile = currentFile;
}
}
public int showOpenDialog(Component parent)
{
return showOpenDialog(parent, "Open");
}
public int showOpenDialog(Component parent, String title)
{
this.parent = parent;
this.title = title;
fileAccessMode = ACCESS_MODE_READ;
if(useSwingDialog()) {
JFileChooser fileChooser = new JFileChooser(getCurrentDirectory());
if(fileSelectionMode == DIRECTORIES_ONLY)
fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
else
if(extension != null) fileChooser.setFileFilter(new FileNameFilter(extension));
int returnVal = fileChooser.showOpenDialog(parent);
if (returnVal == JFileChooser.APPROVE_OPTION) {
setSelectedFile(fileChooser.getSelectedFile());
setCurrentDirectory(fileChooser.getCurrentDirectory());
return returnVal;
}
return returnVal;
} else {
if(parent == null) parent = new Frame();
Frame frame = (Frame)SwingUtilities.getRoot(parent);
FileDialog dialog = new FileDialog(frame, "Open", FileDialog.LOAD);
if(extension != null) {
dialog.setFilenameFilter(new FileNameFilter(extension));
}
File currentDir = getCurrentDirectory();
String startingPath = ".";
if(currentDir != null) {
startingPath = currentDir.getAbsolutePath();
}
dialog.setDirectory(startingPath);
dialog.show();
// the docs for FileDialog.getDirectory say it can
// return null. This could happen if the directory
// set above is invalid (it has been deleted perhaps?)
String selectedDirectoryStr = dialog.getDirectory();
// Save the selected directory
File selectedDirectory = null;
if(selectedDirectoryStr != null) {
selectedDirectory = new File(selectedDirectoryStr);
setCurrentDirectory(selectedDirectory);
}
File selectedFile = null;
if(fileSelectionMode == DIRECTORIES_ONLY) {
if(selectedDirectory != null) {
selectedFile = selectedDirectory;
} else {
// we don't have a valid directory so I guess we
// set the selected File to null
// we don't need an if for this but it makes
// it more clear.
selectedFile = null;
}
} else {
String selectedFileStr = dialog.getFile();
// If the cancel button is pressed this the selectedFileString
// will be null
if(selectedFileStr != null) {
if(selectedDirectory != null) {
selectedFile = new File(selectedDirectory, selectedFileStr);
} else {
// we don't have a valid directory, but might have
// a valid file. I'll take a guess to great the file
// with the working direcotry
selectedFile = new File(selectedFileStr);
}
}
}
dialog.dispose();
if(selectedFile != null) {
setSelectedFile(selectedFile);
return APPROVE_OPTION;
}
return CANCEL_OPTION;
}
// return ERROR_OPTION;
}
public int showSaveDialog(Component parent)
{
return showSaveDialog(parent, "Save");
}
public int showSaveDialog(Component parent, String title)
{
this.parent = parent;
this.title = title;
fileAccessMode = ACCESS_MODE_WRITE;
if(useSwingDialog()) {
JFileChooser fileChooser = new JFileChooser(getCurrentDirectory());
if(extension != null) fileChooser.setFileFilter(new FileNameFilter(extension));
int returnVal = fileChooser.showSaveDialog(parent);
if (returnVal == JFileChooser.APPROVE_OPTION) {
setSelectedFile(fileChooser.getSelectedFile());
setCurrentDirectory(fileChooser.getCurrentDirectory());
return returnVal;
}
return returnVal;
} else {
if(parent == null) parent = new Frame();
Frame frame = (Frame)SwingUtilities.getRoot(parent);
FileDialog dialog = new FileDialog(frame, title, FileDialog.SAVE);
if(extension != null) dialog.setFilenameFilter(new FileNameFilter(extension));
dialog.show();
String selectedFileStr = null;
String selectedDirectoryStr = dialog.getDirectory();
File selectedDirectory = null;
if(selectedDirectoryStr != null) {
selectedDirectory = new File(selectedDirectoryStr);
setCurrentDirectory(selectedDirectory);
}
if(fileSelectionMode == DIRECTORIES_ONLY) {
selectedFileStr = selectedDirectoryStr;
} else {
selectedFileStr = dialog.getFile();
}
dialog.dispose();
if(selectedFileStr != null) {
setSelectedFile(new File(selectedFileStr));
return APPROVE_OPTION;
}
return CANCEL_OPTION;
}
}
public File getSelectedFile()
{
return selectedFile;
}
public File getCurrentDirectory()
{
return currentDirectory;
}
public boolean useSwingDialog()
{
if(swingOnly) {
return true;
}
if(System.getProperty("os.name").startsWith("Mac")) {
return false;
}
return USE_SWING_DIALOG_DEFAULT;
}
protected void setPreferencesKey(String preferencesKey)
{
this.preferencesKey = preferencesKey;
}
protected String getPreferencesKey()
{
if(preferencesKey != null) {
return preferencesKey;
}
return DEFAULT_PREFERENCES_KEY;
}
protected void initCurrentDirectory()
{
String suggestedPath = null;
String savedPath = null;
try{
Preferences userPreferences = Preferences.userRoot();
Preferences dialogPreferences = null;
dialogPreferences = userPreferences.node(PREFERENCE_DOMAIN);
if(dialogPreferences != null) {
savedPath = dialogPreferences.get(preferencesKey,null);
}
}catch(Throwable t){
// can't load the saved path
}
suggestedPath = savedPath;
// Make sure the suggested path is valid
if(suggestedPath != null){
try {
File tmpSuggestedFile = new File(suggestedPath);
if(!tmpSuggestedFile.exists() || !tmpSuggestedFile.isDirectory()) {
suggestedPath = null;
}
} catch (Throwable t){
suggestedPath = null;
}
}
// there is no saved path
if(suggestedPath == null){
try{
// set the suggested path to be the current path of
// this file dialog object
suggestedPath = getCurrentDirectory().getCanonicalPath();
}catch(Throwable t){
}
}
// the file dialog doesn't have a current path
if(suggestedPath == null){
try {
suggestedPath = System.getProperty("user.dir");
} catch (Throwable t) {
}
}
File suggestedFile = null;
if(suggestedPath != null) {
suggestedFile = new File(suggestedPath);
} else {
suggestedFile = new File(".");
}
// Last check to make sure the path is valid, just incase the user.dir
// was invalid, or "." was invalid.
// This does mean that
if(suggestedFile.exists() && suggestedFile.isDirectory()) {
setCurrentDirectoryInternal(suggestedFile);
}
}
protected void saveCurrentDirectory(File currentDirectory)
{
String canonicalPath = null;
try{
canonicalPath = currentDirectory.getCanonicalPath();
Preferences userPreferences = Preferences.userRoot();
Preferences dialogPreferences =
userPreferences.node(PREFERENCE_DOMAIN);
dialogPreferences.put(getPreferencesKey(),canonicalPath);
}catch(Throwable t){
}
}
class FileNameFilter extends FileFilter implements FilenameFilter {
String filter;
public FileNameFilter(String filter) {
this.filter = filter;
}
public boolean accept(File dir, String name) {
if(dir.isDirectory()) return true;
if(name.lastIndexOf(".") != -1)
if(name.substring(name.lastIndexOf(".")).equalsIgnoreCase("." + filter))
return true;
return false;
}
public boolean accept(File file) {
String fileName = file.getAbsolutePath();
if(file.isDirectory()) return true;
if(fileName.lastIndexOf(".") != -1)
if(fileName.substring(fileName.lastIndexOf(".")).equalsIgnoreCase("." + filter))
return true;
return false;
}
public String getDescription() {
if(filter != null && filter.length() > 0) return filter + " files";
return "all files";
}
}
}