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