Bug 1475 : Possible improvements to selectInput, selectOutput, selectFolder
Last modified: 2010-06-05 03:50




Status:
ASSIGNED
Resolution:
-
Priority:
P3
Severity:
enhancement

 

Reporter:
Christian Thiemann
Assigned To:
fry

Attachment Type Created Size Actions
Modified PApplet.java application/octet-stream 2010-02-23 08:02 341.16 KB

Description:   Opened: 2010-02-23 08:01
I recently started using the selectInput etc. functions and found them quite nice. A few
things have annoyed me, though, and thus I would like to propose some improvements. Below is a modified FILE/FOLDER SELECTION section from PApplet.java (current SVN
version, line 4123 onwards), that implements the following:

# selectInput/Output/Folder functions remember the last opened folder and start there when
called the next time.
# Every of them can be called with two String arguments, where the second is the folder to
start the file chooser in.
# A new function requireExtension(String) ensures, if called before selectInput(), that only
files with a specific extension are selected.
# The requireExtension function is a simple interface to setFilenameFilter(FilenameFilter),
which is also public to allow for more complicated filename filtering.

I could only test it on MacOSX so far, which should be fine for everything except selectFolder
(since there is a specific if-branch for MacOSX).

============

//////////////////////////////////////////////////////////////

// FILE/FOLDER SELECTION


public File selectedFile;
public String lastDirectory;
protected FilenameFilter filenameFilter;
protected Frame parentFrame;


protected void checkParentFrame() {
if (parentFrame == null) {
Component comp = getParent();
while (comp != null) {
if (comp instanceof Frame) {
parentFrame = (Frame) comp;
break;
}
comp = comp.getParent();
}
// Who you callin' a hack?
if (parentFrame == null) {
parentFrame = new Frame();
}
}
}


/**
* Creates a new FilenameFilter that only allows files with a specific extension to be
selected by selectInput().
*
* @param filename extension to look for (without the dot)
*
* @see processing.core.PApplet#selectInput(String)
* @see processing.core.PApplet#setFilenameFilter(FilenameFilter)
*/
public void requireExtension(final String ext) {
filenameFilter = new FilenameFilter() {
public boolean accept(File dir, String name) {
return name.endsWith("." + ext);
}
};
}


/**
* Sets a new FilenameFilter that only allows certain files to be selected by selectInput().
*
* @param FilenameFilter instance to use in selectFileImpl
*
* @see processing.core.PApplet#selectInput(String)
*/
public void setFilenameFilter(FilenameFilter filenameFilter) {
this.filenameFilter = filenameFilter;
}


/**
* Open a platform-specific file chooser dialog to select a file for input.
* @return full path to the selected file, or null if no selection.
*/
public String selectInput() {
return selectInput("Select a file...");
}


/**
* Opens a platform-specific file chooser dialog to select a file for input. This function
returns the full path to the selected file as a <b>String</b>, or <b>null</b> if no selection.
*
* @webref input:files
* @param prompt message you want the user to see in the file chooser
* @return full path to the selected file, or null if canceled.
*
* @see processing.core.PApplet#selectOutput(String)
* @see processing.core.PApplet#selectFolder(String)
*/
public String selectInput(String prompt) {
return selectInput(prompt, lastDirectory);
}


/**
* Opens a platform-specific file chooser dialog to select a file for input. This function
returns the full path to the selected file as a <b>String</b>, or <b>null</b> if no selection.
*
* @webref input:files
* @param prompt message you want the user to see in the file chooser
* @param directory in which the file chooser starts
* @return full path to the selected file, or null if canceled.
*
* @see processing.core.PApplet#selectOutput(String, String)
* @see processing.core.PApplet#selectFolder(String, String)
*/
public String selectInput(String prompt, String dir) {
return selectFileImpl(prompt, FileDialog.LOAD, dir);
}


/**
* Open a platform-specific file save dialog to select a file for output.
* @return full path to the file entered, or null if canceled.
*/
public String selectOutput() {
return selectOutput("Save as...");
}


/**
* Open a platform-specific file save dialog to create of select a file for output.
* This function returns the full path to the selected file as a <b>String</b>, or
<b>null</b> if no selection.
* If you select an existing file, that file will be replaced.
* Alternatively, you can navigate to a folder and create a new file to write to.
*
* @param prompt message you want the user to see in the file chooser
* @return full path to the file entered, or null if canceled.
*
* @webref input:files
* @see processing.core.PApplet#selectInput(String)
* @see processing.core.PApplet#selectFolder(String)
*/
public String selectOutput(String prompt) {
return selectOutput(prompt, lastDirectory);
}


