// Copyrigh 2003-2007, FreeHEP.
package org.freehep.util.export;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.Vector;
import javax.swing.DefaultListCellRenderer;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
import org.freehep.swing.ErrorDialog;
import org.freehep.swing.layout.TableLayout;
/**
* An "Export" dialog for saving components as graphic files.
*
* @author tonyj
* @version $Id: ExportDialog.java 12746 2007-06-12 22:18:45Z duns $
*/
public class ExportDialog extends JOptionPane
{
private static final String rootKey = ExportDialog.class.getName();
private static final String SAVE_AS_TYPE = rootKey +".SaveAsType";
private static final String SAVE_AS_FILE = rootKey +".SaveAsFile";
/**
* Set the Properties object to be used for storing/restoring
* user preferences. If not called user preferences will not be
* saved.
* @param properties The Properties to use for user preferences
*/
public void setUserProperties(Properties properties)
{
props = properties;
}
/**
* Register an export file type.
*/
public void addExportFileType(ExportFileType fileType)
{
list.addElement(fileType);
}
public void addAllExportFileTypes()
{
ExportFileTypeGroups groups = new ExportFileTypeGroups(ExportFileType.getExportFileTypes());
for (Iterator i=groups.getGroupNames().iterator(); i.hasNext(); ) {
String group = (String)i.next();
List exportTypes = groups.getExportFileTypes(group);
if (exportTypes.size() > 0) {
list.add(new JLabel(groups.getLabel(group), SwingConstants.CENTER));
Collections.sort(exportTypes);
for (Iterator j=exportTypes.iterator(); j.hasNext(); ) {
addExportFileType((ExportFileType)j.next());
}
}
}
}
/**
* Creates a new instance of ExportDialog with all the standard export filetypes.
*/
public ExportDialog()
{
this(null);
}
/**
* Creates a new instance of ExportDialog with all the standard export filetypes.
* @param creator The "creator" to be written into the header of the file (may be null)
*/
public ExportDialog(String creator)
{
this(creator, true);
}
/**
* Creates a new instance of ExportDialog.
* @param creator The "creator" to be written into the header of the file (may be null)
* @param addAllExportFileTypes If true registers all the standard export filetypes
*/
public ExportDialog(String creator, boolean addAllExportFileTypes)
{
super(null,JOptionPane.PLAIN_MESSAGE,JOptionPane.OK_CANCEL_OPTION);
this.creator = creator;
try
{
baseDir = System.getProperty("user.home");
}
catch (SecurityException x) { trusted = false; }
ButtonListener bl = new ButtonListener();
JPanel panel = new JPanel(new TableLayout());
if (trusted)
{
panel.add("* * [5 5 5 5] w", file);
panel.add("* * * 1 [5 5 5 5] wh", browse);
}
type = new JComboBox(list);
type.setMaximumRowCount(16); // rather than 8
panel.add("* * 1 1 [5 5 5 5] w", type);
panel.add("* * * 1 [5 5 5 5] wh", advanced);
browse.addActionListener(bl);
advanced.addActionListener(bl);
type.setRenderer(new SaveAsRenderer());
type.addActionListener(bl);
setMessage(panel);
if (addAllExportFileTypes) addAllExportFileTypes();
}
/**
* Show the dialog.
* @param parent The parent for the dialog
* @param title The title for the dialog
* @param target The component to be saved.
* @param size The target size to be used for export.
* @param defFile The default file name to use.
*/
public void showExportDialog(Component parent, String title, Component target, Dimension size, String defFile)
{
// NOTE: same, and used in AbstractExportFileType
props.setProperty("size-w", String.valueOf(size.width));
props.setProperty("size-h", String.valueOf(size.height));
showExportDialog(parent, title, target, defFile);
}
/**
* Show the dialog.
* @param parent The parent for the dialog
* @param title The title for the dialog
* @param target The component to be saved.
* @param defFile The default file name to use.
*/
public void showExportDialog(Component parent, String title, Component target, String defFile)
{
this.component = target;
// NOTE: a label is always first
if (list.size() > 0) type.setSelectedIndex(1);
String dType = props.getProperty(SAVE_AS_TYPE);
if (dType != null)
{
for (int i=0; i<list.size(); i++)
{
Object obj = list.elementAt(i);
if (obj instanceof ExportFileType) {
ExportFileType saveAs = (ExportFileType)obj;
if (saveAs.getFileFilter().getDescription().equals(dType))
{
type.setSelectedItem(saveAs);
break;
}
}
}
}
advanced.setEnabled(currentType() != null && currentType().hasOptionPanel());
if (trusted)
{
String saveFile = props.getProperty(SAVE_AS_FILE);
if (saveFile != null) {
baseDir = new File(saveFile).getParent();
defFile = saveFile;
} else {
defFile = baseDir+File.separator+defFile;
}
File f = new File(defFile);
if (currentType() != null) f = currentType().adjustFilename(f, currentType().getFileExtension(f), props);
file.setText(f.toString());
}
else
{
file.setEnabled(false);
browse.setEnabled(false);
}
JDialog dlg = createDialog(parent,title);
dlg.pack();
dlg.setVisible(true);
}
private ExportFileType currentType()
{
return (ExportFileType)type.getSelectedItem();
}
/**
* Called to open a "file browser". Override this method to provide
* special handling (e.g. in a WebStart app)
* @return The full name of the selected file, or null if no file selected
*/
protected String selectFile()
{
JFileChooser dlg = new JFileChooser();
String f = file.getText();
if (f != null) dlg.setSelectedFile(new File(f));
dlg.setFileFilter(currentType().getFileFilter());
if (dlg.showDialog(this, "Select") == JFileChooser.APPROVE_OPTION) {
return dlg.getSelectedFile().getAbsolutePath();
} else {
return null;
}
}
/**
* Called to acually write out the file.
* Override this method to provide special handling (e.g. in a WebStart app)
* @return true if the file was written, or false to cancel operation
*/
protected boolean writeFile(Component component, ExportFileType t) throws IOException
{
File f = new File(file.getText());
if (f.exists())
{
int ok = JOptionPane.showConfirmDialog(this,"Replace existing file?");
if (ok != JOptionPane.OK_OPTION) return false;
}
t.exportToFile(f,component,this,props,creator);
props.put(SAVE_AS_FILE,file.getText());
props.put(SAVE_AS_TYPE,currentType().getFileFilter().getDescription());
return true;
}
public void setValue(Object value)
{
if (value instanceof Integer && ((Integer) value).intValue() == OK_OPTION)
{
try
{
if (!writeFile(component,currentType())) return;
}
catch (Throwable x)
{
ErrorDialog.showErrorDialog(this,"Error writing graphics file",x);
return;
}
}
super.setValue(value);
}
private String creator;
private JButton browse = new JButton("Browse...");
private JButton advanced = new JButton("Options...");
private JTextField file = new JTextField(40);
private JComboBox type;
private Component component;
private boolean trusted = true;
private Vector list = new Vector();
private Properties props = new Properties();
private String baseDir = null;
private class ButtonListener implements ActionListener
{
private ExportFileType previousType = null;
public void actionPerformed(ActionEvent e)
{
Object source = e.getSource();
if (source == browse)
{
String fileName = selectFile();
if (fileName != null) {
if (currentType() != null) {
File f = new File(fileName);
currentType().adjustFilename(f, currentType().getFileExtension(f), props);
file.setText(f.getPath());
} else {
file.setText(fileName);
}
}
}
else if (source == advanced)
{
if (currentType() != null) {
JPanel panel = currentType().createOptionPanel(props);
int rc = JOptionPane.showConfirmDialog(ExportDialog.this,panel,"Options for "+currentType().getDescription(),
JOptionPane.OK_CANCEL_OPTION,JOptionPane.PLAIN_MESSAGE);
if (rc == JOptionPane.OK_OPTION) {
currentType().applyChangedOptions(panel, props);
File f1 = new File(file.getText());
File f2 = currentType().adjustFilename(f1, currentType().getFileExtension(f1), props);
if (!f1.equals(f2) && file.isEnabled()) file.setText(f2.toString());
}
}
}
else if (source == type)
{
if (type.getSelectedItem() instanceof ExportFileType) {
if (previousType == null) previousType = currentType();
advanced.setEnabled(currentType().hasOptionPanel());
File f1 = new File(file.getText());
File f2 = currentType().adjustFilename(f1, previousType.getFileExtension(f1), props);
if (!f1.equals(f2) && file.isEnabled()) file.setText(f2.toString());
previousType = currentType();
} else {
// keep old selection
type.setSelectedItem(previousType);
}
}
}
}
private static class SaveAsRenderer extends DefaultListCellRenderer
{
public Component getListCellRendererComponent(JList list,
Object value,
int index,
boolean isSelected,
boolean cellHasFocus)
{
super.getListCellRendererComponent(list,value,index,isSelected,cellHasFocus);
if (value instanceof ExportFileType)
{
this.setText(((ExportFileType) value).getFileFilter().getDescription());
} else if (value instanceof JLabel) {
return (Component)value;
}
return this;
}
}
}