/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2002-2008, Open Source Geospatial Foundation (OSGeo)
*
* 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;
* version 2.1 of the License.
*
* 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.
*/
package org.geotools.swing.data;
import java.awt.Component;
import java.awt.HeadlessException;
import java.io.File;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.filechooser.FileFilter;
import org.geotools.data.FileDataStoreFactorySpi;
import org.geotools.data.FileDataStoreFinder;
/**
* A file chooser dialog to get user choices for data stores.
* <p>
* Examples of use:
* <pre>{@code
* // prompt the user for a shapefile
* File file = JFileDataStoreChooser.showOpenFile("shp", parentFrame);
* if (file != null) {
* ...
* }
*
* // prompt the user for a given data format
*
* }</pre>
*
* @author Jody Garnett
* @since 2.6
*
*
* @source $URL$
* @version $Id$
*/
public class JFileDataStoreChooser extends JFileChooser {
private static final long serialVersionUID = -7482109609487216939L;
/**
* Create a dialog that filters for files with the specified extension.
*
* @param extension the file extension, with or without the leading '.'
*/
public JFileDataStoreChooser(final String extension) {
this(new String[]{extension});
}
static Map<String, String> associations( List<String> extensions ){
Map<String, String> fileAssociations = new TreeMap<String, String>();
for (String extension : extensions) {
String ext = extension.toLowerCase().trim();
if (!ext.startsWith(".")) {
ext = "." + ext;
}
FileDataStoreFactorySpi factory = FileDataStoreFinder.getDataStoreFactory(ext);
if (factory != null) {
fileAssociations.put(ext, factory.getDescription());
} else {
// guess some common ones
if (".csv".equals(ext)) {
fileAssociations.put(ext, "Comma-delimited files (*.csv)");
} else if (ext.startsWith(".tif")) {
fileAssociations.put(ext, "GeoTIFF files (*.tif; *.tiff)");
} else {
// fallback
fileAssociations.put(ext, ext.toUpperCase().substring(1) + "files (*" + ext + ")");
}
}
}
return fileAssociations;
}
/**
* Create a dialog that filters for files with the specified extensions.
*
* @param extensions the file extensions, with or without the leading '.'
*/
public JFileDataStoreChooser(final List<String> extensions) {
this( associations( extensions ));
}
/**
* Create a dialog that filters for files with the specified extensions.
*
* @param extensions the file extensions, with or without the leading '.'
*/
public JFileDataStoreChooser(final String[] extensions) {
this( associations( Arrays.asList(extensions)));
}
/**
* Creates a dialog based on the given file associations.
*
* <pre><code>
* Map<String, String> assoc = new HashMap<String, String>();
* assoc.put(".foo", "Foo data files (*.foo)");
* assoc.put(".bar", "Bar data files (*.bar)");
* JFileDataStoreChooser chooser = new JFileDataStoreChooser(assoc);
* </code></pre>
*
* @param fileAssociations a {@code Map} where keys are extensions (with or
* wirhout the leading dot) and values are descriptions.
*/
public JFileDataStoreChooser(final Map<String, String> fileAssociations) {
init( fileAssociations );
}
/**
* Helper method for constructors that creates file filters.
*
* @param fileAssociations a {@code Map} where keys are extensions (with or
* wirhout the leading dot) and values are descriptions.
*/
private void init(final Map<String, String> fileAssociations) {
for (final String ext : fileAssociations.keySet()) {
addChoosableFileFilter(new FileFilter() {
public boolean accept(File f) {
if (f.isDirectory()) {
return true;
}
for (String ext : fileAssociations.keySet()) {
if (f.getPath().endsWith(ext) ||
f.getPath().endsWith(ext.toUpperCase())) {
return true;
}
}
return false;
}
@Override
public String getDescription() {
return fileAssociations.get(ext);
}
});
}
}
/**
* Creates a dialog that filters for files matching the specified
* data format.
*
* @param format data file format
*/
public JFileDataStoreChooser(final FileDataStoreFactorySpi format) {
setFileFilter(new FileFilter() {
public boolean accept(File f) {
if (f.isDirectory()) {
return true;
}
for (String ext : format.getFileExtensions()) {
if (f.getPath().endsWith(ext)) {
return true;
}
if (f.getPath().endsWith(ext.toUpperCase())) {
return true;
}
}
return false;
}
public String getDescription() {
return format.getDescription();
}
});
}
/**
* Show a file open dialog that filters for files with the given extension.
*
* @param extension file extension, with or without leading '.'
* @param parent parent GUI component (may be {@code null})
*
* @return the selected file or null if the user cancelled the selection
* @throws java.awt.HeadlessException if run in an unsupported environment
*/
public static File showOpenFile(String extension, Component parent)
throws HeadlessException {
return showOpenFile(extension, null, parent);
}
/**
* Show a file open dialog that filters for files with the given extension.
*
* @param extension file extension, with or without leading '.'
* @param initialDir initial directory to display; if {@code null} the initial directory
* will be the user's default directory
* @param parent parent GUI component (may be {@code null})
*
* @return the selected file or null if the user cancelled the selection
* @throws java.awt.HeadlessException if run in an unsupported environment
*/
public static File showOpenFile(String extension, File initialDir, Component parent)
throws HeadlessException {
JFileDataStoreChooser dialog = new JFileDataStoreChooser(extension);
if (initialDir != null) {
if (initialDir.isDirectory()) {
dialog.setCurrentDirectory(initialDir);
} else {
dialog.setCurrentDirectory(initialDir.getParentFile());
}
}
if (dialog.showOpenDialog(parent) == JFileChooser.APPROVE_OPTION) {
return dialog.getSelectedFile();
}
return null;
}
/**
* Show a file open dialog that filters for files with the given extensions.
*
* @param extensions array of file extension, with or without leading '.'
* @param parent parent GUI component (may be null)
*
* @return the selected file or null if the user cancelled the selection
* @throws java.awt.HeadlessException if run in an unsupported environment
*/
public static File showOpenFile(String[] extensions, Component parent)
throws HeadlessException {
return showOpenFile(extensions, null, parent);
}
/**
* Show a file open dialog that filters for files with the given extensions.
*
* @param extensions array of file extension, with or without leading '.'
* @param initialDir initial directory to display; if {@code null} the initial directory
* will be the user's default directory
* @param parent parent GUI component (may be null)
*
* @return the selected file or null if the user cancelled the selection
* @throws java.awt.HeadlessException if run in an unsupported environment
*/
public static File showOpenFile(String[] extensions, File initialDir, Component parent)
throws HeadlessException {
JFileDataStoreChooser dialog = new JFileDataStoreChooser(extensions);
if (initialDir != null) {
if (initialDir.isDirectory()) {
dialog.setCurrentDirectory(initialDir);
} else {
dialog.setCurrentDirectory(initialDir.getParentFile());
}
}
if (dialog.showOpenDialog(parent) == JFileChooser.APPROVE_OPTION) {
return dialog.getSelectedFile();
}
return null;
}
/**
* Show a file open dialog that filters for files that match a given file
* data store format
*
* @param format the file data store format
* @param parent parent GUI component (may be null)
*
* @return the selected file or null if the user cancelled the selection
* @throws java.awt.HeadlessException if run in an unsupported environment
*/
public static File showOpenFile(FileDataStoreFactorySpi format, Component parent)
throws HeadlessException {
return showOpenFile(format, null, parent);
}
/**
* Show a file open dialog that filters for files that match a given file
* data store format
*
* @param format the file data store format
* @param initialDir initial directory to display; if {@code null} the initial directory
* will be the user's default directory
* @param parent parent GUI component (may be null)
*
* @return the selected file or null if the user cancelled the selection
* @throws java.awt.HeadlessException if run in an unsupported environment
*/
public static File showOpenFile(FileDataStoreFactorySpi format, File initialDir, Component parent)
throws HeadlessException {
JFileDataStoreChooser dialog = new JFileDataStoreChooser(format);
if (initialDir != null) {
if (initialDir.isDirectory()) {
dialog.setCurrentDirectory(initialDir);
} else {
dialog.setCurrentDirectory(initialDir.getParentFile());
}
}
if (dialog.showOpenDialog(parent) == JFileChooser.APPROVE_OPTION) {
return dialog.getSelectedFile();
}
return null;
}
/**
* Demonstrates the file data store dialog by prompting for a shapefile
*
* @param arg ignored
*/
public static void main(String arg[]) {
File file = JFileDataStoreChooser.showOpenFile("shp", null);
if (file != null) {
JOptionPane.showMessageDialog(null, "Selected " + file.getPath());
} else {
JOptionPane.showMessageDialog(null, "Selection cancelled");
}
}
/**
* Consider the provided file as a candidate for a new filename.
* A number will be appended to the filename if there is a
* conflict.
*
* @param file the candidate file name
*/
public void setSaveFile(File file) {
String path = file.getAbsolutePath();
int split = path.lastIndexOf('.');
String base;
String extension;
if( split == -1 ){
base = path;
extension = "";
}
else {
base = path.substring(0, split);
extension = path.substring(split);
}
File saveFile = new File( path );
int number = 0;
while( saveFile.exists() ){
saveFile = new File( base+(number++)+extension );
}
setSelectedFile( saveFile );
}
}