Clover icon

jalviewX

  1. Project Clover database Wed Oct 31 2018 15:13:58 GMT
  2. Package jalview.io

File JalviewFileChooser.java

 

Coverage histogram

../../img/srcFileCovDistChart5.png
40% of files have more coverage

Code metrics

48
122
20
2
491
337
50
0.41
6.1
10
2.5

Classes

Class Line # Actions
JalviewFileChooser 63 98 44 104
0.337579633.8%
JalviewFileChooser.RecentlyOpened 413 24 6 5
0.848484984.8%
 

Contributing tests

This file is covered by 4 tests. .

Source view

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.gui.JvOptionPane;
26    import jalview.util.MessageManager;
27    import jalview.util.Platform;
28    import jalview.util.dialogrunner.DialogRunnerI;
29    import jalview.util.dialogrunner.Response;
30    import jalview.util.dialogrunner.RunResponse;
31   
32    import java.awt.Component;
33    import java.awt.Dimension;
34    import java.awt.EventQueue;
35    import java.awt.HeadlessException;
36    import java.awt.event.MouseAdapter;
37    import java.awt.event.MouseEvent;
38    import java.beans.PropertyChangeEvent;
39    import java.beans.PropertyChangeListener;
40    import java.io.File;
41    import java.util.ArrayList;
42    import java.util.List;
43    import java.util.StringTokenizer;
44    import java.util.Vector;
45   
46    import javax.swing.DefaultListCellRenderer;
47    import javax.swing.JFileChooser;
48    import javax.swing.JList;
49    import javax.swing.JPanel;
50    import javax.swing.JScrollPane;
51    import javax.swing.SpringLayout;
52    import javax.swing.plaf.basic.BasicFileChooserUI;
53   
54    /**
55    * Enhanced file chooser dialog box.
56    *
57    * NOTE: bug on Windows systems when filechooser opened on directory to view
58    * files with colons in title.
59    *
60    * @author AMW
61    *
62    */
 
