/* FileSelectPanel.java
*
*/
package org.signalml.app.view.common.components.filechooser;
import static org.signalml.app.util.i18n.SvarogI18n._;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.regex.Pattern;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.filechooser.FileNameExtensionFilter;
import org.apache.log4j.Logger;
/**
* This class represents a panel which may be used to select a file.
* It contains text fields where a file name can be entered, a label for this
* field (which can be set in the constructor) and a button which opens a dialog
* using which a file path can be selected more conveniently.
*/
public class FileSelectPanel extends JPanel {
private static final long serialVersionUID = 1L;
protected static final Logger logger = Logger.getLogger(FileSelectPanel.class);
/**
* Label for the fileNameField.
*/
private JLabel selectFileLabel;
/**
* A text field where file name can be entered.
*/
private JTextField fileNameField;
/**
* A button for opening a file chooser dialog using which a file path
* can be selected more conveniently.
*/
private JButton browseButton;
/**
* List of filters the user can choose from. The key is the file description,
* the value is the file extensions array. If the selected file doesn't exist,
* first extension in the array will be added to it's name.
*/
private HashMap<String, String[]> filters;
/**
* Indicates if the "All files" filter is available
*/
private boolean allFilters;
/**
* Browse button action.
*/
private BrowseButtonAction browseButtonAction;
/**
* This is the default constructor
*/
public FileSelectPanel(String selectFilePrompt) {
super();
this.selectFileLabel = new JLabel(selectFilePrompt);
initialize();
}
/**
* This constructor takes two additional parameters: {@link #filters} and {@link #allFilters}
*/
public FileSelectPanel(String selectFilePrompt, HashMap<String, String[]> filters, boolean allFilters) {
super();
this.selectFileLabel = new JLabel(selectFilePrompt);
this.filters = filters;
this.allFilters = allFilters;
initialize();
}
/**
* Initializes this panel.
*/
private void initialize() {
setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
c.fill = GridBagConstraints.HORIZONTAL;
c.anchor = GridBagConstraints.WEST;
c.gridx = 0;
c.weightx = 100;
c.insets = new Insets(0, 2, 0, 2);
add(selectFileLabel, c);
c.weightx = 1;
c.gridx = 1;
add(getFileNameField(), c);
c.weightx = 0;
c.gridx = 2;
add(getChangeButton(), c);
}
/**
* Returns the {@link JTextField} which can be used to input
* a file name.
* @return the {@link JTextField} used in this panel
*/
public JTextField getFileNameField() {
if (fileNameField == null) {
fileNameField = new JTextField(18);
}
return fileNameField;
}
/**
* Returns a {@link JButton} which opens a {@link JFileChooser} to
* which allows to select a file path.
* @return a {@link JButton} allowing to browse through directories
* and choose a file path
*/
protected JButton getChangeButton() {
if (browseButton == null) {
browseButton = new JButton(_("Browse"));
if (filters == null)
browseButtonAction = new BrowseButtonAction();
else
browseButtonAction = new BrowseButtonAction(filters, allFilters);
browseButton.addActionListener(browseButtonAction);
}
return browseButton;
}
/**
* Sets the file name which shows in the file name text field.
* @param fileName a value of file name to be set
*/
public void setFileName(String fileName) {
this.fileNameField.setText(fileName);
}
/**
* Returns the file name selected in this panel.
* @return a file name which was selected using this panel.
*/
public String getFileName() {
return this.fileNameField.getText();
}
/**
* Whether the file chooser should return a relative path.
*
* @param ret if true, a relative path will be returned
*/
public void returnRelativePath(boolean ret) {
browseButtonAction.setReturnRelativePath(ret);
}
/**
* Returns whether a file was selected using this panel or not.
* @return true if the file is selected, false otherwise
*/
public boolean isFileSelected() {
String t = getFileNameField().getText();
if (t != null && !"".equals(t)) {
return true;
} else {
return false;
}
}
/**
* Sets the state (enabled/disabled) of this component.
* @param enabled true if this panel should be enabled, false otherwise.
*/
@Override
public void setEnabled(boolean enabled) {
super.setEnabled(enabled);
selectFileLabel.setEnabled(enabled);
fileNameField.setEnabled(enabled);
browseButton.setEnabled(enabled);
}
/**
* Class responsible for the action performed after pressing Browse button.
* Shows a window in which the user can choose a file name's path and changes the
* text field containing the file name in the current FileSelectPanel.
*/
private class BrowseButtonAction implements ActionListener {
/**
* A file chooser to select files with. Shows in response to
* this action.
*/
private JFileChooser fileChooser;
/**
* List of filters the user can choose from. The key is the file description,
* the value is the file extensions array.
*/
private HashMap<String, String[]> filters;
/**
* If true the file chooser will return a relative path.
*/
private boolean returnRelativePath = false;
/**
* Creates a new BrowseButtonAction and initializes it.
*/
public BrowseButtonAction() {
super();
fileChooser = new JFileChooser();
fileChooser.setApproveButtonText(_("Ok"));
}
/**
* Creates a new BrowseButtonAction and initializes it with filters.
*
* @param filters filter collection
* @param allFilters wheter the all files filter should be included
*/
public BrowseButtonAction(HashMap<String, String[]> filters, boolean allFilters) {
super();
fileChooser = new JFileChooser();
fileChooser.setApproveButtonText(_("Ok"));
fileChooser.setAcceptAllFileFilterUsed(allFilters);
for (String description : filters.keySet()) {
FileNameExtensionFilter filter = new FileNameExtensionFilter(description, filters.get(description));
fileChooser.addChoosableFileFilter(filter);
}
this.filters = filters;
}
/**
* Wheter the file chooser should return a relative path.
*
* @param ret if true a relative path will be returned
*/
public void setReturnRelativePath(boolean ret) {
returnRelativePath = ret;
}
/**
* Gets a relative path.
*
* @param absolutePath the absolute path
* @return the relative path
*/
private String getRelativePath(String absolutePath) {
String basePath = (new File(".")).getAbsolutePath();
String pathSeparator = "/";
File f = new File(absolutePath);
boolean isDir = f.isDirectory();
String[] base = basePath.split(Pattern.quote(pathSeparator), -1);
String[] target = absolutePath.split(Pattern.quote(pathSeparator), 0);
String common = "";
int commonIndex = 0;
for (int i = 0; i < target.length && i < base.length; i++) {
if (target[i].equals(base[i])) {
common += target[i] + pathSeparator;
commonIndex++;
}
else break;
}
if (commonIndex == 0)
{
return absolutePath;
}
String relative = "";
if (base.length == commonIndex) {
relative = "." + pathSeparator;
} else {
int numDirsUp = base.length - commonIndex - (isDir ? 0 : 1);
for (int i = 1; i <= numDirsUp; i++) {
relative += ".." + pathSeparator;
}
}
if (absolutePath.length() > common.length()) {
relative += absolutePath.substring(common.length());
}
return relative;
}
@Override
public void actionPerformed(ActionEvent e) {
int returnVal = fileChooser.showOpenDialog(FileSelectPanel.this);
if (returnVal == JFileChooser.APPROVE_OPTION) {
File selectedFile = fileChooser.getSelectedFile();
try {
getFileNameField().setText(selectedFile.getCanonicalPath());
} catch (IOException e1) {
getFileNameField().setText("");
}
if (fileChooser.getFileFilter() instanceof FileNameExtensionFilter)
{
FileNameExtensionFilter filter = (FileNameExtensionFilter) fileChooser.getFileFilter();
String extension = filters.get(filter.getDescription())[0];
if (!getFileNameField().getText().endsWith(extension))
getFileNameField().setText(getFileNameField().getText() + "." + extension);
}
if (returnRelativePath) {
getFileNameField().setText(getRelativePath(getFileNameField().getText()));
}
}
}
}
}