FileFormat enum wip changes
[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.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   public JalviewFileChooser(String property, FileFormatI currentFileFormat,
92           boolean b)
93   {
94     todo write this
95     // TODO Auto-generated constructor stub
96   }
97
98   void init(String[] suffix, String[] desc, String selected,
99           boolean selectAll)
100   {
101
102     JalviewFileFilter chosen = null;
103
104     // SelectAllFilter needs to be set first before adding further
105     // file filters to fix bug on Mac OSX
106     setAcceptAllFileFilterUsed(selectAll);
107
108     for (int i = 0; i < suffix.length; i++)
109     {
110       JalviewFileFilter jvf = new JalviewFileFilter(suffix[i], desc[i]);
111       addChoosableFileFilter(jvf);
112       if ((selected != null) && selected.equalsIgnoreCase(desc[i]))
113       {
114         chosen = jvf;
115       }
116     }
117
118     if (chosen != null)
119     {
120       setFileFilter(chosen);
121     }
122
123     setAccessory(new RecentlyOpened());
124   }
125
126   @Override
127   public void setFileFilter(javax.swing.filechooser.FileFilter filter)
128   {
129     super.setFileFilter(filter);
130
131     try
132     {
133       if (getUI() instanceof javax.swing.plaf.basic.BasicFileChooserUI)
134       {
135         final javax.swing.plaf.basic.BasicFileChooserUI ui = (javax.swing.plaf.basic.BasicFileChooserUI) getUI();
136         final String name = ui.getFileName().trim();
137
138         if ((name == null) || (name.length() == 0))
139         {
140           return;
141         }
142
143         EventQueue.invokeLater(new Thread()
144         {
145           @Override
146           public void run()
147           {
148             String currentName = ui.getFileName();
149             if ((currentName == null) || (currentName.length() == 0))
150             {
151               ui.setFileName(name);
152             }
153           }
154         });
155       }
156     } catch (Exception ex)
157     {
158       ex.printStackTrace();
159       // Some platforms do not have BasicFileChooserUI
160     }
161   }
162
163   public FileFormat getSelectedFormat()
164   {
165     if (getFileFilter() == null)
166     {
167       return null;
168     }
169
170     String format = getFileFilter().getDescription();
171     return FileFormat.valueOf(format);
172   }
173
174   @Override
175   public int showSaveDialog(Component parent) throws HeadlessException
176   {
177     this.setAccessory(null);
178
179     setDialogType(SAVE_DIALOG);
180
181     int ret = showDialog(parent, MessageManager.getString("action.save"));
182
183     if (getFileFilter() instanceof JalviewFileFilter)
184     {
185       JalviewFileFilter jvf = (JalviewFileFilter) getFileFilter();
186
187       if (!jvf.accept(getSelectedFile()))
188       {
189         String withExtension = getSelectedFile() + "."
190                 + jvf.getAcceptableExtension();
191         setSelectedFile(new File(withExtension));
192       }
193     }
194     // TODO: ENSURE THAT FILES SAVED WITH A ':' IN THE NAME ARE REFUSED AND THE
195     // USER PROMPTED FOR A NEW FILENAME
196     if ((ret == JalviewFileChooser.APPROVE_OPTION)
197             && getSelectedFile().exists())
198     {
199       int confirm = JOptionPane.showConfirmDialog(parent,
200               MessageManager.getString("label.overwrite_existing_file"),
201               MessageManager.getString("label.file_already_exists"),
202               JOptionPane.YES_NO_OPTION);
203
204       if (confirm != JOptionPane.YES_OPTION)
205       {
206         ret = JalviewFileChooser.CANCEL_OPTION;
207       }
208     }
209
210     return ret;
211   }
212
213   void recentListSelectionChanged(Object selection)
214   {
215     setSelectedFile(null);
216     if (selection != null)
217     {
218       File file = new File((String) selection);
219       if (getFileFilter() instanceof JalviewFileFilter)
220       {
221         JalviewFileFilter jvf = (JalviewFileFilter) this.getFileFilter();
222
223         if (!jvf.accept(file))
224         {
225           setFileFilter(getChoosableFileFilters()[0]);
226         }
227       }
228
229       setSelectedFile(file);
230     }
231   }
232
233   class RecentlyOpened extends JPanel
234   {
235     JList list;
236
237     public RecentlyOpened()
238     {
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         @Override
263         public void mousePressed(MouseEvent evt)
264         {
265           recentListSelectionChanged(list.getSelectedValue());
266         }
267       });
268
269       this.setBorder(new javax.swing.border.TitledBorder(MessageManager
270               .getString("label.recently_opened")));
271
272       final JScrollPane scroller = new JScrollPane(list);
273
274       SpringLayout layout = new SpringLayout();
275       layout.putConstraint(SpringLayout.WEST, scroller, 5,
276               SpringLayout.WEST, this);
277       layout.putConstraint(SpringLayout.NORTH, scroller, 5,
278               SpringLayout.NORTH, this);
279
280       if (new Platform().isAMac())
281       {
282         scroller.setPreferredSize(new Dimension(500, 100));
283       }
284       else
285       {
286         scroller.setPreferredSize(new Dimension(130, 200));
287       }
288
289       this.add(scroller);
290
291       javax.swing.SwingUtilities.invokeLater(new Runnable()
292       {
293         @Override
294         public void run()
295         {
296           scroller.getHorizontalScrollBar().setValue(
297                   scroller.getHorizontalScrollBar().getMaximum());
298         }
299       });
300
301     }
302
303   }
304 }