/**
* Open a platform-specific file save dialog to create of select a file for output.
* This function returns the full path to the selected file as a <b>String</b>, or
<b>null</b> if no selection.
* If you select an existing file, that file will be replaced.
* Alternatively, you can navigate to a folder and create a new file to write to.
*
* @param prompt message you want the user to see in the file chooser
* @param directory in which the file chooser starts
* @return full path to the file entered, or null if canceled.
*
* @webref input:files
* @see processing.core.PApplet#selectInput(String, String)
* @see processing.core.PApplet#selectFolder(String, String)
*/
public String selectOutput(String prompt, String dir) {
return selectFileImpl(prompt, FileDialog.SAVE, dir);
}


protected String selectFileImpl(final String prompt, final int mode, final String
initialDirectory) {
checkParentFrame();

try {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
FileDialog fileDialog =
new FileDialog(parentFrame, prompt, mode);
fileDialog.setDirectory(initialDirectory);
if ((mode == FileDialog.LOAD) && (filenameFilter != null))
fileDialog.setFilenameFilter(filenameFilter);
fileDialog.setVisible(true);
String directory = fileDialog.getDirectory();
String filename = fileDialog.getFile();
selectedFile =
(filename == null) ? null : new File(directory, filename);
lastDirectory = directory; // save directory even if the dialog was cancelled
}
});
return (selectedFile == null) ? null : selectedFile.getAbsolutePath();

} catch (Exception e) {
e.printStackTrace();
return null;
}
}


public String selectFolder() {
return selectFolder("Select a folder...");
}


/**
* Opens a platform-specific file chooser dialog to select a folder for input.
* This function returns the full path to the selected folder as a <b>String</b>, or
<b>null</b> if no selection.
*
* @webref input:files
* @param prompt message you want the user to see in the file chooser
* @return full path to the selected folder, or null if no selection.
*
* @see processing.core.PApplet#selectOutput(String)
* @see processing.core.PApplet#selectInput(String)
*/
public String selectFolder(String prompt) {
return selectFolder(prompt, lastDirectory);
}


/**
* Opens a platform-specific file chooser dialog to select a folder for input.
* This function returns the full path to the selected folder as a <b>String</b>, or
<b>null</b> if no selection.
*
* @webref input:files
* @param prompt message you want the user to see in the file chooser
* @param directory in which the file chooser starts
* @return full path to the selected folder, or null if no selection.
*
* @see processing.core.PApplet#selectOutput(String, String)
* @see processing.core.PApplet#selectInput(String, String)
*/
public String selectFolder(final String prompt, final String initialDirectory) {
checkParentFrame();

try {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
if (platform == MACOSX) {
FileDialog fileDialog =
new FileDialog(parentFrame, prompt, FileDialog.LOAD);
System.setProperty("apple.awt.fileDialogForDirectories", "true");
fileDialog.setDirectory(initialDirectory);
fileDialog.setVisible(true);
System.setProperty("apple.awt.fileDialogForDirectories", "false");
String filename = fileDialog.getFile();
selectedFile = (filename == null) ? null :
new File(fileDialog.getDirectory(), fileDialog.getFile());
lastDirectory = fileDialog.getDirectory();
} else {
JFileChooser fileChooser = new JFileChooser();
fileChooser.setDialogTitle(prompt);
fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
fileChooser.setCurrentDirectory(new File(initialDirectory));

int returned = fileChooser.showOpenDialog(parentFrame);
System.out.println(returned);
if (returned == JFileChooser.CANCEL_OPTION) {
selectedFile = null;
} else {
selectedFile = fileChooser.getSelectedFile();
}

lastDirectory = fileChooser.getCurrentDirectory().getAbsolutePath();
}
}
});
return (selectedFile == null) ? null : selectedFile.getAbsolutePath();

} catch (Exception e) {
e.printStackTrace();
return null;
}
}
Additional Comment #1 From Christian Thiemann 2010-02-23 08:02
edit]
Modified PApplet.java
Additional Comment #2 From fry 2010-06-05 03:43
I think we're going to keep them minimal for now, but I'll mark it as a
feature request. Thanks for the code.
Additional Comment #3 From fry 2010-06-05 03:50
*** Bug 1504 has been marked as a duplicate of this bug. ***
This bug is now being tracked here.