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