basic fix for pfelkers problem with ':' in the last saved file history - outstanding...
[jalview.git] / src / jalview / io / JalviewFileChooser.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer
3  * Copyright (C) 2007 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 //////////////////////////////////////////////////////////////////
21 package jalview.io;
22
23 import java.io.*;
24 import java.util.*;
25
26 import java.awt.*;
27 import java.awt.event.*;
28 import javax.swing.*;
29 /**
30  * Enhanced file chooser dialog box.
31  * 
32  * NOTE: bug on Windows systems when filechooser opened on directory to view files with colons in title.
33  * 
34  * @author AMW
35  *
36  */
37 public class JalviewFileChooser
38     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     { return null;
50     }
51      
52     File f = new File(dir);
53     if (f.getName().indexOf(':')>-1)
54     {
55       return null;
56     }
57     return f;
58   }
59
60   public JalviewFileChooser(String dir,
61                             String[] suffix,
62                             String[] desc,
63                             String selected,
64                             boolean selectAll)
65   {
66     super(safePath(dir));
67     init(suffix, desc, selected, selectAll);
68   }
69
70   public JalviewFileChooser(String dir,
71                             String[] suffix,
72                             String[] desc,
73                             String selected)
74   {
75     super(safePath(dir));
76     init(suffix, desc, selected, true);
77   }
78
79   void init(String[] suffix,
80             String[] desc,
81             String selected,
82             boolean selectAll)
83   {
84
85     JalviewFileFilter chosen = null;
86
87     //SelectAllFilter needs to be set first before adding further
88     //file filters to fix bug on Mac OSX
89     setAcceptAllFileFilterUsed(selectAll);
90
91     for (int i = 0; i < suffix.length; i++)
92     {
93       JalviewFileFilter jvf = new JalviewFileFilter(suffix[i], desc[i]);
94       addChoosableFileFilter(jvf);
95
96       if ( (selected != null) && selected.equalsIgnoreCase(desc[i]))
97       {
98         chosen = jvf;
99       }
100     }
101
102     if (chosen != null)
103     {
104       setFileFilter(chosen);
105     }
106
107     setAccessory(new RecentlyOpened());
108   }
109
110   public void setFileFilter(javax.swing.filechooser.FileFilter filter)
111   {
112     super.setFileFilter(filter);
113
114     try
115     {
116       if (getUI() instanceof javax.swing.plaf.basic.BasicFileChooserUI)
117       {
118         final javax.swing.plaf.basic.BasicFileChooserUI ui = (javax.swing.plaf.
119             basic.BasicFileChooserUI) getUI();
120         final String name = ui.getFileName().trim();
121
122         if ( (name == null) || (name.length() == 0))
123         {
124           return;
125         }
126
127         EventQueue.invokeLater(new Thread()
128         {
129           public void run()
130           {
131             String currentName = ui.getFileName();
132             if ( (currentName == null) || (currentName.length() == 0))
133             {
134               ui.setFileName(name);
135             }
136           }
137         });
138       }
139     }
140     catch (Exception ex)
141     {
142       ex.printStackTrace();
143       // Some platforms do not have BasicFileChooserUI
144     }
145   }
146
147   public String getSelectedFormat()
148   {
149     if (getFileFilter() == null)
150     {
151       return null;
152     }
153
154     String format = getFileFilter().getDescription();
155
156     if (format.toUpperCase().startsWith("JALVIEW"))
157     {
158       format = "Jalview";
159     }
160     else if (format.toUpperCase().startsWith("FASTA"))
161     {
162       format = "FASTA";
163     }
164     else if (format.toUpperCase().startsWith("MSF"))
165     {
166       format = "MSF";
167     }
168     else if (format.toUpperCase().startsWith("CLUSTAL"))
169     {
170       format = "CLUSTAL";
171     }
172     else if (format.toUpperCase().startsWith("BLC"))
173     {
174       format = "BLC";
175     }
176     else if (format.toUpperCase().startsWith("PIR"))
177     {
178       format = "PIR";
179     }
180     else if (format.toUpperCase().startsWith("PFAM"))
181     {
182       format = "PFAM";
183     }
184
185     return format;
186   }
187
188   public int showSaveDialog(Component parent)
189       throws HeadlessException
190   {
191     this.setAccessory(null);
192
193     setDialogType(SAVE_DIALOG);
194
195     int ret = showDialog(parent, "Save");
196
197     if (getFileFilter() instanceof JalviewFileFilter)
198     {
199       JalviewFileFilter jvf = (JalviewFileFilter) getFileFilter();
200
201       if (!jvf.accept(getSelectedFile()))
202       {
203         String withExtension = getSelectedFile() + "." +
204             jvf.getAcceptableExtension();
205         setSelectedFile(new File(withExtension));
206       }
207     }
208     // TODO: ENSURE THAT FILES SAVED WITH A ':' IN THE NAME ARE REFUSED AND THE USER PROMPTED FOR A NEW FILENAME
209     if ( (ret == JalviewFileChooser.APPROVE_OPTION) &&
210         getSelectedFile().exists())
211     {
212       int confirm = JOptionPane.showConfirmDialog(parent,
213                                                   "Overwrite existing file?",
214                                                   "File exists",
215                                                   JOptionPane.YES_NO_OPTION);
216
217       if (confirm != JOptionPane.YES_OPTION)
218       {
219         ret = JalviewFileChooser.CANCEL_OPTION;
220       }
221     }
222
223     return ret;
224   }
225
226   void recentListSelectionChanged(String selection)
227   {
228     setSelectedFile(null);
229
230     File file = new File(selection);
231     if (getFileFilter() instanceof JalviewFileFilter)
232     {
233       JalviewFileFilter jvf = (JalviewFileFilter)this.getFileFilter();
234
235       if (!jvf.accept(file))
236       {
237         setFileFilter(getChoosableFileFilters()[0]);
238       }
239     }
240
241     setSelectedFile(file);
242   }
243
244   class RecentlyOpened
245       extends JPanel
246   {
247     JList list;
248     public RecentlyOpened()
249     {
250       String historyItems = jalview.bin.Cache.getProperty("RECENT_FILE");
251       StringTokenizer st;
252       Vector recent = new Vector();
253
254       if (historyItems != null)
255       {
256         st = new StringTokenizer(historyItems, "\t");
257
258         while (st.hasMoreTokens())
259         {
260           recent.addElement(st.nextElement());
261         }
262       }
263
264       list = new JList(recent);
265
266       DefaultListCellRenderer dlcr = new DefaultListCellRenderer();
267       dlcr.setHorizontalAlignment(DefaultListCellRenderer.RIGHT);
268       list.setCellRenderer(dlcr);
269
270       list.addMouseListener(new MouseAdapter()
271       {
272         public void mousePressed(MouseEvent evt)
273         {
274           recentListSelectionChanged(list.getSelectedValue().toString());
275         }
276       });
277
278       this.setBorder(new javax.swing.border.TitledBorder("Recently Opened"));
279
280       final JScrollPane scroller = new JScrollPane(list);
281       scroller.setPreferredSize(new Dimension(130, 200));
282       this.add(scroller);
283
284       javax.swing.SwingUtilities.invokeLater(new Runnable()
285       {
286         public void run()
287         {
288           scroller.getHorizontalScrollBar().setValue(
289               scroller.getHorizontalScrollBar().getMaximum());
290         }
291       });
292
293     }
294
295   }
296 }