/*
GanttProject is an opensource project management tool.
Copyright (C) 2005-2011 GanttProject team
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 3
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 net.sourceforge.ganttproject.gui;
import java.awt.Component;
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.Action;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SpringLayout;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.filechooser.FileFilter;
import javax.swing.text.JTextComponent;
import net.sourceforge.ganttproject.GPLogger;
import net.sourceforge.ganttproject.action.CancelAction;
import net.sourceforge.ganttproject.action.GPAction;
import net.sourceforge.ganttproject.action.OkAction;
import com.google.common.base.Objects;
/**
* @author bard
*/
public abstract class TextFieldAndFileChooserComponent extends JPanel {
private final JButton myChooserButton;
private final JTextField myTextField;
private File myFile;
private FileFilter myFileFilter;
private final String myDialogCaption;
private int myFileSelectionMode = JFileChooser.FILES_ONLY;
private boolean myProcessTextEventEnabled = true;
private final SpringLayout myLayout = new SpringLayout();
private final UIFacade myUiFacade;
public TextFieldAndFileChooserComponent(UIFacade uiFacade, String dialogCaption) {
myUiFacade = uiFacade;
myDialogCaption = dialogCaption;
setLayout(myLayout);
myChooserButton = new JButton(new GPAction("fileChooser.browse") {
@Override
public void actionPerformed(ActionEvent e) {
showFileChooser();
}
});
myTextField = new JTextField();
myTextField.getDocument().addDocumentListener(new DocumentListener() {
private final Timer myTimer = new Timer();
private TimerTask myTimerTask = null;
@Override
public void removeUpdate(DocumentEvent e) {
onChange();
}
@Override
public void insertUpdate(DocumentEvent e) {
onChange();
}
@Override
public void changedUpdate(DocumentEvent arg0) {
onChange();
}
private void onChange() {
if (myTimerTask == null && myProcessTextEventEnabled) {
myTimerTask = new TimerTask() {
@Override
public void run() {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
tryFile();
}
});
myTimerTask = null;
}
};
myTimer.schedule(myTimerTask, 1000);
}
}
});
// myChooserPanel = new JPanel(new BorderLayout());
add(myTextField);
add(myChooserButton);
// add(myChooserPanel);
myLayout.putConstraint(SpringLayout.WEST, myTextField, 0, SpringLayout.WEST, this);
myLayout.putConstraint(SpringLayout.NORTH, myTextField, 0, SpringLayout.NORTH, this);
myLayout.putConstraint(SpringLayout.WEST, myChooserButton, 3, SpringLayout.EAST, myTextField);
myLayout.putConstraint(SpringLayout.NORTH, myChooserButton, 0, SpringLayout.NORTH, this);
myLayout.putConstraint(SpringLayout.EAST, this, 0, SpringLayout.EAST, myChooserButton);
// myLayout.putConstraint(SpringLayout.NORTH, myChooserPanel, 3,
// SpringLayout.SOUTH, myChooserButton);
// myLayout.putConstraint(SpringLayout.WEST, myChooserPanel, 0,
// SpringLayout.WEST, myTextField);
// myLayout.putConstraint(SpringLayout.EAST, myChooserPanel, 0,
// SpringLayout.EAST, myChooserButton);
myLayout.putConstraint(SpringLayout.SOUTH, this, 0, SpringLayout.SOUTH, myChooserButton);
}
public File getFile() {
return myFile;
}
/**
* Updates the file path
*
* @param file
* if this is point to a directory, the previously used file name is
* added
*/
public void setFile(File file) {
if (file == null) {
return;
}
if (file.isDirectory()) {
// Add previously used file name because we need/like to select files
myFile = new File(file, (myFile == null ? "out" : myFile.getName()));
} else {
myFile = file;
}
if (myProcessTextEventEnabled) {
myTextField.setText(file.getAbsolutePath());
}
}
public void setFileFilter(FileFilter filter) {
myFileFilter = filter;
}
// public void setChooserHeight(int height) {
// Rectangle bounds = myChooserPanel.getBounds();
// myChooserPanel.setMinimumSize(new Dimension(bounds.width, height));
// myChooserPanel.setMaximumSize(new Dimension(bounds.width, height));
// myChooserPanel.setPreferredSize(new Dimension(bounds.width, height));
// this.doLayout();
// myChooserPanel.doLayout();
// myWizard.getDialog().layout();
// }
// public int getChooserHeight() {
// return getHeight();
// }
// protected void hideFileChooser() {
// Timeline t = new Timeline(this);
// t.addPropertyToInterpolate("chooserHeight", 0, myChooserPanel.getHeight());
// t.playReverse();
// myChooserPanel.removeAll();
// myFileChooser = null;
// }
public void showFileChooser() {
final JFileChooser fc = new JFileChooser(new File(myTextField.getText()));
File selectedFile = getFile();
fc.setCurrentDirectory(selectedFile == null ? getWorkingDir() : selectedFile.getParentFile());
fc.setDialogType(JFileChooser.SAVE_DIALOG);
fc.setDialogTitle(myDialogCaption);
fc.setControlButtonsAreShown(false);
fc.setApproveButtonToolTipText(myDialogCaption);
// fc.setFileSelectionMode(myFileSelectionMode);
//
// Remove the possibility to use a file filter for all files
FileFilter[] filefilters = fc.getChoosableFileFilters();
for (int i = 0; i < filefilters.length; i++) {
fc.removeChoosableFileFilter(filefilters[i]);
}
fc.addChoosableFileFilter(myFileFilter);
for (FileFilter ff : filefilters) {
fc.addChoosableFileFilter(ff);
}
fc.doLayout();
// fc.addPropertyChangeListener(JFileChooser.SELECTED_FILE_CHANGED_PROPERTY, new PropertyChangeListener() {
// @Override
// public void propertyChange(PropertyChangeEvent evt) {
// File f = (File) evt.getNewValue();
// if (f != null) {
// setFile(f);
// }
// }
// });
//
// myChooserPanel.add(fc, BorderLayout.CENTER);
// Timeline t = new Timeline(this);
// t.addPropertyToInterpolate("chooserHeight", 0,
// fc.getPreferredSize().height);
// t.play();
// myFileChooser = fc;
Action[] dialogActions = new Action[] { new OkAction() {
@Override
public void actionPerformed(ActionEvent e) {
File selected = fc.getSelectedFile();
if (selected == null || Objects.equal(selected, fc.getCurrentDirectory())) {
JTextComponent textField = getTextField(fc);
if (textField != null) {
String filename = textField.getText();
File currentDirectory = fc.getCurrentDirectory();
selected = new File(currentDirectory, filename);
}
}
setFile(selected);
onFileChosen(myFile);
}
private JTextComponent getTextField(Container container) {
JTextComponent result = null;
for (Component c : container.getComponents()) {
if (c instanceof JTextComponent) {
result = (JTextComponent) c;
return result;
}
if (c instanceof Container) {
result = getTextField((Container) c);
}
if (result != null) {
return result;
}
}
return null;
}
}, CancelAction.EMPTY };
// int result = fc.showSaveDialog(myUiFacade.getMainFrame());
// if (result == JFileChooser.APPROVE_OPTION) {
// setFile(fc.getSelectedFile());
// onFileChosen(myFile);
// }
myUiFacade.createDialog(fc, dialogActions, "").show();
}
private File getWorkingDir() {
return new File(System.getProperty("user.dir"));
}
public void tryFile() {
myProcessTextEventEnabled = false;
myFile = new File(myTextField.getText());
onFileChosen(myFile);
myProcessTextEventEnabled = true;
}
protected abstract void onFileChosen(File file);
public void setFileSelectionMode(int mode) {
myFileSelectionMode = mode;
}
public URL getSelectedURL() {
try {
return myFile == null ? new URL("file://" + myTextField.getText()) : myFile.toURI().toURL();
} catch (MalformedURLException e) {
GPLogger.log(e);
return null;
}
}
}