/*
* org.openmicroscopy.shoola.util.ui.filechooser.FileSaver
*
*------------------------------------------------------------------------------
* Copyright (C) 2006-2015 University of Dundee. All rights reserved.
*
*
* 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 2 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, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*------------------------------------------------------------------------------
*/
package org.openmicroscopy.shoola.util.ui.filechooser;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.util.List;
import java.util.regex.Pattern;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.filechooser.FileFilter;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.io.FilenameUtils;
import org.openmicroscopy.shoola.util.CommonsLangUtils;
import org.openmicroscopy.shoola.util.filter.file.CustomizedFileFilter;
import org.openmicroscopy.shoola.util.ui.IconManager;
import org.openmicroscopy.shoola.util.ui.MessageBox;
import org.openmicroscopy.shoola.util.ui.RegExFactory;
import org.openmicroscopy.shoola.util.ui.UIUtilities;
/**
* Default Dialog used to display a file chooser.
*
* @author Jean-Marie Burel
* <a href="mailto:j.burel@dundee.ac.uk">j.burel@dundee.ac.uk</a>
* @author Donald MacDonald
* <a href="mailto:donald@lifesci.dundee.ac.uk">donald@lifesci.dundee.ac.uk</a>
* @version 3.0
* @since OME3.0
*/
public class FileChooser
extends JDialog
{
/** The text corresponding to the download action.*/
public static final String DOWNLOAD_TEXT = "Download";
/** The text corresponding to the download action.*/
public static final String DOWNLOAD_DESCRIPTION =
"Select where to download the file(s).";
/** Bound property indicating that the cancel button is pressed. */
public static final String APPROVE_SELECTION_PROPERTY = "approveSelection";
/** Bound property indicating that the cancel button is pressed. */
public static final String CANCEL_SELECTION_PROPERTY = "cancelSelection";
/**
* Bound property indicating the directory where to save the original files.
*/
public static final String LOCATION_PROPERTY = "location";
/** Identifies the <code>Load</code> dialog. */
public static final int LOAD = 0;
/** Identifies the <code>Save</code> dialog. */
public static final int SAVE = 1;
/** Identifies the <code>Folder Chooser</code> dialog. */
public static final int FOLDER_CHOOSER = 2;
/** Identifies the <code>Import</code> dialog. */
public static final int IMPORT = 3;
/** Indicates to add the button to the left of the controls. */
public static final int LEFT = 100;
/** Indicates to add the button to the center of the controls. */
public static final int CENTER = 101;
/** Indicates to add the button to the right of the controls. */
public static final int RIGHT = 102;
/** The approval option the user chose. */
private int option;
/** The UI delegate. */
private FileSaverUI uiDelegate;
/** One of the constants defined by this class. */
private int dialogType;
/** Title for the save dialog. */
private String title;
/** Message at top of dialog window. */
private String message;
/** Collection of supported filters. */
private List<FileFilter> filters;
/** The list of selected paths.*/
private List<String> paths;
/**
* Path to the folder.
* Only used when the type is {@link #FOLDER_CHOOSER}.
*/
private String folderPath;
/** Ask if a file should be overridden. */
private boolean checkOverride;
/** Flag indicate to override the names when saving.*/
private boolean override;
/** Sets the properties of the dialog. */
private void setProperties()
{
setTitle(title);
setModal(true);
setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
addWindowListener(new WindowAdapter() {
/**
* Cancels the selection.
* @see WindowAdapter#windowClosing(WindowEvent)
*/
public void windowClosing(WindowEvent e) {
cancelSelection();
}
/**
* Requests focus on name to enable the <code>Approve button</code>.
* @see WindowAdapter#windowOpened(WindowEvent)
*/
public void windowOpened(WindowEvent e) {
uiDelegate.requestFocusOnName();
}
});
}
/**
* Controls if the passed window type is supported.
*
* @param v The value to check.
*/
private void checkType(int v)
{
switch (v) {
case SAVE:
case LOAD:
case FOLDER_CHOOSER:
case IMPORT:
return;
default:
throw new IllegalArgumentException("Type not supported");
}
}
/**
* Creates a new instance.
*
* @param owner The owner of this dialog.
* @param dialogType One of the constants defined by this class.
* @param title Title of the dialog.
* @param message Message of the dialog.
* @param filters The list of filters.
* @param accept Determines whether the all files filter is
* turned on or off. Default value is <code>false</code>.
* @param checkOverride Ask for confirmation if the user selects a file
* that already exists.
*/
public FileChooser(JFrame owner, int dialogType, String title,
String message, List<FileFilter> filters, boolean accept,
boolean checkOverride)
{
super(owner);
checkType(dialogType);
this.dialogType = dialogType;
this.title = title;
this.message = message;
this.filters = filters;
this.checkOverride = checkOverride;
setProperties();
folderPath = null;
uiDelegate = new FileSaverUI(this, accept);
pack();
}
/**
* Creates a new instance.
*
* @param owner The owner of this dialog.
* @param dialogType One of the constants defined by this class.
* @param title Title of the dialog.
* @param message Message of the dialog.
* @param filters The list of filters.
* @param accept Determines whether the all files filter is turned.
*/
public FileChooser(JFrame owner, int dialogType, String title,
String message, List<FileFilter> filters, boolean accept)
{
this(owner, dialogType, title, message, filters, accept, false);
}
/**
* Creates a new instance.
*
* @param owner The owner of this dialog.
* @param dialogType One of the constants defined by this class.
* @param title Title of the dialog.
* @param message Message of the dialog.
* @param filters The list of filters.
*/
public FileChooser(JFrame owner, int dialogType, String title,
String message, List<FileFilter> filters)
{
this(owner, dialogType, title, message, filters, false, false);
}
/**
* Creates a new instance.
*
* @param owner The owner of this dialog.
* @param dialogType One of the constants defined by this class.
* @param title Title of the dialog.
* @param message Message of the dialog.
*/
public FileChooser(JFrame owner, int dialogType, String title,
String message)
{
this(owner, dialogType, title, message, null, false);
}
/**
* Returns the message to the dialog.
*
* @return See above.
*/
String getNote() { return message; }
/**
* Returns the list of filters.
*
* @return See above.
*/
List<FileFilter> getFilters() { return filters; }
/**
* Adds the extension to the passed name if necessary.
*
* @param name The name to handle.
* @param format The selected file format.
* @return See above.
*/
String getExtendedName(String name, String format)
{
String extension = "."+format;
Pattern pattern = RegExFactory.createPattern(extension);
String n;
if (RegExFactory.find(pattern, name)) {
n = name;
} else {
pattern = RegExFactory.createCaseInsensitivePattern(extension);
if (RegExFactory.find(pattern, name)) n = name;
else n = name + "." + format;
}
return n;
}
/** Closes the window and disposes. */
void cancelSelection()
{
firePropertyChange(CANCEL_SELECTION_PROPERTY, Boolean.valueOf(false),
Boolean.valueOf(true));
option = JFileChooser.CANCEL_OPTION;
setVisible(false);
dispose();
}
/** Saves the file. */
void acceptSelection()
{
option = JFileChooser.APPROVE_OPTION;
File[] files;
override = false;
if (getChooserType() == FOLDER_CHOOSER) {
File f = uiDelegate.getCurrentDirectory();
if (f != null) {
if (!CollectionUtils.isEmpty(paths) && checkOverride) {
File[] entries = f.listFiles();
boolean exist = false;
for (int i = 0; i < entries.length; i++) {
if (paths.contains(entries[i].getName())) {
exist = true;
}
}
if (exist) {
MessageBox msg = new MessageBox(this,
"Overwrite existing files.",
"Do you wish to overwrite the existing files?");
int option = msg.centerMsgBox();
override = option == MessageBox.YES_OPTION;
}
}
String path = f.getAbsolutePath();
if (!path.endsWith(File.separator))
path += File.separator;
firePropertyChange(APPROVE_SELECTION_PROPERTY, null, path);
setVisible(false);
dispose();
}
return;
} else {
if (uiDelegate.isMultisSelectionEnabled()) {
files = getSelectedFiles();
} else {
files = new File[1];
files[0] = getSelectedFile();
}
}
if (uiDelegate.isSetDefaultFolder()
&& getChooserType() != FileChooser.FOLDER_CHOOSER)
UIUtilities.setDefaultFolder(
uiDelegate.getCurrentDirectory().toString());
File f = getSelectedFile();
String extension = FilenameUtils.getExtension(f.getName());
if (CommonsLangUtils.isBlank(extension)) {
FileFilter filter = getSelectedFilter();
if (filter instanceof CustomizedFileFilter) {
extension = ((CustomizedFileFilter) filter).getExtension();
f = new File(f.getAbsolutePath()+"."+extension);
files[0] = f;
}
}
if (getChooserType() != FileChooser.FOLDER_CHOOSER) {
if (f.exists() && checkOverride)
{
MessageBox msg = new MessageBox(this,
"Overwrite existing file.",
"Do you wish to overwrite the existing file?");
int option = msg.centerMsgBox();
if (option == MessageBox.NO_OPTION)
return;
String path = f.getAbsolutePath();
f.delete();
files[0] = new File(path);
}
}
firePropertyChange(APPROVE_SELECTION_PROPERTY, Boolean.valueOf(false),
files);
setVisible(false);
dispose();
}
/**
* Fires a property indicating where to save the archived files.
*
* @param path The path to the directory.
*/
void setFolderPath(String path)
{
if (path == null) return;
folderPath = path;
firePropertyChange(LOCATION_PROPERTY, null, path+File.separatorChar);
setVisible(false);
dispose();
}
/** Brings up on screen the dialog asking a <code>Yes/No</code>. */
void setSelection()
{
IconManager im = IconManager.getInstance();
FileSaverDialog d = new FileSaverDialog(this,
im.getIcon(IconManager.QUESTION_32));
UIUtilities.centerAndShow(d);
}
/**
* Returns the path to the folder or <code>null</code>.
*
* @return See above.
*/
public File getFolderPath()
{
if (folderPath != null) return new File(folderPath);
return null;
}
/**
* Returns the type.
*
* @return See above.
*/
public int getChooserType() { return dialogType; }
/**
* Sets the name of the file to save.
*
* @param name The name to set.
*/
public void setSelectedFile(String name)
{
if (CommonsLangUtils.isBlank(name))
throw new IllegalArgumentException("File name not valid.");
String s = FilenameUtils.getBaseName(name);
if (CommonsLangUtils.isBlank(s)) s = name;
uiDelegate.setSelectedFile(new File(s));
}
/**
* Sets the name of the file to save.
*
* @param name The name to set.
*/
public void setSelectedFileFull(String name)
{
if (CommonsLangUtils.isBlank(name)) return;
uiDelegate.setSelectedFile(new File(name));
}
/**
* Sets the name of the file to save.
*
* @param name The name to set.
*/
public void setSelectedFile(File name)
{
if (name == null) return;
uiDelegate.setSelectedFile(name);
}
/**
* Sets the name of the directory to save.
*
* @param dir The name to set.
*/
public void setCurrentDirectory(String dir)
{
if (CommonsLangUtils.isBlank(dir))
throw new IllegalArgumentException("Folder name not valid.");
uiDelegate.setCurrentDirectory(new File(dir));
}
/**
* Sets the name of the directory to save.
*
* @param dir The name to set.
*/
public void setCurrentDirectory(File dir)
{
if (dir == null)
throw new IllegalArgumentException("Folder cannot be null.");
uiDelegate.setCurrentDirectory(dir);
}
/**
* Returns the selected file for the chooser.
*
* @return See above,
*/
public File getSelectedFile()
{
return uiDelegate.getSelectedFile();
}
/**
* Returns the selected files.
*
* @return See above.
*/
public File[] getSelectedFiles()
{
return uiDelegate.getSelectedFiles();
}
/**
* Returns the selected file with the file format extension added
* to it e.g. myfile.csv if the CVS filter is selected.
* If no filter selected, the method returns the selected file
*
* @return See above.
* @see #getSelectedFile()
*/
public File getFormattedSelectedFile()
{
return uiDelegate.getFormattedSelectedFile();
}
/**
* Returns the currently selected filter.
*
* @return See above.
*/
public FileFilter getSelectedFilter()
{
return uiDelegate.getSelectedFilter();
}
/**
* Shows the chooser dialog.
*
* @return The option selected.
*/
public int showDialog()
{
UIUtilities.setLocationRelativeToAndShow(getParent(), this);
return option;
}
/**
* Shows the chooser dialog.
*
* @return The option selected.
*/
public int centerDialog()
{
UIUtilities.centerAndShow(this);
return option;
}
/**
* Sets the text of the <code>Approve</code> button.
*
* @param text The value to set.
*/
public void setApproveButtonText(String text)
{
if (CommonsLangUtils.isBlank(text)) return;
uiDelegate.setApproveButtonText(text);
}
/**
* Sets the text displayed in the tool tip of the <code>Approve</code>
* button.
*
* @param text The value to set.
*/
public void setApproveButtonToolTipText(String text)
{
if (CommonsLangUtils.isBlank(text)) return;
uiDelegate.setApproveButtonToolTipText(text);
}
/**
* Adds the passed button to add to the control.
*
* @param button The button to add.
* @param location he location of the button.
*/
public void addControlButton(JButton button, int location)
{
if (button == null)
throw new IllegalArgumentException("Button cannot be null.");
switch (location) {
case LEFT:
case RIGHT:
case CENTER:
break;
default:
throw new IllegalArgumentException("Location not supported.");
}
uiDelegate.addControlButton(button, location);
}
/**
* Adds the passed component to add to the control.
*
* @param component The component to add.
*/
public void addComponentToControls(JComponent component)
{
if (component == null)
throw new IllegalArgumentException("The component cannot be null.");
uiDelegate.addComponentToControls(component);
}
/**
* Sets the icon displayed in the title panel.
*
* @param icon the value to set.
*/
public void setTitleIcon(Icon icon)
{
if (icon == null) return;
uiDelegate.setTitleIcon(icon);
}
/**
* Sets the value indicating to allow for multiple selection if
* <code>true</code>.
*
* @param enabled Pass <code>true</code> to allow multiple selections,
* <code>false</code> otherwise.
*/
public void setMultiSelectionEnabled(boolean enabled)
{
uiDelegate.setMultiSelectionEnabled(enabled);
}
/**
* Sets the value indicating to check or not if the file can be overridden.
*
* @param checkOverride Pass <code>true</code> to override,
* <code>false</code> otherwise.
*/
public void setCheckOverride(boolean checkOverride)
{
this.checkOverride = checkOverride;
}
/**
* Sets the list of selected files. This should only be used when
* several files are selected.
*
* @param paths The collection of selected paths.
*/
public void setSelectedFiles(List<String> paths)
{
this.paths = paths;
}
/**
* Returns <code>true</code> to override the files when saving,
* <code>false</code> otherwise. Default is <code>false</code>.
*
* @return See above.
*/
public boolean isOverride() { return override; }
}