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