X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fio%2FJalviewFileChooser.java;h=079cc09e367688f4850b13099be4a9a591dc52bd;hb=02e38bb826828ab2991584cf4b737c0138cb6c44;hp=5a29ba715dbb7481cf14f3f28caf0fc5bb897355;hpb=99c58ee0ae2a848f982552e53feaf6d5cb9925e5;p=jalview.git diff --git a/src/jalview/io/JalviewFileChooser.java b/src/jalview/io/JalviewFileChooser.java index 5a29ba7..079cc09 100755 --- a/src/jalview/io/JalviewFileChooser.java +++ b/src/jalview/io/JalviewFileChooser.java @@ -1,378 +1,408 @@ -/* -* Jalview - A Sequence Alignment Editor and Viewer -* Copyright (C) 2005 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle -* -* 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 -*/ - - -/*/////////////////////////////////////////////////////////////////// -// This file was taken from java forum -// Re: JFileChooser functioning like normal Windows Apps FileChooser -// Author: ddanimal -// http://forum.java.sun.com/thread.jspa?forumID=57&threadID=327712 -*/////////////////////////////////////////////////////////////////// - -package jalview.io; - -import java.awt.*; -import java.awt.event.*; -import java.io.*; -import java.util.*; - -import javax.swing.*; -import javax.swing.plaf.*; -import javax.swing.plaf.basic.*; -import javax.swing.plaf.metal.*; -import javax.swing.table.*; - -public class JalviewFileChooser extends JFileChooser -{ - - private static final int COLUMN_FILENAME = 0; - private static final int COLUMN_FILESIZE = 1; - private static final int COLUMN_FILETYPE = 2; - private static final int COLUMN_FILEDATE = 3; - private static final int COLUMN_FILEATTR = 4; - private static final int COLUMN_COLCOUNT = 5; - private static String[] COLUMNS = null; - - - public JalviewFileChooser(String dir, String [] suffix, String [] desc, String selected) - { - super(dir); - - JalviewFileFilter chosen = null; - for(int i=0; i 1) return; - e.consume(); - final int col = tbl.getTableHeader().columnAtPoint(e.getPoint()); - if (col == COLUMN_FILENAME || col == COLUMN_FILESIZE || - col == COLUMN_FILEDATE) - model.sort(col,tbl); - } - }); - } - return panel; - } - - /************************************************************************** - * Finds the JTable in the panel so we can add MouseListener - * @param comp - * @return - *************************************************************************/ - private final static JTable findJTable(Component[] comp) - { - for (int i=0;i b.lastModified(); - break; - case COLUMN_FILESIZE: - less = a.length() > b.length(); - break; - default: - less = a.getName().compareToIgnoreCase(b.getName()) > 0; - break; - } - if (ascending) return less = !less; - return less; - } - - /************************************************************************** - * Resorts the JFileChooser table based on new column - * @param c - *************************************************************************/ - protected final void sort(int c, JTable tbl) - { - //Set column and order - col = c; - ascending = !ascending; - String indicator = " (^)"; - if (ascending) - indicator = " (v)"; - - final JTableHeader th = tbl.getTableHeader(); - final TableColumnModel tcm = th.getColumnModel(); - - for (int i=0;i b.lastModified()) - ret = -1; - else if (a.lastModified() == b.lastModified()) - ret = 0; - - if (ascending) - ret *= -1; - return ret; - } - - }); - break; - case COLUMN_FILESIZE: - Collections.sort(data,new Comparator(){ - public int compare(Object o1,Object o2) - { - int ret = 1; - final File a = (File)o1; - final File b = (File)o2; - if (a.length() > b.length()) - ret = -1; - else if (a.length() == b.length()) - ret = 0; - - if (ascending) - ret *= -1; - return ret; - } - - }); - break; - case COLUMN_FILENAME: - Collections.sort(data,new Comparator(){ - public int compare(Object o1,Object o2) - { - final File a = (File)o1; - final File b = (File)o2; - if (ascending) - return a.getName().compareToIgnoreCase(b.getName()); - else - return -1 * a.getName().compareToIgnoreCase(b.getName()); - } - - }); - break; - } - } - } -} - +/* + * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$) + * Copyright (C) $$Year-Rel$$ The Jalview Authors + * + * This file is part of Jalview. + * + * Jalview 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. + * + * Jalview 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 Jalview. If not, see . + * The Jalview Authors are detailed in the 'AUTHORS' file. + */ +////////////////////////////////////////////////////////////////// +package jalview.io; + +import jalview.util.MessageManager; +import jalview.util.Platform; + +import java.awt.Component; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.HeadlessException; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.io.File; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.StringTokenizer; +import java.util.Vector; + +import javax.swing.DefaultListCellRenderer; +import javax.swing.JFileChooser; +import javax.swing.JList; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.SpringLayout; +import javax.swing.filechooser.FileView; +import javax.swing.plaf.basic.BasicFileChooserUI; + +/** + * Enhanced file chooser dialog box. + * + * NOTE: bug on Windows systems when filechooser opened on directory to view + * files with colons in title. + * + * @author AMW + * + */ +public class JalviewFileChooser extends JFileChooser +{ + /** + * Factory method to return a file chooser that offers readable alignment file + * formats + * + * @param directory + * @param selected + * @param selectAll + * @return + */ + public static JalviewFileChooser forRead(String directory, + String selected, boolean selectAll) + { + List extensions = new ArrayList(); + List descs = new ArrayList(); + for (FileFormatI format : FileFormat.values()) + { + if (format.isReadable()) + { + extensions.add(format.getExtensions()); + descs.add(format.toString()); + } + } + return new JalviewFileChooser(directory, + extensions.toArray(new String[extensions.size()]), + descs.toArray(new String[descs.size()]), + selected); + } + + /** + * Factory method to return a file chooser that offers writable alignment file + * formats + * + * @param directory + * @param selected + * @param selectAll + * @return + */ + public static JalviewFileChooser forWrite(String directory, + String selected, boolean selectAll) + { + // TODO in Java 8, forRead and forWrite can be a single method + // with a lambda expression parameter for isReadable/isWritable + List extensions = new ArrayList(); + List descs = new ArrayList(); + for (FileFormatI format : FileFormat.values()) + { + if (format.isWritable()) + { + extensions.add(format.getExtensions()); + descs.add(format.toString()); + } + } + return new JalviewFileChooser(directory, + extensions.toArray(new String[extensions.size()]), + descs.toArray(new String[descs.size()]), selected); + } + + public JalviewFileChooser(String dir) + { + super(safePath(dir)); + setAccessory(new RecentlyOpened()); + } + + public JalviewFileChooser(String dir, String extension, String desc, + String selected) + { + super(safePath(dir)); + init(Collections.singletonList(new String[] { extension, desc }), + selected); + } + + public JalviewFileChooser(String dir, String[] extensions, String[] descs, + String selected) + { + super(safePath(dir)); + if (extensions.length == descs.length) + { + List formats = new ArrayList(); + for (int i = 0; i < extensions.length; i++) + { + formats.add(new String[] { extensions[i], descs[i] }); + } + init(formats, selected); + } + else + { + System.err.println("JalviewFileChooser arguments mismatch: " + + extensions + ", " + descs); + } + } + + private static File safePath(String dir) + { + if (dir == null) + { + return null; + } + + File f = new File(dir); + if (f.getName().indexOf(':') > -1) + { + return null; + } + return f; + } + + /** + * + * @param formats + * a list of {extensions, description} for each file format + * @param selected + */ + void init(List formats, String selected) + { + + JalviewFileFilter chosen = null; + + // SelectAllFilter needs to be set first before adding further + // file filters to fix bug on Mac OSX + setAcceptAllFileFilterUsed(true); + + for (String[] format : formats) + { + JalviewFileFilter jvf = new JalviewFileFilter(format[0], format[1]); + addChoosableFileFilter(jvf); + if ((selected != null) && selected.equalsIgnoreCase(format[1])) + { + chosen = jvf; + } + } + + if (chosen != null) + { + setFileFilter(chosen); + } + + setAccessory(new RecentlyOpened()); + } + + @Override + public void setFileFilter(javax.swing.filechooser.FileFilter filter) + { + super.setFileFilter(filter); + + try + { + if (getUI() instanceof BasicFileChooserUI) + { + final BasicFileChooserUI fcui = (BasicFileChooserUI) getUI(); + final String name = fcui.getFileName().trim(); + + if ((name == null) || (name.length() == 0)) + { + return; + } + + EventQueue.invokeLater(new Thread() + { + @Override + public void run() + { + String currentName = fcui.getFileName(); + if ((currentName == null) || (currentName.length() == 0)) + { + fcui.setFileName(name); + } + } + }); + } + } catch (Exception ex) + { + ex.printStackTrace(); + // Some platforms do not have BasicFileChooserUI + } + } + + /** + * Returns the selected file format, or null if none selected + * + * @return + */ + public FileFormatI getSelectedFormat() + { + if (getFileFilter() == null) + { + return null; + } + + /* + * logic here depends on option description being formatted as + * formatName (extension, extension...) + * or the 'no option selected' value + * All Files + * @see JalviewFileFilter.getDescription + */ + String format = getFileFilter().getDescription(); + int parenPos = format.indexOf("("); + if (parenPos > 0) + { + format = format.substring(0, parenPos).trim(); + try + { + return FileFormat.valueOf(format); + } catch (IllegalArgumentException e) + { + System.err.println("Unexpected format: " + format); + } + } + return null; + } + + @Override + public int showSaveDialog(Component parent) throws HeadlessException + { + this.setAccessory(null); + + setDialogType(SAVE_DIALOG); + + int ret = showDialog(parent, MessageManager.getString("action.save")); + + if (getFileFilter() instanceof JalviewFileFilter) + { + JalviewFileFilter jvf = (JalviewFileFilter) getFileFilter(); + + if (!jvf.accept(getSelectedFile())) + { + String withExtension = getSelectedFile() + "." + + jvf.getAcceptableExtension(); + setSelectedFile(new File(withExtension)); + } + } + // TODO: ENSURE THAT FILES SAVED WITH A ':' IN THE NAME ARE REFUSED AND THE + // USER PROMPTED FOR A NEW FILENAME + if ((ret == JalviewFileChooser.APPROVE_OPTION) + && getSelectedFile().exists()) + { + int confirm = JOptionPane.showConfirmDialog(parent, + MessageManager.getString("label.overwrite_existing_file"), + MessageManager.getString("label.file_already_exists"), + JOptionPane.YES_NO_OPTION); + + if (confirm != JOptionPane.YES_OPTION) + { + ret = JalviewFileChooser.CANCEL_OPTION; + } + } + + return ret; + } + + void recentListSelectionChanged(Object selection) + { + setSelectedFile(null); + if (selection != null) + { + File file = new File((String) selection); + if (getFileFilter() instanceof JalviewFileFilter) + { + JalviewFileFilter jvf = (JalviewFileFilter) this.getFileFilter(); + + if (!jvf.accept(file)) + { + setFileFilter(getChoosableFileFilters()[0]); + } + } + + setSelectedFile(file); + } + } + + class RecentlyOpened extends JPanel + { + JList list; + + public RecentlyOpened() + { + + String historyItems = jalview.bin.Cache.getProperty("RECENT_FILE"); + StringTokenizer st; + Vector recent = new Vector(); + + if (historyItems != null) + { + st = new StringTokenizer(historyItems, "\t"); + + while (st.hasMoreTokens()) + { + recent.addElement(st.nextElement()); + } + } + + list = new JList(recent); + + DefaultListCellRenderer dlcr = new DefaultListCellRenderer(); + dlcr.setHorizontalAlignment(DefaultListCellRenderer.RIGHT); + list.setCellRenderer(dlcr); + + list.addMouseListener(new MouseAdapter() + { + @Override + public void mousePressed(MouseEvent evt) + { + recentListSelectionChanged(list.getSelectedValue()); + } + }); + + this.setBorder(new javax.swing.border.TitledBorder(MessageManager + .getString("label.recently_opened"))); + + final JScrollPane scroller = new JScrollPane(list); + + SpringLayout layout = new SpringLayout(); + layout.putConstraint(SpringLayout.WEST, scroller, 5, + SpringLayout.WEST, this); + layout.putConstraint(SpringLayout.NORTH, scroller, 5, + SpringLayout.NORTH, this); + + if (new Platform().isAMac()) + { + scroller.setPreferredSize(new Dimension(500, 100)); + } + else + { + scroller.setPreferredSize(new Dimension(130, 200)); + } + + this.add(scroller); + + javax.swing.SwingUtilities.invokeLater(new Runnable() + { + @Override + public void run() + { + scroller.getHorizontalScrollBar().setValue( + scroller.getHorizontalScrollBar().getMaximum()); + } + }); + + } + + } + + @Override + public void setFileView(FileView fileView) + { + // do nothing - does it matter? + } +}