merge from 2_4_Release branch
[jalview.git] / src / jalview / io / JalviewFileChooser.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.4)
3  * Copyright (C) 2008 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle
4  * 
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  * 
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  * 
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
18  */
19 //////////////////////////////////////////////////////////////////
20 package jalview.io;
21
22 import java.io.*;
23 import java.util.*;
24
25 import java.awt.*;
26 import java.awt.event.*;
27 import javax.swing.*;
28
29 /**
30  * Enhanced file chooser dialog box.
31  * 
32  * NOTE: bug on Windows systems when filechooser opened on directory to view
33  * files with colons in title.
34  * 
35  * @author AMW
36  * 
37  */
38 public class JalviewFileChooser extends JFileChooser
39 {
40   public JalviewFileChooser(String dir)
41   {
42     super(safePath(dir));
43     setAccessory(new RecentlyOpened());
44   }
45
46   private static File safePath(String dir)
47   {
48     if (dir == null)
49     {
50       return null;
51     }
52
53     File f = new File(dir);
54     if (f.getName().indexOf(':') > -1)
55     {
56       return null;
57     }
58     return f;
59   }
60
61   public JalviewFileChooser(String dir, String[] suffix, String[] desc,
62           String selected, boolean selectAll)
63   {
64     super(safePath(dir));
65     init(suffix, desc, selected, selectAll);
66   }
67
68   public JalviewFileChooser(String dir, String[] suffix, String[] desc,
69           String selected)
70   {
71     super(safePath(dir));
72     init(suffix, desc, selected, true);
73   }
74
75   void init(String[] suffix, String[] desc, String selected,
76           boolean selectAll)
77   {
78
79     JalviewFileFilter chosen = null;
80
81     // SelectAllFilter needs to be set first before adding further
82     // file filters to fix bug on Mac OSX
83     setAcceptAllFileFilterUsed(selectAll);
84
85     for (int i = 0; i < suffix.length; i++)
86     {
87       JalviewFileFilter jvf = new JalviewFileFilter(suffix[i], desc[i]);
88       addChoosableFileFilter(jvf);
89
90       if ((selected != null) && selected.equalsIgnoreCase(desc[i]))
91       {
92         chosen = jvf;
93       }
94     }
95
96     if (chosen != null)
97     {
98       setFileFilter(chosen);
99     }
100
101     setAccessory(new RecentlyOpened());
102   }
103
104   public void setFileFilter(javax.swing.filechooser.FileFilter filter)
105   {
106     super.setFileFilter(filter);
107
108     try
109     {
110       if (getUI() instanceof javax.swing.plaf.basic.BasicFileChooserUI)
111       {
112         final javax.swing.plaf.basic.BasicFileChooserUI ui = (javax.swing.plaf.basic.BasicFileChooserUI) getUI();
113         final String name = ui.getFileName().trim();
114
115         if ((name == null) || (name.length() == 0))
116         {
117           return;
118         }
119
120         EventQueue.invokeLater(new Thread()
121         {
122           public void run()
123           {
124             String currentName = ui.getFileName();
125             if ((currentName == null) || (currentName.length() == 0))
126             {
127               ui.setFileName(name);
128             }
129           }
130         });
131       }
132     } catch (Exception ex)
133     {
134       ex.printStackTrace();
135       // Some platforms do not have BasicFileChooserUI
136     }
137   }
138
139   public String getSelectedFormat()
140   {
141     if (getFileFilter() == null)
142     {
143       return null;
144     }
145
146     String format = getFileFilter().getDescription();
147
148     if (format.toUpperCase().startsWith("JALVIEW"))
149     {
150       format = "Jalview";
151     }
152     else if (format.toUpperCase().startsWith("FASTA"))
153     {
154       format = "FASTA";
155     }
156     else if (format.toUpperCase().startsWith("MSF"))
157     {
158       format = "MSF";
159     }
160     else if (format.toUpperCase().startsWith("CLUSTAL"))
161     {
162       format = "CLUSTAL";
163     }
164     else if (format.toUpperCase().startsWith("BLC"))
165     {
166       format = "BLC";
167     }
168     else if (format.toUpperCase().startsWith("PIR"))
169     {
170       format = "PIR";
171     }
172     else if (format.toUpperCase().startsWith("PFAM"))
173     {
174       format = "PFAM";
175     }
176
177     return format;
178   }
179
180   public int showSaveDialog(Component parent) throws HeadlessException
181   {
182     this.setAccessory(null);
183
184     setDialogType(SAVE_DIALOG);
185
186     int ret = showDialog(parent, "Save");
187
188     if (getFileFilter() instanceof JalviewFileFilter)
189     {
190       JalviewFileFilter jvf = (JalviewFileFilter) getFileFilter();
191
192       if (!jvf.accept(getSelectedFile()))
193       {
194         String withExtension = getSelectedFile() + "."
195                 + jvf.getAcceptableExtension();
196         setSelectedFile(new File(withExtension));
197       }
198     }
199     // TODO: ENSURE THAT FILES SAVED WITH A ':' IN THE NAME ARE REFUSED AND THE
200     // USER PROMPTED FOR A NEW FILENAME
201     if ((ret == JalviewFileChooser.APPROVE_OPTION)
202             && getSelectedFile().exists())
203     {
204       int confirm = JOptionPane.showConfirmDialog(parent,
205               "Overwrite existing file?", "File exists",
206               JOptionPane.YES_NO_OPTION);
207
208       if (confirm != JOptionPane.YES_OPTION)
209       {
210         ret = JalviewFileChooser.CANCEL_OPTION;
211       }
212     }
213
214     return ret;
215   }
216
217   void recentListSelectionChanged(String selection)
218   {
219     setSelectedFile(null);
220
221     File file = new File(selection);
222     if (getFileFilter() instanceof JalviewFileFilter)
223     {
224       JalviewFileFilter jvf = (JalviewFileFilter) this.getFileFilter();
225
226       if (!jvf.accept(file))
227       {
228         setFileFilter(getChoosableFileFilters()[0]);
229       }
230     }
231
232     setSelectedFile(file);
233   }
234
235   class RecentlyOpened extends JPanel
236   {
237     JList list;
238
239     public RecentlyOpened()
240     {
241       String historyItems = jalview.bin.Cache.getProperty("RECENT_FILE");
242       StringTokenizer st;
243       Vector recent = new Vector();
244
245       if (historyItems != null)
246       {
247         st = new StringTokenizer(historyItems, "\t");
248
249         while (st.hasMoreTokens())
250         {
251           recent.addElement(st.nextElement());
252         }
253       }
254
255       list = new JList(recent);
256
257       DefaultListCellRenderer dlcr = new DefaultListCellRenderer();
258       dlcr.setHorizontalAlignment(DefaultListCellRenderer.RIGHT);
259       list.setCellRenderer(dlcr);
260
261       list.addMouseListener(new MouseAdapter()
262       {
263         public void mousePressed(MouseEvent evt)
264         {
265           recentListSelectionChanged(list.getSelectedValue().toString());
266         }
267       });
268
269       this
270               .setBorder(new javax.swing.border.TitledBorder(
271                       "Recently Opened"));
272
273       final JScrollPane scroller = new JScrollPane(list);
274       scroller.setPreferredSize(new Dimension(130, 200));
275       this.add(scroller);
276
277       javax.swing.SwingUtilities.invokeLater(new Runnable()
278       {
279         public void run()
280         {
281           scroller.getHorizontalScrollBar().setValue(
282                   scroller.getHorizontalScrollBar().getMaximum());
283         }
284       });
285
286     }
287
288   }
289 }