package jas.util; import java.awt.Dimension; import java.awt.Point; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.LineNumberReader; import java.io.Reader; import java.util.zip.GZIPInputStream; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JDialog; import javax.swing.JFileChooser; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.filechooser.FileFilter; /** * This class provides a convenient way to get a file name from the user. It is merely * a panel with a text field for the file name with some built in convenience items. * This panel does not actually open a file for you; it simply provides an easy way to get * a file name from the user. Use <code>getText()</code> to get the file name selected. * <ul> * <li>The text field is in fact a JASEditableComboBox, so recently selected files are * available on a drop-down list. The drop-down list is stored in the Application's * UserProperties object according to a key that you specify for the constructor.</li> * <li>A "Browse..." button opens a file dialog so that the user can select a file. * The object will remember the last directory used according to the given key and * open the dialog to that directory the next time it is opened.</li> * <li>Optionally, you can have a "Preview..." button that opens a dialog showing the * beginning of the file.</li> * <li>Optionally, you can have GZip option, where the user can select whether the file * in in GZip format.</li> * <li>If you add an <a href="http://www.javasoft.com/products/jdk/1.2/docs/api/java.awt.event.ActionListener.html">ActionListener</a> * to this class, you will receive <a href="http://www.javasoft.com/products/jdk/1.2/docs/api/java.awt.event.ActionEvent.html">ActionEvents</a> * from the JASEditableComboBox. An <a href="http://www.javasoft.com/products/jdk/1.2/docs/api/java.awt.event.ActionEvent.html">ActionEvent</a> * will be sent only when the 'Enter' button is clicked in the text field. Similarly, * if you add a <a href="http://java.sun.com/products/jfc/swingdoc-api/javax.swing.event.ChangeListener.html#_top_">ChangeListener</a> * to this class, you will receive <a href="http://java.sun.com/products/jfc/swingdoc-api/javax.swing.event.ChangeEvent.html#_top_">ChangeEvents</a> * from the JASEditableComboBox. A <a href="http://java.sun.com/products/jfc/swingdoc-api/javax.swing.event.ChangeEvent.html#_top_">ChangeEvent</a> * will be sent every time the visible text changes.</li> * </ul> * Be sure to invoke the <code>saveState()</code> method when you are done. This will set * include the selected file in the drop-down list for the next time the panel is used. * @author Jonas Gifford * @author Tony Johnson * @see JASEditableComboBox * @see UserProperties * @see #getText() * @see #saveState() */ public class OpenLocalFilePanel extends JPanel implements ActionListener, ChangeListener { /** * Creates an OpenLocalFilePanel component that you can add to a container. * @param includePreviewButton whether a "Preview" button should be shown * @param includeGZIP whether the GZip option should be shown * @param key the key used to store the drop-down items and the last directory for the browse dialog * @param filter sets a FileFilter for the browse dialog */ public OpenLocalFilePanel(boolean includePreviewButton, boolean includeGZIP, String key, FileFilter filter) { this(includePreviewButton, includeGZIP, key); m_filter = filter; } /** * Creates an OpenLocalFilePanel component that you can add to a container. * @param includePreviewButton whether a "Preview" button should be shown * @param includeGZIP whether the GZip option should be shown * @param key the key used to store the drop-down items and the last directory for the browse dialog */ public OpenLocalFilePanel(boolean includePreviewButton, boolean includeGZIP, String key) { m_lastLocalDirectory_Key = key +"-directory"; m_fileName = new JASEditableComboBox(key +"-files", 4, true); m_fileName.addChangeListener(this); m_fileName.setMinWidth(250); m_fileName.setMaxWidth(250); add(m_fileName); m_browse = new JButton("Browse..."); m_browse.addActionListener(this); m_browse.setMnemonic('B'); add(m_browse); if (includePreviewButton) { m_view = new JButton("Preview"); m_view.addActionListener(this); m_view.setMnemonic('V'); add(m_view); m_view.setEnabled(false); } if (includeGZIP) { m_gzip = new JCheckBox("GZIPed"); m_gzip.addActionListener(this); m_gzip.setMnemonic('Z'); add(m_gzip); m_gzip.setEnabled(false); } setBorder(BorderFactory.createTitledBorder("Enter the data file name")); setViewEnabled(); } /** * The given ChangeListener will be notified when the visible * text changes in the file name field. */ public void addChangeListener(ChangeListener cl) { m_fileName.addChangeListener(cl); } /** * The given ActionListener will be notified when the "Enter" button * is clicked in the file name text field. */ public void addActionListener(ActionListener al) { m_fileName.addActionListener(al); } /** This method is public as an implelentation side effect; do not call. */ public final void stateChanged(ChangeEvent e) { setViewEnabled(); } private void setViewEnabled() { String text = m_fileName.getText(); boolean enable = text.length() > 0; if (m_view != null) m_view.setEnabled(enable); if (m_gzip != null) { m_gzip.setEnabled(enable); m_gzip.setSelected(text.endsWith(".gz")); } } /** This method is public as an implelentation side effect; do not call. */ public final void actionPerformed(ActionEvent e) { Object source = e.getSource(); if (source == m_browse) { JFileChooser dlg = new JFileChooser(m_prop.getString(m_lastLocalDirectory_Key, System.getProperty("user.home"))); dlg.setDialogTitle("Select a file"); if (m_filter != null) dlg.setFileFilter(m_filter); if (dlg.showDialog(this, "Select") == JFileChooser.APPROVE_OPTION) { final File file = dlg.getSelectedFile(); m_fileName.setText(file.getAbsolutePath()); m_prop.setString(m_lastLocalDirectory_Key, file.getParent()); } } else if (source == m_view) { try { java.awt.Component c = this; while (! (c instanceof java.awt.Frame)) c = c.getParent(); new FilePreview((java.awt.Frame) c, new File(m_fileName.getText()), m_gzip == null ? false : m_gzip.isSelected()); } catch (Exception x) { JOptionPane.showMessageDialog(this, x instanceof FileNotFoundException ? "File not found" : "Could not read file", "Error...", JOptionPane.ERROR_MESSAGE); } } } /** * Returns the file name showing in the text field. * @return the selected file name */ public String getText() { String fileName = m_fileName.getText(); return fileName; } /** * Includes the currently selected file name in the drop-down list for the next time * this class is instantiated. It merely invokes the <code>saveState()</code> method in the * JASEditableComboBox that is shown on the panel. * @see JASEditableComboBox * @see JASEditableComboBox#saveState() */ public void saveState() { m_fileName.saveState(); } /** * Returns whether the user has selected the GZip option. If the GZip option was not * available (i.e., in the constructor the parameter <code>includeGZIP</code> was <code>false</code>) then it will * return <code>false</code>. * @return whether the GZip option was selected */ public boolean getGZIPed() { return m_gzip == null ? false : m_gzip.isSelected(); } private String m_lastLocalDirectory_Key; private JASEditableComboBox m_fileName; private JButton m_browse, m_view = null; private JCheckBox m_gzip = null; final private UserProperties m_prop = UserProperties.getUserProperties(); private FileFilter m_filter = null; } class FilePreview extends JDialog { FilePreview(java.awt.Frame frame, File f, boolean gzip) throws IOException, FileNotFoundException { super(frame, "File preview"); JTextArea text = new JTextArea(); if (!gzip) text.read(new PreviewReader(new FileReader(f)), f); else text.read(new PreviewReader(new InputStreamReader(new GZIPInputStream(new FileInputStream(f)))), f); text.setEditable(false); JScrollPane pane = new JScrollPane(text); setContentPane(pane); pack(); Dimension screenSize = getToolkit().getScreenSize(); Dimension dialogSize = getPreferredSize(); int maxHeight = (int) (screenSize.height * 0.6); if (dialogSize.height > maxHeight) dialogSize.height = maxHeight; int maxWidth = (int) (screenSize.width * 0.9); if (dialogSize.width > maxWidth) dialogSize.width = maxWidth; else dialogSize.width += 50; Point position = getLocation(); position.translate((screenSize.width-dialogSize.width)/2, (screenSize.height-dialogSize.height)/2); setLocation(position); setSize(dialogSize); show(); } } class PreviewReader extends LineNumberReader { PreviewReader(Reader r) { super(r); } public int read() throws IOException { return getLineNumber()>maxLines ? -1 : super.read(); } public int read(char[] cbuf, int off, int len) throws IOException { return getLineNumber()>maxLines ? -1 : super.read(cbuf,off,len); } public String readLine() throws IOException { return getLineNumber()>maxLines ? null : super.readLine(); } private final int maxLines = 100; }