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