(JAL-965) new api methods to allow features to be loaded without automatically enabli...
[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, 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
89       if ((selected != null) && selected.equalsIgnoreCase(desc[i]))
90       {
91         chosen = jvf;
92       }
93     }
94
95     if (chosen != null)
96     {
97       setFileFilter(chosen);
98     }
99
100     setAccessory(new RecentlyOpened());
101   }
102
103   public void setFileFilter(javax.swing.filechooser.FileFilter filter)
104   {
105     super.setFileFilter(filter);
106
107     try
108     {
109       if (getUI() instanceof javax.swing.plaf.basic.BasicFileChooserUI)
110       {
111         final javax.swing.plaf.basic.BasicFileChooserUI ui = (javax.swing.plaf.basic.BasicFileChooserUI) getUI();
112         final String name = ui.getFileName().trim();
113
114         if ((name == null) || (name.length() == 0))
115         {
116           return;
117         }
118
119         EventQueue.invokeLater(new Thread()
120         {
121           public void run()
122           {
123             String currentName = ui.getFileName();
124             if ((currentName == null) || (currentName.length() == 0))
125             {
126               ui.setFileName(name);
127             }
128           }
129         });
130       }
131     } catch (Exception ex)
132     {
133       ex.printStackTrace();
134       // Some platforms do not have BasicFileChooserUI
135     }
136   }
137
138   public String getSelectedFormat()
139   {
140     if (getFileFilter() == null)
141     {
142       return null;
143     }
144
145     String format = getFileFilter().getDescription();
146
147     if (format.toUpperCase().startsWith("JALVIEW"))
148     {
149       format = "Jalview";
150     }
151     else if (format.toUpperCase().startsWith("FASTA"))
152     {
153       format = "FASTA";
154     }
155     else if (format.toUpperCase().startsWith("MSF"))
156     {
157       format = "MSF";
158     }
159     else if (format.toUpperCase().startsWith("CLUSTAL"))
160     {
161       format = "CLUSTAL";
162     }
163     else if (format.toUpperCase().startsWith("BLC"))
164     {
165       format = "BLC";
166     }
167     else if (format.toUpperCase().startsWith("PIR"))
168     {
169       format = "PIR";
170     }
171     else if (format.toUpperCase().startsWith("PFAM"))
172     {
173       format = "PFAM";
174     }
175
176     return format;
177   }
178
179   public int showSaveDialog(Component parent) throws HeadlessException
180   {
181     this.setAccessory(null);
182
183     setDialogType(SAVE_DIALOG);
184
185     int ret = showDialog(parent, "Save");
186
187     if (getFileFilter() instanceof JalviewFileFilter)
188     {
189       JalviewFileFilter jvf = (JalviewFileFilter) getFileFilter();
190
191       if (!jvf.accept(getSelectedFile()))
192       {
193         String withExtension = getSelectedFile() + "."
194                 + jvf.getAcceptableExtension();
195         setSelectedFile(new File(withExtension));
196       }
197     }
198     // TODO: ENSURE THAT FILES SAVED WITH A ':' IN THE NAME ARE REFUSED AND THE
199     // USER PROMPTED FOR A NEW FILENAME
200     if ((ret == JalviewFileChooser.APPROVE_OPTION)
201             && getSelectedFile().exists())
202     {
203       int confirm = JOptionPane.showConfirmDialog(parent,
204               "Overwrite existing file?", "File exists",
205               JOptionPane.YES_NO_OPTION);
206
207       if (confirm != JOptionPane.YES_OPTION)
208       {
209         ret = JalviewFileChooser.CANCEL_OPTION;
210       }
211     }
212
213     return ret;
214   }
215
216   void recentListSelectionChanged(String selection)
217   {
218     setSelectedFile(null);
219
220     File file = new File(selection);
221     if (getFileFilter() instanceof JalviewFileFilter)
222     {
223       JalviewFileFilter jvf = (JalviewFileFilter) this.getFileFilter();
224
225       if (!jvf.accept(file))
226       {
227         setFileFilter(getChoosableFileFilters()[0]);
228       }
229     }
230
231     setSelectedFile(file);
232   }
233
234   class RecentlyOpened extends JPanel
235   {
236     JList list;
237
238     public RecentlyOpened()
239     {
240       String historyItems = jalview.bin.Cache.getProperty("RECENT_FILE");
241       StringTokenizer st;
242       Vector recent = new Vector();
243
244       if (historyItems != null)
245       {
246         st = new StringTokenizer(historyItems, "\t");
247
248         while (st.hasMoreTokens())
249         {
250           recent.addElement(st.nextElement());
251         }
252       }
253
254       list = new JList(recent);
255
256       DefaultListCellRenderer dlcr = new DefaultListCellRenderer();
257       dlcr.setHorizontalAlignment(DefaultListCellRenderer.RIGHT);
258       list.setCellRenderer(dlcr);
259
260       list.addMouseListener(new MouseAdapter()
261       {
262         public void mousePressed(MouseEvent evt)
263         {
264           recentListSelectionChanged(list.getSelectedValue().toString());
265         }
266       });
267
268       this.setBorder(new javax.swing.border.TitledBorder("Recently Opened"));
269
270       final JScrollPane scroller = new JScrollPane(list);
271       scroller.setPreferredSize(new Dimension(130, 200));
272       this.add(scroller);
273
274       javax.swing.SwingUtilities.invokeLater(new Runnable()
275       {
276         public void run()
277         {
278           scroller.getHorizontalScrollBar().setValue(
279                   scroller.getHorizontalScrollBar().getMaximum());
280         }
281       });
282
283     }
284
285   }
286 }