63    public class JalviewFileChooser extends JFileChooser
64    implements PropertyChangeListener, DialogRunnerI
65    {
66    jalview.util.dialogrunner.DialogRunner<JalviewFileChooser> runner = new jalview.util.dialogrunner.DialogRunner<>(
67    this);
68    /**
69    * Factory method to return a file chooser that offers readable alignment file
70    * formats
71    *
72    * @param directory
73    * @param selected
74    * @return
75    */
 
76  11 toggle public static JalviewFileChooser forRead(String directory,
77    String selected)
78    {
79  11 List<String> extensions = new ArrayList<>();
80  11 List<String> descs = new ArrayList<>();
81  11 for (FileFormatI format : FileFormats.getInstance().getFormats())
82    {
83  209 if (format.isReadable())
84    {
85  187 extensions.add(format.getExtensions());
86  187 descs.add(format.getName());
87    }
88    }
89  11 return new JalviewFileChooser(directory,
90    extensions.toArray(new String[extensions.size()]),
91    descs.toArray(new String[descs.size()]), selected, true);
92    }
93   
94    /**
95    * Factory method to return a file chooser that offers writable alignment file
96    * formats
97    *
98    * @param directory
99    * @param selected
100    * @return
101    */
 
102  0 toggle public static JalviewFileChooser forWrite(String directory,
103    String selected)
104    {
105    // TODO in Java 8, forRead and forWrite can be a single method
106    // with a lambda expression parameter for isReadable/isWritable
107  0 List<String> extensions = new ArrayList<>();
108  0 List<String> descs = new ArrayList<>();
109  0 for (FileFormatI format : FileFormats.getInstance().getFormats())
110    {
111  0 if (format.isWritable())
112    {
113  0 extensions.add(format.getExtensions());
114  0 descs.add(format.getName());
115    }
116    }
117  0 return new JalviewFileChooser(directory,
118    extensions.toArray(new String[extensions.size()]),
119    descs.toArray(new String[descs.size()]), selected, false);
120    }
121   
 
122  0 toggle public JalviewFileChooser(String dir)
123    {
124  0 super(safePath(dir));
125  0 setAccessory(new RecentlyOpened());
126    }
127   
 
128  0 toggle public JalviewFileChooser(String dir, String[] suffix, String[] desc,
129    String selected)
130    {
131  0 this(dir, suffix, desc, selected, true);
132    }
133   
134    /**
135    * Constructor for a single choice of file extension and description
136    *
137    * @param extension
138    * @param desc
139    */
 
140  0 toggle public JalviewFileChooser(String extension, String desc)
141    {
142  0 this(Cache.getProperty("LAST_DIRECTORY"), new String[] { extension },
143    new String[]
144    { desc }, desc, true);
145    }
146   
 
147  11 toggle JalviewFileChooser(String dir, String[] extensions, String[] descs,
148    String selected, boolean allFiles)
149    {
150  11 super(safePath(dir));
151  11 if (extensions.length == descs.length)
152    {
153  11 List<String[]> formats = new ArrayList<>();
154  198 for (int i = 0; i < extensions.length; i++)
155    {
156  187 formats.add(new String[] { extensions[i], descs[i] });
157    }
158  11 init(formats, selected, allFiles);
159    }
160    else
161    {
162  0 System.err.println("JalviewFileChooser arguments mismatch: "
163    + extensions + ", " + descs);
164    }
165    }
166   
 
167  0 toggle @Override
168    public void propertyChange(PropertyChangeEvent evt)
169    {
170    // TODO other properties need runners...
171  0 switch (evt.getPropertyName())
172    {
173  0 case "SelectedFile":
174  0 runner.run(APPROVE_OPTION);
175  0 break;
176    }
177    }
178   
 
179  11 toggle private static File safePath(String dir)
180    {
181  11 if (dir == null)
182    {
183  4 return null;
184    }
185   
186  7 File f = new File(dir);
187  7 if (f.getName().indexOf(':') > -1)
188    {
189  0 return null;
190    }
191  7 return f;
192    }
193   
 
194  0 toggle public void openDialog(Component parent)
195    {
196  0 runner.resetResponses();
197  0 int value = showOpenDialog(this);
198    /**
199    * @j2sNative
200    */
201    {
202  0 runner.firstRun(value);
203    }
204    }
205   
206    /**
207    *
208    * @param formats
209    * a list of {extensions, description} for each file format
210    * @param selected
211    * @param allFiles
212    * if true, 'any format' option is included
213    */
 
214  11 toggle void init(List<String[]> formats, String selected, boolean allFiles)
215    {
216   
217  11 JalviewFileFilter chosen = null;
218   
219    // SelectAllFilter needs to be set first before adding further
220    // file filters to fix bug on Mac OSX
221  11 setAcceptAllFileFilterUsed(allFiles);
222   
223  11 for (String[] format : formats)
224    {
225  187 JalviewFileFilter jvf = new JalviewFileFilter(format[0], format[1]);
226  187 addChoosableFileFilter(jvf);
227  187 if ((selected != null) && selected.equalsIgnoreCase(format[1]))
228    {
229  11 chosen = jvf;
230    }
231    }
232   
233  11 if (chosen != null)
234    {
235  11 setFileFilter(chosen);
236    }
237   
238  11 setAccessory(new RecentlyOpened());
239    }
240   
 
241  55 toggle @Override
242    public void setFileFilter(javax.swing.filechooser.FileFilter filter)
243    {
244  55 super.setFileFilter(filter);
245   
246  55 try
247    {
248  55 if (getUI() instanceof BasicFileChooserUI)
249    {
250  55 final BasicFileChooserUI fcui = (BasicFileChooserUI) getUI();
251  55 final String name = fcui.getFileName().trim();
252   
253  55 if ((name == null) || (name.length() == 0))
254    {
255  55 return;
256    }
257   
258  0 EventQueue.invokeLater(new Thread()
259    {
 
260  0 toggle @Override
261    public void run()
262    {
263  0 String currentName = fcui.getFileName();
264  0 if ((currentName == null) || (currentName.length() == 0))
265    {
266  0 fcui.setFileName(name);
267    }
268    }
269    });
270    }
271    } catch (Exception ex)
272    {
273  0 ex.printStackTrace();
274    // Some platforms do not have BasicFileChooserUI
275    }
276    }
277   
278    /**
279    * Returns the selected file format, or null if none selected
280    *
281    * @return
282    */
 
283  0 toggle public FileFormatI getSelectedFormat()
284    {
285  0 if (getFileFilter() == null)
286    {
287  0 return null;
288    }
289   
290    /*
291    * logic here depends on option description being formatted as
292    * formatName (extension, extension...)
293    * or the 'no option selected' value
294    * All Files
295    * @see JalviewFileFilter.getDescription
296    */
297  0 String format = getFileFilter().getDescription();
298  0 int parenPos = format.indexOf("(");
299  0 if (parenPos > 0)
300    {
301  0 format = format.substring(0, parenPos).trim();
302  0 try
303    {
304  0 return FileFormats.getInstance().forName(format);
305    } catch (IllegalArgumentException e)
306    {
307  0 System.err.println("Unexpected format: " + format);
308    }
309    }
310  0 return null;
311    }
312   
313    Component saveparent;
314    RunResponse overwriteCheck = new RunResponse(
315    JalviewFileChooser.APPROVE_OPTION)
316    {
 
317  0 toggle @Override
318    public void run()
319    {
320    // JBP Note - this code was executed regardless of 'SAVE' being pressed
321    // need to see if there were side effects
322  0 if (getFileFilter() instanceof JalviewFileFilter)
323    {
324  0 JalviewFileFilter jvf = (JalviewFileFilter) getFileFilter();
325   
326  0 if (!jvf.accept(getSelectedFile()))
327    {
328  0 String withExtension = getSelectedFile() + "."
329    + jvf.getAcceptableExtension();
330  0 setSelectedFile(new File(withExtension));
331    }
332    }
333    // All good, so we continue to save
334  0 returned = new Response(JalviewFileChooser.APPROVE_OPTION);
335   
336    // TODO: ENSURE THAT FILES SAVED WITH A ':' IN THE NAME ARE REFUSED AND THE
337    // USER PROMPTED FOR A NEW FILENAME
338    /**
339    * @j2sNative
340    */
341    {
342  0 if (getSelectedFile().exists())
343    {
344    // JAL-3048 - may not need to raise this for browser saves
345   
346    // yes/no cancel
347  0 int confirm = JvOptionPane.showConfirmDialog(saveparent,
348    MessageManager.getString("label.overwrite_existing_file"),
349    MessageManager.getString("label.file_already_exists"),
350    JvOptionPane.YES_NO_OPTION);
351   
352  0 if (confirm != JvOptionPane.YES_OPTION)
353    {
354  0 returned = new Response(JalviewFileChooser.CANCEL_OPTION);
355    }
356    }
357    }
358    };
359    };
360   
 
361  0 toggle @Override
362    public int showSaveDialog(Component parent) throws HeadlessException
363    {
364  0 this.setAccessory(null);
365   
366    /*
367    * Save dialog is opened until user picks a file format
368    */
369  0 if (!runner.isRegistered(overwriteCheck))
370    {
371    // first call for this instance
372  0 runner.firstResponse(overwriteCheck);
373    }
374    else
375    {
376    // reset response flags
377  0 runner.resetResponses();
378    }
379   
380  0 setDialogType(SAVE_DIALOG);
381  0 saveparent = parent;
382   
383  0 int value = showDialog(parent, MessageManager.getString("action.save"));
384    /**
385    * @j2sNative
386    */
387    {
388  0 runner.firstRun(value);
389    }
390  0 return value;
391    }
392   
 
393  0 toggle void recentListSelectionChanged(Object selection)
394    {
395  0 setSelectedFile(null);
396  0 if (selection != null)
397    {
398  0 File file = new File((String) selection);
399  0 if (getFileFilter() instanceof JalviewFileFilter)
400    {
401  0 JalviewFileFilter jvf = (JalviewFileFilter) this.getFileFilter();
402   
403  0 if (!jvf.accept(file))
404    {
405  0 setFileFilter(getChoosableFileFilters()[0]);
406    }
407    }
408   
409  0 setSelectedFile(file);
410    }
411    }
412   
 
413    class RecentlyOpened extends JPanel
414    {
415    JList list;
416   
 
417  11 toggle public RecentlyOpened()
418    {
419   
420  11 String historyItems = jalview.bin.Cache.getProperty("RECENT_FILE");
421  11 StringTokenizer st;
422  11 Vector recent = new Vector();
423   
424  11 if (historyItems != null)
425    {
426  11 st = new StringTokenizer(historyItems, "\t");
427   
428  36 while (st.hasMoreTokens())
429    {
430  25 recent.addElement(st.nextElement());
431    }
432    }
433   
434  11 list = new JList(recent);
435   
436  11 DefaultListCellRenderer dlcr = new DefaultListCellRenderer();
437  11 dlcr.setHorizontalAlignment(DefaultListCellRenderer.RIGHT);
438  11 list.setCellRenderer(dlcr);
439   
440  11 list.addMouseListener(new MouseAdapter()
441    {
 
442  0 toggle @Override
443    public void mousePressed(MouseEvent evt)
444    {
445  0 recentListSelectionChanged(list.getSelectedValue());
446    }
447    });
448   
449  11 this.setBorder(new javax.swing.border.TitledBorder(
450    MessageManager.getString("label.recently_opened")));
451   
452  11 final JScrollPane scroller = new JScrollPane(list);
453   
454  11 SpringLayout layout = new SpringLayout();
455  11 layout.putConstraint(SpringLayout.WEST, scroller, 5,
456    SpringLayout.WEST, this);
457  11 layout.putConstraint(SpringLayout.NORTH, scroller, 5,
458    SpringLayout.NORTH, this);
459   
460  11 if (new Platform().isAMac())
461    {
462  0 scroller.setPreferredSize(new Dimension(500, 100));
463    }
464    else
465    {
466  11 scroller.setPreferredSize(new Dimension(130, 200));
467    }
468   
469  11 this.add(scroller);
470   
471  11 javax.swing.SwingUtilities.invokeLater(new Runnable()
472    {
 
473  11 toggle @Override
474    public void run()
475    {
476  11 scroller.getHorizontalScrollBar()
477    .setValue(scroller.getHorizontalScrollBar().getMaximum());
478    }
479    });
480   
481    }
482   
483    }
484   
 
485  0 toggle @Override
486    public JalviewFileChooser response(RunResponse action)
487    {
488  0 return runner.response(action);
489    }
490   
491    }