JAL-1807 Bob's first commit -- Applet loaded; needs image
[jalview.git] / src / jalview / io / JalviewFileChooser.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3  * Copyright (C) $$Year-Rel$$ 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.bin.Cache;
25 import jalview.util.MessageManager;
26 import jalview.util.Platform;
27
28 import java.awt.Component;
29 import java.awt.Dimension;
30 import java.awt.EventQueue;
31 import java.awt.HeadlessException;
32 import java.awt.event.MouseAdapter;
33 import java.awt.event.MouseEvent;
34 import java.io.File;
35 import java.util.StringTokenizer;
36 import java.util.Vector;
37
38 import javax.swing.DefaultListCellRenderer;
39 import javax.swing.JFileChooser;
40 import javax.swing.JList;
41 import javax.swing.JOptionPane;
42 import javax.swing.JPanel;
43 import javax.swing.JScrollPane;
44 import javax.swing.SpringLayout;
45
46 /**
47  * Enhanced file chooser dialog box.
48  *
49  * NOTE: bug on Windows systems when filechooser opened on directory to view
50  * files with colons in title.
51  *
52  * @author AMW
53  *
54  */
55 public class JalviewFileChooser extends JFileChooser
56 {
57   public JalviewFileChooser(String dir)
58   {
59     super(safePath(dir));
60     setAccessory(new RecentlyOpened());
61   }
62
63   private static File safePath(String dir)
64   {
65     if (dir == null)
66     {
67       return null;
68     }
69
70     File f = new File(dir);
71     if (f.getName().indexOf(':') > -1)
72     {
73       return null;
74     }
75     return f;
76   }
77
78   public JalviewFileChooser(String dir, String[] suffix, String[] desc,
79           String selected, boolean selectAll)
80   {
81     super(safePath(dir));
82     init(suffix, desc, selected, selectAll);
83   }
84
85   public JalviewFileChooser(String dir, String[] suffix, String[] desc,
86           String selected)
87   {
88     super(safePath(dir));
89     init(suffix, desc, selected, true);
90   }
91
92   void init(String[] suffix, String[] desc, String selected,
93           boolean selectAll)
94   {
95
96     JalviewFileFilter chosen = null;
97
98     // SelectAllFilter needs to be set first before adding further
99     // file filters to fix bug on Mac OSX
100     setAcceptAllFileFilterUsed(selectAll);
101
102     for (int i = 0; i < suffix.length; i++)
103     {
104       JalviewFileFilter jvf = new JalviewFileFilter(suffix[i], desc[i]);
105       addChoosableFileFilter(jvf);
106       if ((selected != null) && selected.equalsIgnoreCase(desc[i]))
107       {
108         chosen = jvf;
109       }
110     }
111
112     if (chosen != null)
113     {
114       setFileFilter(chosen);
115     }
116
117     setAccessory(new RecentlyOpened());
118   }
119
120   @Override
121   public void setFileFilter(javax.swing.filechooser.FileFilter filter)
122   {
123     super.setFileFilter(filter);
124
125     try
126     {
127       if (getUI() instanceof javax.swing.plaf.basic.BasicFileChooserUI)
128       {
129         final javax.swing.plaf.basic.BasicFileChooserUI ui = (javax.swing.plaf.basic.BasicFileChooserUI) getUI();
130         final String name = ui.getFileName().trim();
131
132         if ((name == null) || (name.length() == 0))
133         {
134           return;
135         }
136
137         EventQueue.invokeLater(new Thread()
138         {
139           @Override
140           public void run()
141           {
142             String currentName = ui.getFileName();
143             if ((currentName == null) || (currentName.length() == 0))
144             {
145               ui.setFileName(name);
146             }
147           }
148         });
149       }
150     } catch (Exception ex)
151     {
152       ex.printStackTrace();
153       // Some platforms do not have BasicFileChooserUI
154     }
155   }
156
157   public String getSelectedFormat()
158   {
159     if (getFileFilter() == null)
160     {
161       return null;
162     }
163
164     String format = getFileFilter().getDescription();
165
166     if (format.toUpperCase().startsWith("JALVIEW"))
167     {
168       format = "Jalview";
169     }
170     else if (format.toUpperCase().startsWith("FASTA"))
171     {
172       format = "FASTA";
173     }
174     else if (format.toUpperCase().startsWith("MSF"))
175     {
176       format = "MSF";
177     }
178     else if (format.toUpperCase().startsWith("CLUSTAL"))
179     {
180       format = "CLUSTAL";
181     }
182     else if (format.toUpperCase().startsWith("BLC"))
183     {
184       format = "BLC";
185     }
186     else if (format.toUpperCase().startsWith("PIR"))
187     {
188       format = "PIR";
189     }
190     else if (format.toUpperCase().startsWith("PFAM"))
191     {
192       format = "PFAM";
193     }
194     else if (format.toUpperCase().startsWith(PhylipFile.FILE_DESC))
195     {
196       format = PhylipFile.FILE_DESC;
197     }
198
199     return format;
200   }
201
202   @Override
203   public int showSaveDialog(Component parent) throws HeadlessException
204   {
205     this.setAccessory(null);
206
207     setDialogType(SAVE_DIALOG);
208
209     int ret = showDialog(parent, MessageManager.getString("action.save"));
210
211     if (getFileFilter() instanceof JalviewFileFilter)
212     {
213       JalviewFileFilter jvf = (JalviewFileFilter) getFileFilter();
214
215       if (!jvf.accept(getSelectedFile()))
216       {
217         String withExtension = getSelectedFile() + "."
218                 + jvf.getAcceptableExtension();
219         setSelectedFile(new File(withExtension));
220       }
221     }
222     // TODO: ENSURE THAT FILES SAVED WITH A ':' IN THE NAME ARE REFUSED AND THE
223     // USER PROMPTED FOR A NEW FILENAME
224     if ((ret == JalviewFileChooser.APPROVE_OPTION)
225             && getSelectedFile().exists())
226     {
227       int confirm = JOptionPane.showConfirmDialog(parent,
228               MessageManager.getString("label.overwrite_existing_file"), 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 = 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.getString("label.recently_opened")));
297
298       final JScrollPane scroller = new JScrollPane(list);
299
300       SpringLayout layout = new SpringLayout();
301       layout.putConstraint(SpringLayout.WEST, scroller, 5,
302               SpringLayout.WEST, this);
303       layout.putConstraint(SpringLayout.NORTH, scroller, 5,
304               SpringLayout.NORTH, this);
305
306       if (new Platform().isAMac())
307       {
308         scroller.setPreferredSize(new Dimension(500, 100));
309       }
310       else
311       {
312         scroller.setPreferredSize(new Dimension(130, 200));
313       }
314
315       this.add(scroller);
316
317       javax.swing.SwingUtilities.invokeLater(new Runnable()
318       {
319         @Override
320         public void run()
321         {
322           scroller.getHorizontalScrollBar().setValue(
323                   scroller.getHorizontalScrollBar().getMaximum());
324         }
325       });
326
327     }
328
329   }
330 }