in progress
[jalview.git] / forester / java / src / org / forester / archaeopteryx / MainFrameApplication.java
1 // $Id:\r
2 // FORESTER -- software libraries and applications\r
3 // for evolutionary biology research and applications.\r
4 //\r
5 // Copyright (C) 2008-2009 Christian M. Zmasek\r
6 // Copyright (C) 2008-2009 Burnham Institute for Medical Research\r
7 // Copyright (C) 2003-2007 Ethalinda K.S. Cannon\r
8 // All rights reserved\r
9 //\r
10 // This library is free software; you can redistribute it and/or\r
11 // modify it under the terms of the GNU Lesser General Public\r
12 // License as published by the Free Software Foundation; either\r
13 // version 2.1 of the License, or (at your option) any later version.\r
14 //\r
15 // This library is distributed in the hope that it will be useful,\r
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of\r
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
18 // Lesser General Public License for more details.\r
19 //\r
20 // You should have received a copy of the GNU Lesser General Public\r
21 // License along with this library; if not, write to the Free Software\r
22 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\r
23 //\r
24 // Contact: phylosoft @ gmail . com\r
25 // WWW: https://sites.google.com/site/cmzmasek/home/software/forester\r
26 \r
27 package org.forester.archaeopteryx;\r
28 \r
29 import java.awt.BorderLayout;\r
30 import java.awt.Font;\r
31 import java.awt.event.ActionEvent;\r
32 import java.awt.event.ComponentAdapter;\r
33 import java.awt.event.ComponentEvent;\r
34 import java.awt.event.WindowAdapter;\r
35 import java.awt.event.WindowEvent;\r
36 import java.io.File;\r
37 import java.io.FileInputStream;\r
38 import java.io.IOException;\r
39 import java.io.InputStream;\r
40 import java.net.MalformedURLException;\r
41 import java.net.URL;\r
42 import java.util.ArrayList;\r
43 import java.util.HashSet;\r
44 import java.util.List;\r
45 import java.util.Set;\r
46 \r
47 import javax.swing.ButtonGroup;\r
48 import javax.swing.JCheckBoxMenuItem;\r
49 import javax.swing.JFileChooser;\r
50 import javax.swing.JMenu;\r
51 import javax.swing.JMenuBar;\r
52 import javax.swing.JMenuItem;\r
53 import javax.swing.JOptionPane;\r
54 import javax.swing.JRadioButtonMenuItem;\r
55 import javax.swing.UIManager;\r
56 import javax.swing.UnsupportedLookAndFeelException;\r
57 import javax.swing.WindowConstants;\r
58 import javax.swing.event.ChangeEvent;\r
59 import javax.swing.event.ChangeListener;\r
60 import javax.swing.filechooser.FileFilter;\r
61 import javax.swing.plaf.synth.SynthLookAndFeel;\r
62 \r
63 import org.forester.analysis.TaxonomyDataManager;\r
64 import org.forester.archaeopteryx.AptxUtil.GraphicsExportType;\r
65 import org.forester.archaeopteryx.Options.CLADOGRAM_TYPE;\r
66 import org.forester.archaeopteryx.Options.NODE_LABEL_DIRECTION;\r
67 import org.forester.archaeopteryx.Options.PHYLOGENY_GRAPHICS_TYPE;\r
68 import org.forester.archaeopteryx.tools.AncestralTaxonomyInferrer;\r
69 import org.forester.archaeopteryx.tools.InferenceManager;\r
70 import org.forester.archaeopteryx.tools.PhyloInferenceDialog;\r
71 import org.forester.archaeopteryx.tools.PhylogeneticInferenceOptions;\r
72 import org.forester.archaeopteryx.tools.PhylogeneticInferrer;\r
73 import org.forester.archaeopteryx.tools.SequenceDataRetriver;\r
74 import org.forester.archaeopteryx.webservices.PhylogeniesWebserviceClient;\r
75 import org.forester.archaeopteryx.webservices.WebservicesManager;\r
76 import org.forester.io.parsers.FastaParser;\r
77 import org.forester.io.parsers.GeneralMsaParser;\r
78 import org.forester.io.parsers.PhylogenyParser;\r
79 import org.forester.io.parsers.nexus.NexusPhylogeniesParser;\r
80 import org.forester.io.parsers.nhx.NHXParser;\r
81 import org.forester.io.parsers.nhx.NHXParser.TAXONOMY_EXTRACTION;\r
82 import org.forester.io.parsers.phyloxml.PhyloXmlDataFormatException;\r
83 import org.forester.io.parsers.phyloxml.PhyloXmlParser;\r
84 import org.forester.io.parsers.phyloxml.PhyloXmlUtil;\r
85 import org.forester.io.parsers.tol.TolParser;\r
86 import org.forester.io.parsers.util.ParserUtils;\r
87 import org.forester.io.writers.PhylogenyWriter;\r
88 import org.forester.io.writers.SequenceWriter;\r
89 import org.forester.msa.Msa;\r
90 import org.forester.msa.MsaFormatException;\r
91 import org.forester.phylogeny.Phylogeny;\r
92 import org.forester.phylogeny.PhylogenyMethods;\r
93 import org.forester.phylogeny.PhylogenyNode;\r
94 import org.forester.phylogeny.PhylogenyNode.NH_CONVERSION_SUPPORT_VALUE_STYLE;\r
95 import org.forester.phylogeny.data.Confidence;\r
96 import org.forester.phylogeny.data.Taxonomy;\r
97 import org.forester.phylogeny.factories.ParserBasedPhylogenyFactory;\r
98 import org.forester.phylogeny.factories.PhylogenyFactory;\r
99 import org.forester.phylogeny.iterators.PhylogenyNodeIterator;\r
100 import org.forester.sequence.Sequence;\r
101 import org.forester.util.BasicDescriptiveStatistics;\r
102 import org.forester.util.BasicTable;\r
103 import org.forester.util.BasicTableParser;\r
104 import org.forester.util.DescriptiveStatistics;\r
105 import org.forester.util.ForesterUtil;\r
106 import org.forester.util.WindowsUtils;\r
107 \r
108 public final class MainFrameApplication extends MainFrame {\r
109 \r
110     static final String                      INFER_ANCESTOR_TAXONOMIES             = "Infer Ancestor Taxonomies";\r
111     static final String                      OBTAIN_DETAILED_TAXONOMIC_INFORMATION = "Obtain Detailed Taxonomic Information";\r
112     private final static int                 FRAME_X_SIZE                          = 800;\r
113     private final static int                 FRAME_Y_SIZE                          = 800;\r
114     // Filters for the file-open dialog (classes defined in this file)\r
115     private final static NHFilter            nhfilter                              = new NHFilter();\r
116     private final static NHXFilter           nhxfilter                             = new NHXFilter();\r
117     private final static XMLFilter           xmlfilter                             = new XMLFilter();\r
118     private final static TolFilter           tolfilter                             = new TolFilter();\r
119     private final static NexusFilter         nexusfilter                           = new NexusFilter();\r
120     private final static PdfFilter           pdffilter                             = new PdfFilter();\r
121     private final static GraphicsFileFilter  graphicsfilefilter                    = new GraphicsFileFilter();\r
122     private final static MsaFileFilter       msafilter                             = new MsaFileFilter();\r
123     private final static SequencesFileFilter seqsfilter                            = new SequencesFileFilter();\r
124     private final static DefaultFilter       defaultfilter                         = new DefaultFilter();\r
125     private static final long                serialVersionUID                      = -799735726778865234L;\r
126     private final JFileChooser               _values_filechooser;\r
127     private final JFileChooser               _sequences_filechooser;\r
128     private final JFileChooser               _open_filechooser;\r
129     private final JFileChooser               _msa_filechooser;\r
130     private final JFileChooser               _seqs_pi_filechooser;\r
131     private final JFileChooser               _open_filechooser_for_species_tree;\r
132     private final JFileChooser               _save_filechooser;\r
133     private final JFileChooser               _writetopdf_filechooser;\r
134     private final JFileChooser               _writetographics_filechooser;\r
135     // Application-only print menu items\r
136     private JMenuItem                        _print_item;\r
137     private JMenuItem                        _write_to_pdf_item;\r
138     private JMenuItem                        _write_to_jpg_item;\r
139     private JMenuItem                        _write_to_gif_item;\r
140     private JMenuItem                        _write_to_tif_item;\r
141     private JMenuItem                        _write_to_png_item;\r
142     private JMenuItem                        _write_to_bmp_item;\r
143     private File                             _current_dir;\r
144     private ButtonGroup                      _radio_group_1;\r
145     private ButtonGroup                      _radio_group_2;\r
146     // Others:\r
147     double                                   _min_not_collapse                     = Constants.MIN_NOT_COLLAPSE_DEFAULT;\r
148     // Phylogeny Inference menu\r
149     private JMenu                            _inference_menu;\r
150     private JMenuItem                        _inference_from_msa_item;\r
151     private JMenuItem                        _inference_from_seqs_item;\r
152     // Phylogeny Inference\r
153     private PhylogeneticInferenceOptions     _phylogenetic_inference_options       = null;\r
154     private Msa                              _msa                                  = null;\r
155     private File                             _msa_file                             = null;\r
156     private List<Sequence>                   _seqs                                 = null;\r
157     private File                             _seqs_file                            = null;\r
158     JMenuItem                                _read_values_jmi;\r
159     JMenuItem                                _read_seqs_jmi;\r
160    \r
161 \r
162     private MainFrameApplication( final Phylogeny[] phys, final Configuration config ) {\r
163         _configuration = config;\r
164         if ( _configuration == null ) {\r
165             throw new IllegalArgumentException( "configuration is null" );\r
166         }\r
167         setVisible( false );\r
168         setOptions( Options.createInstance( _configuration ) );\r
169         _mainpanel = new MainPanel( _configuration, this );\r
170         _open_filechooser = null;\r
171         _open_filechooser_for_species_tree = null;\r
172         _save_filechooser = null;\r
173         _writetopdf_filechooser = null;\r
174         _writetographics_filechooser = null;\r
175         _msa_filechooser = null;\r
176         _seqs_pi_filechooser = null;\r
177         _values_filechooser = null;\r
178         _sequences_filechooser = null;\r
179         _jmenubar = new JMenuBar();\r
180         buildFileMenu();\r
181         buildTypeMenu();\r
182         _contentpane = getContentPane();\r
183         _contentpane.setLayout( new BorderLayout() );\r
184         _contentpane.add( _mainpanel, BorderLayout.CENTER );\r
185         // App is this big\r
186         setSize( MainFrameApplication.FRAME_X_SIZE, MainFrameApplication.FRAME_Y_SIZE );\r
187         // The window listener\r
188         setDefaultCloseOperation( WindowConstants.DO_NOTHING_ON_CLOSE );\r
189         addWindowListener( new WindowAdapter() {\r
190 \r
191             @Override\r
192             public void windowClosing( final WindowEvent e ) {\r
193                 exit();\r
194             }\r
195         } );\r
196         //   setVisible( true );\r
197         if ( ( phys != null ) && ( phys.length > 0 ) ) {\r
198             AptxUtil.addPhylogeniesToTabs( phys, "", null, _configuration, _mainpanel );\r
199             validate();\r
200             getMainPanel().getControlPanel().showWholeAll();\r
201             getMainPanel().getControlPanel().showWhole();\r
202         }\r
203         //activateSaveAllIfNeeded();\r
204         // ...and its children\r
205         _contentpane.repaint();\r
206     }\r
207 \r
208     private MainFrameApplication( final Phylogeny[] phys, final Configuration config, final String title ) {\r
209         this( phys, config, title, null );\r
210     }\r
211 \r
212     private MainFrameApplication( final Phylogeny[] phys,\r
213                                   final Configuration config,\r
214                                   final String title,\r
215                                   final File current_dir ) {\r
216         super();\r
217         _configuration = config;\r
218         if ( _configuration == null ) {\r
219             throw new IllegalArgumentException( "configuration is null" );\r
220         }\r
221         try {\r
222             boolean synth_exception = false;\r
223             if ( Constants.__SYNTH_LF ) {\r
224                 try {\r
225                     final SynthLookAndFeel synth = new SynthLookAndFeel();\r
226                     synth.load( MainFrameApplication.class.getResourceAsStream( "/resources/synth_look_and_feel_1.xml" ),\r
227                                 MainFrameApplication.class );\r
228                     UIManager.setLookAndFeel( synth );\r
229                 }\r
230                 catch ( final Exception ex ) {\r
231                     synth_exception = true;\r
232                     ForesterUtil.printWarningMessage( Constants.PRG_NAME,\r
233                                                       "could not create synth look and feel: "\r
234                                                               + ex.getLocalizedMessage() );\r
235                 }\r
236             }\r
237             if ( !Constants.__SYNTH_LF || synth_exception ) {\r
238                 if ( _configuration.isUseNativeUI() ) {\r
239                     UIManager.setLookAndFeel( UIManager.getSystemLookAndFeelClassName() );\r
240                 }\r
241                 else {\r
242                     UIManager.setLookAndFeel( UIManager.getCrossPlatformLookAndFeelClassName() );\r
243                 }\r
244             }\r
245             //UIManager.setLookAndFeel( "com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel" );\r
246         }\r
247         catch ( final UnsupportedLookAndFeelException e ) {\r
248             AptxUtil.dieWithSystemError( "unsupported look and feel: " + e.toString() );\r
249         }\r
250         catch ( final ClassNotFoundException e ) {\r
251             AptxUtil.dieWithSystemError( "class not found exception: " + e.toString() );\r
252         }\r
253         catch ( final InstantiationException e ) {\r
254             AptxUtil.dieWithSystemError( "instantiation exception: " + e.toString() );\r
255         }\r
256         catch ( final IllegalAccessException e ) {\r
257             AptxUtil.dieWithSystemError( "illegal access exception: " + e.toString() );\r
258         }\r
259         if ( ( current_dir != null ) && current_dir.canRead() && current_dir.isDirectory() ) {\r
260             setCurrentDir( current_dir );\r
261         }\r
262         // hide until everything is ready\r
263         setVisible( false );\r
264         setOptions( Options.createInstance( _configuration ) );\r
265         setInferenceManager( InferenceManager.createInstance( _configuration ) );\r
266         setPhylogeneticInferenceOptions( PhylogeneticInferenceOptions.createInstance( _configuration ) );\r
267         //     _textframe = null; #~~~~\r
268         // set title\r
269         setTitle( Constants.PRG_NAME + " " + Constants.VERSION + " (" + Constants.PRG_DATE + ")" );\r
270         _mainpanel = new MainPanel( _configuration, this );\r
271         // The file dialogs\r
272         _open_filechooser = new JFileChooser();\r
273         _open_filechooser.setCurrentDirectory( new File( "." ) );\r
274         _open_filechooser.setMultiSelectionEnabled( false );\r
275         _open_filechooser.addChoosableFileFilter( MainFrameApplication.xmlfilter );\r
276         _open_filechooser.addChoosableFileFilter( MainFrameApplication.nhxfilter );\r
277         _open_filechooser.addChoosableFileFilter( MainFrameApplication.nhfilter );\r
278         _open_filechooser.addChoosableFileFilter( MainFrameApplication.nexusfilter );\r
279         _open_filechooser.addChoosableFileFilter( MainFrameApplication.tolfilter );\r
280         _open_filechooser.addChoosableFileFilter( _open_filechooser.getAcceptAllFileFilter() );\r
281         _open_filechooser.setFileFilter( MainFrameApplication.defaultfilter );\r
282         _open_filechooser_for_species_tree = new JFileChooser();\r
283         _open_filechooser_for_species_tree.setCurrentDirectory( new File( "." ) );\r
284         _open_filechooser_for_species_tree.setMultiSelectionEnabled( false );\r
285         _open_filechooser_for_species_tree.addChoosableFileFilter( MainFrameApplication.xmlfilter );\r
286         _open_filechooser_for_species_tree.addChoosableFileFilter( MainFrameApplication.tolfilter );\r
287         _open_filechooser_for_species_tree.setFileFilter( MainFrameApplication.xmlfilter );\r
288         _save_filechooser = new JFileChooser();\r
289         _save_filechooser.setCurrentDirectory( new File( "." ) );\r
290         _save_filechooser.setMultiSelectionEnabled( false );\r
291         _save_filechooser.setFileFilter( MainFrameApplication.xmlfilter );\r
292         _save_filechooser.addChoosableFileFilter( MainFrameApplication.nhfilter );\r
293         _save_filechooser.addChoosableFileFilter( MainFrameApplication.nexusfilter );\r
294         _save_filechooser.addChoosableFileFilter( _save_filechooser.getAcceptAllFileFilter() );\r
295         _writetopdf_filechooser = new JFileChooser();\r
296         _writetopdf_filechooser.addChoosableFileFilter( MainFrameApplication.pdffilter );\r
297         _writetographics_filechooser = new JFileChooser();\r
298         _writetographics_filechooser.addChoosableFileFilter( MainFrameApplication.graphicsfilefilter );\r
299         // Msa:\r
300         _msa_filechooser = new JFileChooser();\r
301         _msa_filechooser.setName( "Read Multiple Sequence Alignment File" );\r
302         _msa_filechooser.setCurrentDirectory( new File( "." ) );\r
303         _msa_filechooser.setMultiSelectionEnabled( false );\r
304         _msa_filechooser.addChoosableFileFilter( _msa_filechooser.getAcceptAllFileFilter() );\r
305         _msa_filechooser.addChoosableFileFilter( MainFrameApplication.msafilter );\r
306         // Seqs:\r
307         _seqs_pi_filechooser = new JFileChooser();\r
308         _seqs_pi_filechooser.setName( "Read Sequences File" );\r
309         _seqs_pi_filechooser.setCurrentDirectory( new File( "." ) );\r
310         _seqs_pi_filechooser.setMultiSelectionEnabled( false );\r
311         _seqs_pi_filechooser.addChoosableFileFilter( _seqs_pi_filechooser.getAcceptAllFileFilter() );\r
312         _seqs_pi_filechooser.addChoosableFileFilter( MainFrameApplication.seqsfilter );\r
313         // Expression\r
314         _values_filechooser = new JFileChooser();\r
315         _values_filechooser.setCurrentDirectory( new File( "." ) );\r
316         _values_filechooser.setMultiSelectionEnabled( false );\r
317         // Sequences\r
318         _sequences_filechooser = new JFileChooser();\r
319         _sequences_filechooser.setCurrentDirectory( new File( "." ) );\r
320         _sequences_filechooser.setMultiSelectionEnabled( false );\r
321         // build the menu bar\r
322         _jmenubar = new JMenuBar();\r
323         if ( !_configuration.isUseNativeUI() ) {\r
324             _jmenubar.setBackground( getConfiguration().getGuiMenuBackgroundColor() );\r
325         }\r
326         buildFileMenu();\r
327         if ( Constants.__ALLOW_PHYLOGENETIC_INFERENCE ) {\r
328             buildPhylogeneticInferenceMenu();\r
329         }\r
330         buildAnalysisMenu();\r
331         buildToolsMenu();\r
332         buildViewMenu();\r
333         buildFontSizeMenu();\r
334         buildOptionsMenu();\r
335         buildTypeMenu();\r
336         buildHelpMenu();\r
337         setJMenuBar( _jmenubar );\r
338         _jmenubar.add( _help_jmenu );\r
339         _contentpane = getContentPane();\r
340         _contentpane.setLayout( new BorderLayout() );\r
341         _contentpane.add( _mainpanel, BorderLayout.CENTER );\r
342         // App is this big\r
343         setSize( MainFrameApplication.FRAME_X_SIZE, MainFrameApplication.FRAME_Y_SIZE );\r
344         //        addWindowFocusListener( new WindowAdapter() {\r
345         //\r
346         //            @Override\r
347         //            public void windowGainedFocus( WindowEvent e ) {\r
348         //                requestFocusInWindow();\r
349         //            }\r
350         //        } );\r
351         // The window listener\r
352         setDefaultCloseOperation( WindowConstants.DO_NOTHING_ON_CLOSE );\r
353         addWindowListener( new WindowAdapter() {\r
354 \r
355             @Override\r
356             public void windowClosing( final WindowEvent e ) {\r
357                 if ( isUnsavedDataPresent() ) {\r
358                     final int r = JOptionPane.showConfirmDialog( null,\r
359                                                                  "Exit despite potentially unsaved changes?",\r
360                                                                  "Exit?",\r
361                                                                  JOptionPane.YES_NO_OPTION );\r
362                     if ( r != JOptionPane.YES_OPTION ) {\r
363                         return;\r
364                     }\r
365                 }\r
366                 else {\r
367                     final int r = JOptionPane.showConfirmDialog( null,\r
368                                                                  "Exit Archaeopteryx?",\r
369                                                                  "Exit?",\r
370                                                                  JOptionPane.YES_NO_OPTION );\r
371                     if ( r != JOptionPane.YES_OPTION ) {\r
372                         return;\r
373                     }\r
374                 }\r
375                 exit();\r
376             }\r
377         } );\r
378         // The component listener\r
379         addComponentListener( new ComponentAdapter() {\r
380 \r
381             @Override\r
382             public void componentResized( final ComponentEvent e ) {\r
383                 if ( _mainpanel.getCurrentTreePanel() != null ) {\r
384                     _mainpanel.getCurrentTreePanel().calcParametersForPainting( _mainpanel.getCurrentTreePanel()\r
385                                                                                         .getWidth(),\r
386                                                                                 _mainpanel.getCurrentTreePanel()\r
387                                                                                         .getHeight(),\r
388                                                                                 getOptions().isAllowFontSizeChange() );\r
389                 }\r
390             }\r
391         } );\r
392         requestFocusInWindow();\r
393         // addKeyListener( this );\r
394         setVisible( true );\r
395         if ( ( phys != null ) && ( phys.length > 0 ) ) {\r
396             AptxUtil.addPhylogeniesToTabs( phys, title, null, _configuration, _mainpanel );\r
397             validate();\r
398             getMainPanel().getControlPanel().showWholeAll();\r
399             getMainPanel().getControlPanel().showWhole();\r
400         }\r
401         activateSaveAllIfNeeded();\r
402         // ...and its children\r
403         _contentpane.repaint();\r
404         System.gc();\r
405     }\r
406 \r
407     private MainFrameApplication( final Phylogeny[] phys, final String config_file, final String title ) {\r
408         // Reads the config file (false, false => not url, not applet):\r
409         this( phys, new Configuration( config_file, false, false, true ), title );\r
410     }\r
411 \r
412     @Override\r
413     public void actionPerformed( final ActionEvent e ) {\r
414         try {\r
415             super.actionPerformed( e );\r
416             final Object o = e.getSource();\r
417             // Handle app-specific actions here:\r
418             if ( o == _open_item ) {\r
419                 readPhylogeniesFromFile();\r
420             }\r
421             if ( o == _open_url_item ) {\r
422                 readPhylogeniesFromURL();\r
423             }\r
424             else if ( o == _save_item ) {\r
425                 writeToFile( _mainpanel.getCurrentPhylogeny() );\r
426                 // If subtree currently displayed, save it, instead of complete\r
427                 // tree.\r
428             }\r
429             else if ( o == _new_item ) {\r
430                 newTree();\r
431             }\r
432             else if ( o == _save_all_item ) {\r
433                 writeAllToFile();\r
434             }\r
435             else if ( o == _close_item ) {\r
436                 closeCurrentPane();\r
437             }\r
438             else if ( o == _write_to_pdf_item ) {\r
439                 writeToPdf( _mainpanel.getCurrentPhylogeny() );\r
440             }\r
441             else if ( o == _write_to_jpg_item ) {\r
442                 writeToGraphicsFile( _mainpanel.getCurrentPhylogeny(), GraphicsExportType.JPG );\r
443             }\r
444             else if ( o == _write_to_png_item ) {\r
445                 writeToGraphicsFile( _mainpanel.getCurrentPhylogeny(), GraphicsExportType.PNG );\r
446             }\r
447             else if ( o == _write_to_gif_item ) {\r
448                 writeToGraphicsFile( _mainpanel.getCurrentPhylogeny(), GraphicsExportType.GIF );\r
449             }\r
450             else if ( o == _write_to_tif_item ) {\r
451                 writeToGraphicsFile( _mainpanel.getCurrentPhylogeny(), GraphicsExportType.TIFF );\r
452             }\r
453             else if ( o == _write_to_bmp_item ) {\r
454                 writeToGraphicsFile( _mainpanel.getCurrentPhylogeny(), GraphicsExportType.BMP );\r
455             }\r
456             else if ( o == _print_item ) {\r
457                 print();\r
458             }\r
459             else if ( o == _load_species_tree_item ) {\r
460                 readSpeciesTreeFromFile();\r
461             }\r
462             else if ( o == _lineage_inference ) {\r
463                 if ( isSubtreeDisplayed() ) {\r
464                     JOptionPane.showMessageDialog( this,\r
465                                                    "Subtree is shown.",\r
466                                                    "Cannot infer ancestral taxonomies",\r
467                                                    JOptionPane.ERROR_MESSAGE );\r
468                     return;\r
469                 }\r
470                 executeLineageInference();\r
471             }\r
472             else if ( o == _obtain_detailed_taxonomic_information_jmi ) {\r
473                 if ( isSubtreeDisplayed() ) {\r
474                     return;\r
475                 }\r
476                 obtainDetailedTaxonomicInformation();\r
477             }\r
478             else if ( o == _obtain_detailed_taxonomic_information_deleting_jmi ) {\r
479                 if ( isSubtreeDisplayed() ) {\r
480                     return;\r
481                 }\r
482                 obtainDetailedTaxonomicInformationDelete();\r
483             }\r
484             else if ( o == _obtain_seq_information_jmi ) {\r
485                 obtainSequenceInformation();\r
486             }\r
487             else if ( o == _read_values_jmi ) {\r
488                 if ( isSubtreeDisplayed() ) {\r
489                     return;\r
490                 }\r
491                 addExpressionValuesFromFile();\r
492             }\r
493             else if ( o == _read_seqs_jmi ) {\r
494                 if ( isSubtreeDisplayed() ) {\r
495                     return;\r
496                 }\r
497                 addSequencesFromFile();\r
498             }\r
499             else if ( o == _move_node_names_to_tax_sn_jmi ) {\r
500                 moveNodeNamesToTaxSn();\r
501             }\r
502             else if ( o == _move_node_names_to_seq_names_jmi ) {\r
503                 moveNodeNamesToSeqNames();\r
504             }\r
505             else if ( o == _extract_tax_code_from_node_names_jmi ) {\r
506                 extractTaxDataFromNodeNames();\r
507             }\r
508             else if ( o == _graphics_export_visible_only_cbmi ) {\r
509                 updateOptions( getOptions() );\r
510             }\r
511             else if ( o == _antialias_print_cbmi ) {\r
512                 updateOptions( getOptions() );\r
513             }\r
514             else if ( o == _print_black_and_white_cbmi ) {\r
515                 updateOptions( getOptions() );\r
516             }\r
517             else if ( o == _print_using_actual_size_cbmi ) {\r
518                 updateOptions( getOptions() );\r
519             }\r
520             else if ( o == _graphics_export_using_actual_size_cbmi ) {\r
521                 updateOptions( getOptions() );\r
522             }\r
523             else if ( o == _print_size_mi ) {\r
524                 choosePrintSize();\r
525             }\r
526             else if ( o == _choose_pdf_width_mi ) {\r
527                 choosePdfWidth();\r
528             }\r
529             else if ( o == _internal_number_are_confidence_for_nh_parsing_cbmi ) {\r
530                 updateOptions( getOptions() );\r
531             }\r
532             else if ( o == _replace_underscores_cbmi ) {\r
533                 if ( ( _extract_taxonomy_no_rbmi != null ) && !_extract_taxonomy_no_rbmi.isSelected() ) {\r
534                     _extract_taxonomy_no_rbmi.setSelected( true );\r
535                 }\r
536                 updateOptions( getOptions() );\r
537             }\r
538             else if ( o == _allow_errors_in_distance_to_parent_cbmi ) {\r
539                 updateOptions( getOptions() );\r
540             }\r
541             else if ( o == _collapse_below_threshold ) {\r
542                 if ( isSubtreeDisplayed() ) {\r
543                     return;\r
544                 }\r
545                 collapseBelowThreshold();\r
546             }\r
547             else if ( ( o == _extract_taxonomy_pfam_strict_rbmi ) || ( o == _extract_taxonomy_pfam_relaxed_rbmi )\r
548                     || ( o == _extract_taxonomy_agressive_rbmi ) ) {\r
549                 if ( _replace_underscores_cbmi != null ) {\r
550                     _replace_underscores_cbmi.setSelected( false );\r
551                 }\r
552                 updateOptions( getOptions() );\r
553             }\r
554             else if ( o == _extract_taxonomy_no_rbmi ) {\r
555                 updateOptions( getOptions() );\r
556             }\r
557             else if ( o == _inference_from_msa_item ) {\r
558                 executePhyleneticInference( false );\r
559             }\r
560             else if ( o == _inference_from_seqs_item ) {\r
561                 executePhyleneticInference( true );\r
562             }\r
563             _contentpane.repaint();\r
564         }\r
565         catch ( final Exception ex ) {\r
566             AptxUtil.unexpectedException( ex );\r
567         }\r
568         catch ( final Error err ) {\r
569             AptxUtil.unexpectedError( err );\r
570         }\r
571     }\r
572 \r
573     public void end() {\r
574         _mainpanel.terminate();\r
575         _contentpane.removeAll();\r
576         setVisible( false );\r
577         dispose();\r
578     }\r
579 \r
580     @Override\r
581     public MainPanel getMainPanel() {\r
582         return _mainpanel;\r
583     }\r
584 \r
585     public Msa getMsa() {\r
586         return _msa;\r
587     }\r
588 \r
589     public File getMsaFile() {\r
590         return _msa_file;\r
591     }\r
592 \r
593     public List<Sequence> getSeqs() {\r
594         return _seqs;\r
595     }\r
596 \r
597     public File getSeqsFile() {\r
598         return _seqs_file;\r
599     }\r
600 \r
601     public void readMsaFromFile() {\r
602         // Set an initial directory if none set yet\r
603         final File my_dir = getCurrentDir();\r
604         _msa_filechooser.setMultiSelectionEnabled( false );\r
605         // Open file-open dialog and set current directory\r
606         if ( my_dir != null ) {\r
607             _msa_filechooser.setCurrentDirectory( my_dir );\r
608         }\r
609         final int result = _msa_filechooser.showOpenDialog( _contentpane );\r
610         // All done: get the msa\r
611         final File file = _msa_filechooser.getSelectedFile();\r
612         setCurrentDir( _msa_filechooser.getCurrentDirectory() );\r
613         if ( ( file != null ) && !file.isDirectory() && ( result == JFileChooser.APPROVE_OPTION ) ) {\r
614             setMsaFile( null );\r
615             setMsa( null );\r
616             Msa msa = null;\r
617             try {\r
618                 final InputStream is = new FileInputStream( file );\r
619                 if ( FastaParser.isLikelyFasta( file ) ) {\r
620                     msa = FastaParser.parseMsa( is );\r
621                 }\r
622                 else {\r
623                     msa = GeneralMsaParser.parse( is );\r
624                 }\r
625             }\r
626             catch ( final MsaFormatException e ) {\r
627                 setArrowCursor();\r
628                 JOptionPane.showMessageDialog( this,\r
629                                                e.getLocalizedMessage(),\r
630                                                "Multiple sequence alignment format error",\r
631                                                JOptionPane.ERROR_MESSAGE );\r
632                 return;\r
633             }\r
634             catch ( final IOException e ) {\r
635                 setArrowCursor();\r
636                 JOptionPane.showMessageDialog( this,\r
637                                                e.getLocalizedMessage(),\r
638                                                "Failed to read multiple sequence alignment",\r
639                                                JOptionPane.ERROR_MESSAGE );\r
640                 return;\r
641             }\r
642             catch ( final IllegalArgumentException e ) {\r
643                 setArrowCursor();\r
644                 JOptionPane.showMessageDialog( this,\r
645                                                e.getLocalizedMessage(),\r
646                                                "Unexpected error during reading of multiple sequence alignment",\r
647                                                JOptionPane.ERROR_MESSAGE );\r
648                 return;\r
649             }\r
650             catch ( final Exception e ) {\r
651                 setArrowCursor();\r
652                 e.printStackTrace();\r
653                 JOptionPane.showMessageDialog( this,\r
654                                                e.getLocalizedMessage(),\r
655                                                "Unexpected error during reading of multiple sequence alignment",\r
656                                                JOptionPane.ERROR_MESSAGE );\r
657                 return;\r
658             }\r
659             if ( ( msa == null ) || ( msa.getNumberOfSequences() < 1 ) ) {\r
660                 JOptionPane.showMessageDialog( this,\r
661                                                "Multiple sequence alignment is empty",\r
662                                                "Illegal Multiple Sequence Alignment",\r
663                                                JOptionPane.ERROR_MESSAGE );\r
664                 return;\r
665             }\r
666             if ( msa.getNumberOfSequences() < 4 ) {\r
667                 JOptionPane.showMessageDialog( this,\r
668                                                "Multiple sequence alignment needs to contain at least 3 sequences",\r
669                                                "Illegal multiple sequence alignment",\r
670                                                JOptionPane.ERROR_MESSAGE );\r
671                 return;\r
672             }\r
673             if ( msa.getLength() < 2 ) {\r
674                 JOptionPane.showMessageDialog( this,\r
675                                                "Multiple sequence alignment needs to contain at least 2 residues",\r
676                                                "Illegal multiple sequence alignment",\r
677                                                JOptionPane.ERROR_MESSAGE );\r
678                 return;\r
679             }\r
680             System.gc();\r
681             setMsaFile( _msa_filechooser.getSelectedFile() );\r
682             setMsa( msa );\r
683         }\r
684     }\r
685 \r
686     public void readSeqsFromFileforPI() {\r
687         // Set an initial directory if none set yet\r
688         final File my_dir = getCurrentDir();\r
689         _seqs_pi_filechooser.setMultiSelectionEnabled( false );\r
690         // Open file-open dialog and set current directory\r
691         if ( my_dir != null ) {\r
692             _seqs_pi_filechooser.setCurrentDirectory( my_dir );\r
693         }\r
694         final int result = _seqs_pi_filechooser.showOpenDialog( _contentpane );\r
695         // All done: get the seqs\r
696         final File file = _seqs_pi_filechooser.getSelectedFile();\r
697         setCurrentDir( _seqs_pi_filechooser.getCurrentDirectory() );\r
698         if ( ( file != null ) && !file.isDirectory() && ( result == JFileChooser.APPROVE_OPTION ) ) {\r
699             setSeqsFile( null );\r
700             setSeqs( null );\r
701             List<Sequence> seqs = null;\r
702             try {\r
703                 if ( FastaParser.isLikelyFasta( new FileInputStream( file ) ) ) {\r
704                     seqs = FastaParser.parse( new FileInputStream( file ) );\r
705                     for( final Sequence seq : seqs ) {\r
706                         System.out.println( SequenceWriter.toFasta( seq, 60 ) );\r
707                     }\r
708                 }\r
709                 else {\r
710                     //TODO error\r
711                 }\r
712             }\r
713             catch ( final MsaFormatException e ) {\r
714                 setArrowCursor();\r
715                 JOptionPane.showMessageDialog( this,\r
716                                                e.getLocalizedMessage(),\r
717                                                "Multiple sequence file format error",\r
718                                                JOptionPane.ERROR_MESSAGE );\r
719                 return;\r
720             }\r
721             catch ( final IOException e ) {\r
722                 setArrowCursor();\r
723                 JOptionPane.showMessageDialog( this,\r
724                                                e.getLocalizedMessage(),\r
725                                                "Failed to read multiple sequence file",\r
726                                                JOptionPane.ERROR_MESSAGE );\r
727                 return;\r
728             }\r
729             catch ( final IllegalArgumentException e ) {\r
730                 setArrowCursor();\r
731                 JOptionPane.showMessageDialog( this,\r
732                                                e.getLocalizedMessage(),\r
733                                                "Unexpected error during reading of multiple sequence file",\r
734                                                JOptionPane.ERROR_MESSAGE );\r
735                 return;\r
736             }\r
737             catch ( final Exception e ) {\r
738                 setArrowCursor();\r
739                 e.printStackTrace();\r
740                 JOptionPane.showMessageDialog( this,\r
741                                                e.getLocalizedMessage(),\r
742                                                "Unexpected error during reading of multiple sequence file",\r
743                                                JOptionPane.ERROR_MESSAGE );\r
744                 return;\r
745             }\r
746             if ( ( seqs == null ) || ( seqs.size() < 1 ) ) {\r
747                 JOptionPane.showMessageDialog( this,\r
748                                                "Multiple sequence file is empty",\r
749                                                "Illegal multiple sequence file",\r
750                                                JOptionPane.ERROR_MESSAGE );\r
751                 return;\r
752             }\r
753             if ( seqs.size() < 4 ) {\r
754                 JOptionPane.showMessageDialog( this,\r
755                                                "Multiple sequence file needs to contain at least 3 sequences",\r
756                                                "Illegal multiple sequence file",\r
757                                                JOptionPane.ERROR_MESSAGE );\r
758                 return;\r
759             }\r
760             //  if ( msa.getLength() < 2 ) {\r
761             //       JOptionPane.showMessageDialog( this,\r
762             //                                      "Multiple sequence alignment needs to contain at least 2 residues",\r
763             //                                      "Illegal multiple sequence file",\r
764             //                                      JOptionPane.ERROR_MESSAGE );\r
765             //       return;\r
766             //   }\r
767             System.gc();\r
768             setSeqsFile( _seqs_pi_filechooser.getSelectedFile() );\r
769             setSeqs( seqs );\r
770         }\r
771     }\r
772 \r
773     void buildAnalysisMenu() {\r
774         _analysis_menu = MainFrame.createMenu( "Analysis", getConfiguration() );\r
775         _analysis_menu.add( _gsdi_item = new JMenuItem( "GSDI (Generalized Speciation Duplication Inference)" ) );\r
776         _analysis_menu.add( _gsdir_item = new JMenuItem( "GSDIR (GSDI with re-rooting)" ) );\r
777         _analysis_menu.add( _load_species_tree_item = new JMenuItem( "Load Species Tree..." ) );\r
778         customizeJMenuItem( _gsdi_item );\r
779         customizeJMenuItem( _gsdir_item );\r
780         customizeJMenuItem( _load_species_tree_item );\r
781         _analysis_menu.addSeparator();\r
782         _analysis_menu.add( _lineage_inference = new JMenuItem( INFER_ANCESTOR_TAXONOMIES ) );\r
783         customizeJMenuItem( _lineage_inference );\r
784         _lineage_inference.setToolTipText( "Inference of ancestor taxonomies/lineages" );\r
785         _jmenubar.add( _analysis_menu );\r
786     }\r
787 \r
788     @Override\r
789     void buildFileMenu() {\r
790         _file_jmenu = MainFrame.createMenu( "File", getConfiguration() );\r
791         _file_jmenu.add( _open_item = new JMenuItem( "Read Tree from File..." ) );\r
792         _file_jmenu.addSeparator();\r
793         _file_jmenu.add( _open_url_item = new JMenuItem( "Read Tree from URL/Webservice..." ) );\r
794         _file_jmenu.addSeparator();\r
795         final WebservicesManager webservices_manager = WebservicesManager.getInstance();\r
796         _load_phylogeny_from_webservice_menu_items = new JMenuItem[ webservices_manager\r
797                 .getAvailablePhylogeniesWebserviceClients().size() ];\r
798         for( int i = 0; i < webservices_manager.getAvailablePhylogeniesWebserviceClients().size(); ++i ) {\r
799             final PhylogeniesWebserviceClient client = webservices_manager.getAvailablePhylogeniesWebserviceClient( i );\r
800             _load_phylogeny_from_webservice_menu_items[ i ] = new JMenuItem( client.getMenuName() );\r
801             _file_jmenu.add( _load_phylogeny_from_webservice_menu_items[ i ] );\r
802         }\r
803         if ( getConfiguration().isEditable() ) {\r
804             _file_jmenu.addSeparator();\r
805             _file_jmenu.add( _new_item = new JMenuItem( "New" ) );\r
806             _new_item.setToolTipText( "to create a new tree with one node, as source for manual tree construction" );\r
807         }\r
808         _file_jmenu.addSeparator();\r
809         _file_jmenu.add( _save_item = new JMenuItem( "Save Tree As..." ) );\r
810         _file_jmenu.add( _save_all_item = new JMenuItem( "Save All Trees As..." ) );\r
811         _save_all_item.setToolTipText( "Write all phylogenies to one file." );\r
812         _save_all_item.setEnabled( false );\r
813         _file_jmenu.addSeparator();\r
814         _file_jmenu.add( _write_to_pdf_item = new JMenuItem( "Export to PDF file ..." ) );\r
815         if ( AptxUtil.canWriteFormat( "tif" ) || AptxUtil.canWriteFormat( "tiff" ) || AptxUtil.canWriteFormat( "TIF" ) ) {\r
816             _file_jmenu.add( _write_to_tif_item = new JMenuItem( "Export to TIFF file..." ) );\r
817         }\r
818         _file_jmenu.add( _write_to_png_item = new JMenuItem( "Export to PNG file..." ) );\r
819         _file_jmenu.add( _write_to_jpg_item = new JMenuItem( "Export to JPG file..." ) );\r
820         if ( AptxUtil.canWriteFormat( "gif" ) ) {\r
821             _file_jmenu.add( _write_to_gif_item = new JMenuItem( "Export to GIF file..." ) );\r
822         }\r
823         if ( AptxUtil.canWriteFormat( "bmp" ) ) {\r
824             _file_jmenu.add( _write_to_bmp_item = new JMenuItem( "Export to BMP file..." ) );\r
825         }\r
826         _file_jmenu.addSeparator();\r
827         _file_jmenu.add( _print_item = new JMenuItem( "Print..." ) );\r
828         _file_jmenu.addSeparator();\r
829         _file_jmenu.add( _close_item = new JMenuItem( "Close Tab" ) );\r
830         _close_item.setToolTipText( "To close the current pane." );\r
831         _close_item.setEnabled( true );\r
832         _file_jmenu.addSeparator();\r
833         _file_jmenu.add( _exit_item = new JMenuItem( "Exit" ) );\r
834         customizeJMenuItem( _open_item );\r
835         _open_item\r
836                 .setFont( new Font( _open_item.getFont().getFontName(), Font.BOLD, _open_item.getFont().getSize() + 4 ) );\r
837         customizeJMenuItem( _open_url_item );\r
838         for( int i = 0; i < webservices_manager.getAvailablePhylogeniesWebserviceClients().size(); ++i ) {\r
839             customizeJMenuItem( _load_phylogeny_from_webservice_menu_items[ i ] );\r
840         }\r
841         customizeJMenuItem( _save_item );\r
842         if ( getConfiguration().isEditable() ) {\r
843             customizeJMenuItem( _new_item );\r
844         }\r
845         customizeJMenuItem( _close_item );\r
846         customizeJMenuItem( _save_all_item );\r
847         customizeJMenuItem( _write_to_pdf_item );\r
848         customizeJMenuItem( _write_to_png_item );\r
849         customizeJMenuItem( _write_to_jpg_item );\r
850         customizeJMenuItem( _write_to_gif_item );\r
851         customizeJMenuItem( _write_to_tif_item );\r
852         customizeJMenuItem( _write_to_bmp_item );\r
853         customizeJMenuItem( _print_item );\r
854         customizeJMenuItem( _exit_item );\r
855         _jmenubar.add( _file_jmenu );\r
856     }\r
857 \r
858     void buildOptionsMenu() {\r
859         _options_jmenu = MainFrame.createMenu( OPTIONS_HEADER, getConfiguration() );\r
860         _options_jmenu.addChangeListener( new ChangeListener() {\r
861 \r
862             @Override\r
863             public void stateChanged( final ChangeEvent e ) {\r
864                 MainFrame.setOvPlacementColorChooseMenuItem( _overview_placment_mi, getOptions() );\r
865                 MainFrame.setTextColorChooseMenuItem( _switch_colors_mi, getCurrentTreePanel() );\r
866                 MainFrame\r
867                         .setTextMinSupportMenuItem( _choose_minimal_confidence_mi, getOptions(), getCurrentTreePanel() );\r
868                 MainFrame.setTextForFontChooserMenuItem( _choose_font_mi, MainFrame\r
869                         .createCurrentFontDesc( getMainPanel().getTreeFontSet() ) );\r
870                 setTextForGraphicsSizeChooserMenuItem( _print_size_mi, getOptions() );\r
871                 setTextForPdfLineWidthChooserMenuItem( _choose_pdf_width_mi, getOptions() );\r
872                 MainFrame.updateOptionsMenuDependingOnPhylogenyType( getMainPanel(),\r
873                                                                      _show_scale_cbmi,\r
874                                                                      _show_branch_length_values_cbmi,\r
875                                                                      _non_lined_up_cladograms_rbmi,\r
876                                                                      _uniform_cladograms_rbmi,\r
877                                                                      _ext_node_dependent_cladogram_rbmi,\r
878                                                                      _label_direction_cbmi );\r
879                 MainFrame.setCycleNodeFillMenuItem( _cycle_node_fill_mi, getOptions() );\r
880                 MainFrame.setCycleNodeShapeMenuItem( _cycle_node_shape_mi, getOptions() );\r
881                 MainFrame.setTextNodeSizeMenuItem( _choose_node_size_mi, getOptions() );\r
882             }\r
883         } );\r
884         _options_jmenu.add( customizeMenuItemAsLabel( new JMenuItem( DISPLAY_SUBHEADER ), getConfiguration() ) );\r
885         _options_jmenu\r
886                 .add( _ext_node_dependent_cladogram_rbmi = new JRadioButtonMenuItem( MainFrame.NONUNIFORM_CLADOGRAMS_LABEL ) );\r
887         _options_jmenu.add( _uniform_cladograms_rbmi = new JRadioButtonMenuItem( MainFrame.UNIFORM_CLADOGRAMS_LABEL ) );\r
888         _options_jmenu.add( _non_lined_up_cladograms_rbmi = new JRadioButtonMenuItem( NON_LINED_UP_CLADOGRAMS_LABEL ) );\r
889         _radio_group_1 = new ButtonGroup();\r
890         _radio_group_1.add( _ext_node_dependent_cladogram_rbmi );\r
891         _radio_group_1.add( _uniform_cladograms_rbmi );\r
892         _radio_group_1.add( _non_lined_up_cladograms_rbmi );\r
893         ///////\r
894         _options_jmenu.add( _show_overview_cbmi = new JCheckBoxMenuItem( SHOW_OVERVIEW_LABEL ) );\r
895         _options_jmenu.add( _show_scale_cbmi = new JCheckBoxMenuItem( DISPLAY_SCALE_LABEL ) );\r
896         _options_jmenu\r
897                 .add( _show_branch_length_values_cbmi = new JCheckBoxMenuItem( DISPLAY_BRANCH_LENGTH_VALUES_LABEL ) );\r
898         _options_jmenu\r
899                 .add( _show_default_node_shapes_internal_cbmi = new JCheckBoxMenuItem( DISPLAY_NODE_BOXES_LABEL_INT ) );\r
900         _options_jmenu\r
901                 .add( _show_default_node_shapes_external_cbmi = new JCheckBoxMenuItem( DISPLAY_NODE_BOXES_LABEL_EXT ) );\r
902         if ( getConfiguration().doDisplayOption( Configuration.show_domain_architectures ) ) {\r
903             _options_jmenu.add( _show_domain_labels = new JCheckBoxMenuItem( SHOW_DOMAIN_LABELS_LABEL ) );\r
904             _options_jmenu.add( _right_line_up_domains_cbmi = new JCheckBoxMenuItem( MainFrame.RIGHT_LINE_UP_DOMAINS ) );\r
905          }\r
906         _options_jmenu.add( _line_up_renderable_data_cbmi = new JCheckBoxMenuItem( MainFrame.LINE_UP_RENDERABLE_DATA ) );\r
907  \r
908         _options_jmenu.add( _show_annotation_ref_source = new JCheckBoxMenuItem( SHOW_ANN_REF_SOURCE_LABEL ) );\r
909         _options_jmenu.add( _show_confidence_stddev_cbmi = new JCheckBoxMenuItem( SHOW_CONF_STDDEV_LABEL ) );\r
910         _options_jmenu.add( _color_by_taxonomic_group_cbmi = new JCheckBoxMenuItem( COLOR_BY_TAXONOMIC_GROUP ) );\r
911         _options_jmenu.add( _color_labels_same_as_parent_branch = new JCheckBoxMenuItem( COLOR_LABELS_LABEL ) );\r
912         _color_labels_same_as_parent_branch.setToolTipText( MainFrame.COLOR_LABELS_TIP );\r
913         _options_jmenu.add( _abbreviate_scientific_names = new JCheckBoxMenuItem( ABBREV_SN_LABEL ) );\r
914         _options_jmenu.add( _label_direction_cbmi = new JCheckBoxMenuItem( LABEL_DIRECTION_LABEL ) );\r
915         _label_direction_cbmi.setToolTipText( LABEL_DIRECTION_TIP );\r
916         _options_jmenu.add( _screen_antialias_cbmi = new JCheckBoxMenuItem( SCREEN_ANTIALIAS_LABEL ) );\r
917         _options_jmenu.add( _background_gradient_cbmi = new JCheckBoxMenuItem( BG_GRAD_LABEL ) );\r
918         _options_jmenu.add( _cycle_node_shape_mi = new JMenuItem( MainFrame.CYCLE_NODE_SHAPE_LABEL ) );\r
919         _options_jmenu.add( _cycle_node_fill_mi = new JMenuItem( MainFrame.CYCLE_NODE_FILL_LABEL ) );\r
920         _options_jmenu.add( _choose_node_size_mi = new JMenuItem( MainFrame.CHOOSE_NODE_SIZE_LABEL ) );\r
921         _options_jmenu.add( _choose_minimal_confidence_mi = new JMenuItem( "" ) );\r
922         _options_jmenu.add( _overview_placment_mi = new JMenuItem( "" ) );\r
923         _options_jmenu.add( _switch_colors_mi = new JMenuItem( "" ) );\r
924         _options_jmenu.add( _choose_font_mi = new JMenuItem( "" ) );\r
925         ///////\r
926         _options_jmenu.addSeparator();\r
927         _options_jmenu.add( customizeMenuItemAsLabel( new JMenuItem( SEARCH_SUBHEADER ), getConfiguration() ) );\r
928         _options_jmenu.add( _search_case_senstive_cbmi = new JCheckBoxMenuItem( SEARCH_CASE_SENSITIVE_LABEL ) );\r
929         _options_jmenu.add( _search_whole_words_only_cbmi = new JCheckBoxMenuItem( SEARCH_TERMS_ONLY_LABEL ) );\r
930         _options_jmenu.add( _inverse_search_result_cbmi = new JCheckBoxMenuItem( INVERSE_SEARCH_RESULT_LABEL ) );\r
931         _options_jmenu.addSeparator();\r
932         _options_jmenu.add( customizeMenuItemAsLabel( new JMenuItem( "Graphics Export & Printing:" ),\r
933                                                       getConfiguration() ) );\r
934         _options_jmenu.add( _antialias_print_cbmi = new JCheckBoxMenuItem( "Antialias" ) );\r
935         _options_jmenu.add( _print_black_and_white_cbmi = new JCheckBoxMenuItem( "Export in Black and White" ) );\r
936         _options_jmenu\r
937                 .add( _print_using_actual_size_cbmi = new JCheckBoxMenuItem( "Use Current Image Size for PDF export and Printing" ) );\r
938         _options_jmenu\r
939                 .add( _graphics_export_using_actual_size_cbmi = new JCheckBoxMenuItem( "Use Current Image Size for PNG, JPG, and GIF export" ) );\r
940         _options_jmenu\r
941                 .add( _graphics_export_visible_only_cbmi = new JCheckBoxMenuItem( "Limit to Visible ('Screenshot') for PNG, JPG, and GIF export" ) );\r
942         _options_jmenu.add( _print_size_mi = new JMenuItem( "" ) );\r
943         _options_jmenu.add( _choose_pdf_width_mi = new JMenuItem( "" ) );\r
944         _options_jmenu.addSeparator();\r
945         _options_jmenu.add( customizeMenuItemAsLabel( new JMenuItem( "Newick/NHX/Nexus Input:" ), getConfiguration() ) );\r
946         _options_jmenu\r
947                 .add( _internal_number_are_confidence_for_nh_parsing_cbmi = new JCheckBoxMenuItem( "Internal Node Names are Confidence Values" ) );\r
948         _options_jmenu.add( _replace_underscores_cbmi = new JCheckBoxMenuItem( "Replace Underscores with Spaces" ) );\r
949         _options_jmenu\r
950                 .add( _allow_errors_in_distance_to_parent_cbmi = new JCheckBoxMenuItem( "Ignore Distance Values Format Errors" ) );\r
951         //\r
952         _options_jmenu.add( _extract_taxonomy_no_rbmi = new JRadioButtonMenuItem( "No Taxonomy Extraction" ) );\r
953         _options_jmenu\r
954                 .add( _extract_taxonomy_pfam_strict_rbmi = new JRadioButtonMenuItem( "Extract Taxonomy Codes/Ids from Pfam-style Node Names" ) );\r
955         _options_jmenu\r
956                 .add( _extract_taxonomy_pfam_relaxed_rbmi = new JRadioButtonMenuItem( "Extract Taxonomy Codes/Ids from Pfam-style like Node Names" ) );\r
957         _options_jmenu\r
958                 .add( _extract_taxonomy_agressive_rbmi = new JRadioButtonMenuItem( "Extract Taxonomy Codes/Ids/Scientific Names from Node Names" ) );\r
959         _extract_taxonomy_pfam_strict_rbmi\r
960                 .setToolTipText( "To extract taxonomy codes/ids from node names in the form of e.g. \"BCL2_MOUSE/123-304\" or \"BCL2_10090/123-304\"" );\r
961         _extract_taxonomy_pfam_relaxed_rbmi\r
962                 .setToolTipText( "To extract taxonomy codes/ids from node names in the form of e.g. \"bax_MOUSE\" or \"bax_10090\"" );\r
963         _extract_taxonomy_agressive_rbmi\r
964                 .setToolTipText( "To extract taxonomy codes/ids or scientific names from node names in the form of e.g. \"MOUSE\" or \"10090\" or \"xyz_Nematostella_vectensis\"" );\r
965         _radio_group_2 = new ButtonGroup();\r
966         _radio_group_2.add( _extract_taxonomy_no_rbmi );\r
967         _radio_group_2.add( _extract_taxonomy_pfam_strict_rbmi );\r
968         _radio_group_2.add( _extract_taxonomy_pfam_relaxed_rbmi );\r
969         _radio_group_2.add( _extract_taxonomy_agressive_rbmi );\r
970         // \r
971         _options_jmenu.add( customizeMenuItemAsLabel( new JMenuItem( "Newick/Nexus Output:" ), getConfiguration() ) );\r
972         _options_jmenu\r
973                 .add( _use_brackets_for_conf_in_nh_export_cbmi = new JCheckBoxMenuItem( USE_BRACKETS_FOR_CONF_IN_NH_LABEL ) );\r
974         _use_brackets_for_conf_in_nh_export_cbmi\r
975                 .setToolTipText( "e.g. \"0.1[90]\" for a branch with support 90 and a length of 0.1" );\r
976         _options_jmenu\r
977                 .add( _use_internal_names_for_conf_in_nh_export_cbmi = new JCheckBoxMenuItem( USE_INTERNAL_NAMES_FOR_CONF_IN_NH_LABEL ) );\r
978         customizeJMenuItem( _choose_font_mi );\r
979         customizeJMenuItem( _choose_minimal_confidence_mi );\r
980         customizeJMenuItem( _switch_colors_mi );\r
981         customizeJMenuItem( _print_size_mi );\r
982         customizeJMenuItem( _choose_pdf_width_mi );\r
983         customizeJMenuItem( _overview_placment_mi );\r
984         customizeCheckBoxMenuItem( _show_default_node_shapes_external_cbmi, getOptions()\r
985                 .isShowDefaultNodeShapesExternal() );\r
986         customizeCheckBoxMenuItem( _show_default_node_shapes_internal_cbmi, getOptions()\r
987                 .isShowDefaultNodeShapesInternal() );\r
988         customizeJMenuItem( _cycle_node_shape_mi );\r
989         customizeJMenuItem( _cycle_node_fill_mi );\r
990         customizeJMenuItem( _choose_node_size_mi );\r
991         customizeCheckBoxMenuItem( _color_labels_same_as_parent_branch, getOptions().isColorLabelsSameAsParentBranch() );\r
992         customizeCheckBoxMenuItem( _color_by_taxonomic_group_cbmi, getOptions().isColorByTaxonomicGroup() );\r
993         customizeCheckBoxMenuItem( _screen_antialias_cbmi, getOptions().isAntialiasScreen() );\r
994         customizeCheckBoxMenuItem( _background_gradient_cbmi, getOptions().isBackgroundColorGradient() );\r
995         customizeCheckBoxMenuItem( _show_domain_labels, getOptions().isShowDomainLabels() );\r
996         customizeCheckBoxMenuItem( _show_annotation_ref_source, getOptions().isShowAnnotationRefSource() );\r
997         customizeCheckBoxMenuItem( _abbreviate_scientific_names, getOptions().isAbbreviateScientificTaxonNames() );\r
998         customizeCheckBoxMenuItem( _search_case_senstive_cbmi, getOptions().isSearchCaseSensitive() );\r
999         customizeCheckBoxMenuItem( _show_scale_cbmi, getOptions().isShowScale() );\r
1000         customizeRadioButtonMenuItem( _non_lined_up_cladograms_rbmi,\r
1001                                       getOptions().getCladogramType() == CLADOGRAM_TYPE.NON_LINED_UP );\r
1002         customizeRadioButtonMenuItem( _uniform_cladograms_rbmi,\r
1003                                       getOptions().getCladogramType() == CLADOGRAM_TYPE.TOTAL_NODE_SUM_DEP );\r
1004         customizeRadioButtonMenuItem( _ext_node_dependent_cladogram_rbmi,\r
1005                                       getOptions().getCladogramType() == CLADOGRAM_TYPE.EXT_NODE_SUM_DEP );\r
1006         customizeCheckBoxMenuItem( _show_branch_length_values_cbmi, getOptions().isShowBranchLengthValues() );\r
1007         customizeCheckBoxMenuItem( _show_overview_cbmi, getOptions().isShowOverview() );\r
1008         customizeCheckBoxMenuItem( _label_direction_cbmi,\r
1009                                    getOptions().getNodeLabelDirection() == NODE_LABEL_DIRECTION.RADIAL );\r
1010         customizeCheckBoxMenuItem( _antialias_print_cbmi, getOptions().isAntialiasPrint() );\r
1011         customizeCheckBoxMenuItem( _print_black_and_white_cbmi, getOptions().isPrintBlackAndWhite() );\r
1012         customizeCheckBoxMenuItem( _internal_number_are_confidence_for_nh_parsing_cbmi, getOptions()\r
1013                 .isInternalNumberAreConfidenceForNhParsing() );\r
1014         customizeRadioButtonMenuItem( _extract_taxonomy_no_rbmi,\r
1015                                       getOptions().getTaxonomyExtraction() == TAXONOMY_EXTRACTION.NO );\r
1016         customizeRadioButtonMenuItem( _extract_taxonomy_pfam_strict_rbmi,\r
1017                                       getOptions().getTaxonomyExtraction() == TAXONOMY_EXTRACTION.PFAM_STYLE_STRICT );\r
1018         customizeRadioButtonMenuItem( _extract_taxonomy_pfam_relaxed_rbmi,\r
1019                                       getOptions().getTaxonomyExtraction() == TAXONOMY_EXTRACTION.PFAM_STYLE_RELAXED );\r
1020         customizeRadioButtonMenuItem( _extract_taxonomy_agressive_rbmi,\r
1021                                       getOptions().getTaxonomyExtraction() == TAXONOMY_EXTRACTION.AGGRESSIVE );\r
1022         customizeCheckBoxMenuItem( _replace_underscores_cbmi, getOptions().isReplaceUnderscoresInNhParsing() );\r
1023         customizeCheckBoxMenuItem( _allow_errors_in_distance_to_parent_cbmi, getOptions()\r
1024                 .isReplaceUnderscoresInNhParsing() );\r
1025         customizeCheckBoxMenuItem( _search_whole_words_only_cbmi, getOptions().isMatchWholeTermsOnly() );\r
1026         customizeCheckBoxMenuItem( _inverse_search_result_cbmi, getOptions().isInverseSearchResult() );\r
1027         customizeCheckBoxMenuItem( _graphics_export_visible_only_cbmi, getOptions().isGraphicsExportVisibleOnly() );\r
1028         customizeCheckBoxMenuItem( _print_using_actual_size_cbmi, getOptions().isPrintUsingActualSize() );\r
1029         customizeCheckBoxMenuItem( _graphics_export_using_actual_size_cbmi, getOptions()\r
1030                 .isGraphicsExportUsingActualSize() );\r
1031         customizeCheckBoxMenuItem( _show_confidence_stddev_cbmi, getOptions().isShowConfidenceStddev() );\r
1032         customizeCheckBoxMenuItem( _use_brackets_for_conf_in_nh_export_cbmi, getOptions()\r
1033                 .getNhConversionSupportValueStyle() == NH_CONVERSION_SUPPORT_VALUE_STYLE.IN_SQUARE_BRACKETS );\r
1034         customizeCheckBoxMenuItem( _use_internal_names_for_conf_in_nh_export_cbmi, getOptions()\r
1035                 .getNhConversionSupportValueStyle() == NH_CONVERSION_SUPPORT_VALUE_STYLE.AS_INTERNAL_NODE_NAMES );\r
1036       \r
1037         \r
1038         customizeCheckBoxMenuItem( _line_up_renderable_data_cbmi, getOptions().isLineUpRendarableNodeData()\r
1039                                     );\r
1040         \r
1041         customizeCheckBoxMenuItem( _right_line_up_domains_cbmi, getOptions().isRightLineUpDomains() );\r
1042         _jmenubar.add( _options_jmenu );\r
1043     }\r
1044 \r
1045     void buildPhylogeneticInferenceMenu() {\r
1046         final InferenceManager im = getInferenceManager();\r
1047         _inference_menu = MainFrame.createMenu( "Inference", getConfiguration() );\r
1048         _inference_menu.add( _inference_from_msa_item = new JMenuItem( "From Multiple Sequence Alignment..." ) );\r
1049         customizeJMenuItem( _inference_from_msa_item );\r
1050         _inference_from_msa_item.setToolTipText( "Basic phylogenetic inference from MSA" );\r
1051         if ( im.canDoMsa() ) {\r
1052             _inference_menu.add( _inference_from_seqs_item = new JMenuItem( "From Unaligned Sequences..." ) );\r
1053             customizeJMenuItem( _inference_from_seqs_item );\r
1054             _inference_from_seqs_item\r
1055                     .setToolTipText( "Basic phylogenetic inference including multiple sequence alignment" );\r
1056         }\r
1057         else {\r
1058             _inference_menu\r
1059                     .add( _inference_from_seqs_item = new JMenuItem( "From Unaligned Sequences (no program found)" ) );\r
1060             customizeJMenuItem( _inference_from_seqs_item );\r
1061             _inference_from_seqs_item.setEnabled( false );\r
1062         }\r
1063         _jmenubar.add( _inference_menu );\r
1064     }\r
1065 \r
1066     void buildToolsMenu() {\r
1067         _tools_menu = createMenu( "Tools", getConfiguration() );\r
1068         _tools_menu.add( _confcolor_item = new JMenuItem( "Colorize Branches Depending on Confidence" ) );\r
1069         customizeJMenuItem( _confcolor_item );\r
1070         _tools_menu.add( _color_rank_jmi = new JMenuItem( "Colorize Subtrees via Taxonomic Rank" ) );\r
1071         customizeJMenuItem( _color_rank_jmi );\r
1072         _color_rank_jmi.setToolTipText( "for example, at \"Class\" level, colorize mammal specific subtree red" );\r
1073         _tools_menu.add( _taxcolor_item = new JMenuItem( "Taxonomy Colorize Branches" ) );\r
1074         customizeJMenuItem( _taxcolor_item );\r
1075         _tools_menu.addSeparator();\r
1076         _tools_menu.add( _remove_visual_styles_item = new JMenuItem( "Delete All Visual Styles From Nodes" ) );\r
1077         _remove_visual_styles_item\r
1078                 .setToolTipText( "To remove all node visual styles (fonts, colors) from the current phylogeny" );\r
1079         customizeJMenuItem( _remove_visual_styles_item );\r
1080         _tools_menu.add( _remove_branch_color_item = new JMenuItem( "Delete All Colors From Branches" ) );\r
1081         _remove_branch_color_item.setToolTipText( "To remove all branch color values from the current phylogeny" );\r
1082         customizeJMenuItem( _remove_branch_color_item );\r
1083         _tools_menu.addSeparator();\r
1084         _tools_menu.add( _annotate_item = new JMenuItem( "Annotate Sequences of Selected Nodes" ) );\r
1085         customizeJMenuItem( _annotate_item );\r
1086         _tools_menu.addSeparator();\r
1087         _tools_menu.add( _midpoint_root_item = new JMenuItem( "Midpoint-Root" ) );\r
1088         customizeJMenuItem( _midpoint_root_item );\r
1089         _tools_menu.addSeparator();\r
1090         _tools_menu.add( _delete_selected_nodes_item = new JMenuItem( "Delete Selected Nodes" ) );\r
1091         _delete_selected_nodes_item.setToolTipText( "To delete all selected external nodes" );\r
1092         customizeJMenuItem( _delete_selected_nodes_item );\r
1093         _tools_menu.add( _delete_not_selected_nodes_item = new JMenuItem( "Retain Selected Nodes" ) );\r
1094         _delete_not_selected_nodes_item.setToolTipText( "To delete all not selected external nodes" );\r
1095         \r
1096         customizeJMenuItem( _delete_not_selected_nodes_item );\r
1097         _tools_menu.addSeparator();\r
1098         _tools_menu.add( _collapse_species_specific_subtrees = new JMenuItem( "Collapse Species-Specific Subtrees" ) );\r
1099         customizeJMenuItem( _collapse_species_specific_subtrees );\r
1100         _tools_menu\r
1101                 .add( _collapse_below_threshold = new JMenuItem( "Collapse Branches with Confidence Below Threshold into Multifurcations" ) );\r
1102         customizeJMenuItem( _collapse_below_threshold );\r
1103         _collapse_below_threshold\r
1104                 .setToolTipText( "To collapse branches with confidence values below a threshold into multifurcations (in the case of multiple confidences per branch: without at least one confidence value above a threshold)" );\r
1105         _tools_menu.addSeparator();\r
1106         _tools_menu\r
1107                 .add( _extract_tax_code_from_node_names_jmi = new JMenuItem( "Extract Taxonomic Data from Node Names" ) );\r
1108         customizeJMenuItem( _extract_tax_code_from_node_names_jmi );\r
1109         _extract_tax_code_from_node_names_jmi\r
1110                 .setToolTipText( "To extract SwissProt/Uniprot taxonomic codes (mnemonics) from nodes names in the form of 'xyz_CAEEL', Uniprot/NCBI identifiers form of 'xyz_6239', or scientific names form of 'xyz_Caenorhabditis_elegans'" );\r
1111         _tools_menu\r
1112                 .add( _move_node_names_to_tax_sn_jmi = new JMenuItem( "Transfer Node Names to Taxonomic Scientific Names" ) );\r
1113         customizeJMenuItem( _move_node_names_to_tax_sn_jmi );\r
1114         _move_node_names_to_tax_sn_jmi.setToolTipText( "To interpret node names as taxonomic scientific names" );\r
1115         _tools_menu.add( _move_node_names_to_seq_names_jmi = new JMenuItem( "Transfer Node Names to Sequence Names" ) );\r
1116         customizeJMenuItem( _move_node_names_to_seq_names_jmi );\r
1117         _move_node_names_to_seq_names_jmi.setToolTipText( "To interpret node names as sequence (protein, gene) names" );\r
1118         _tools_menu.addSeparator();\r
1119         _tools_menu.add( _obtain_seq_information_jmi = new JMenuItem( "Obtain Sequence Information" ) );\r
1120         customizeJMenuItem( _obtain_seq_information_jmi );\r
1121         _obtain_seq_information_jmi.setToolTipText( "To add additional sequence information" );\r
1122         _tools_menu\r
1123                 .add( _obtain_detailed_taxonomic_information_jmi = new JMenuItem( OBTAIN_DETAILED_TAXONOMIC_INFORMATION ) );\r
1124         customizeJMenuItem( _obtain_detailed_taxonomic_information_jmi );\r
1125         _obtain_detailed_taxonomic_information_jmi\r
1126                 .setToolTipText( "To add additional taxonomic information (from UniProt Taxonomy)" );\r
1127         _tools_menu\r
1128                 .add( _obtain_detailed_taxonomic_information_deleting_jmi = new JMenuItem( "Obtain Detailed Taxonomic Information (deletes nodes!)" ) );\r
1129         customizeJMenuItem( _obtain_detailed_taxonomic_information_deleting_jmi );\r
1130         _obtain_detailed_taxonomic_information_deleting_jmi\r
1131                 .setToolTipText( "To add additional taxonomic information, deletes nodes for which taxonomy cannot found (from UniProt Taxonomy)" );\r
1132         _tools_menu.addSeparator();\r
1133         _tools_menu.add( _read_values_jmi = new JMenuItem( "Attach Vector/Expression Values" ) );\r
1134         customizeJMenuItem( _read_values_jmi );\r
1135         _read_values_jmi.setToolTipText( "To attach vector (e.g. gene expression) values to tree nodes (beta)" );\r
1136         _jmenubar.add( _tools_menu );\r
1137         _tools_menu.add( _read_seqs_jmi = new JMenuItem( "Attach Molecular Sequences" ) );\r
1138         customizeJMenuItem( _read_seqs_jmi );\r
1139         _read_seqs_jmi\r
1140                 .setToolTipText( "To attach molecular sequences to tree nodes (from Fasta-formatted file) (beta)" );\r
1141         _jmenubar.add( _tools_menu );\r
1142     }\r
1143 \r
1144     @Override\r
1145     void close() {\r
1146         if ( isUnsavedDataPresent() ) {\r
1147             final int r = JOptionPane.showConfirmDialog( this,\r
1148                                                          "Exit despite potentially unsaved changes?",\r
1149                                                          "Exit?",\r
1150                                                          JOptionPane.YES_NO_OPTION );\r
1151             if ( r != JOptionPane.YES_OPTION ) {\r
1152                 return;\r
1153             }\r
1154         }\r
1155         exit();\r
1156     }\r
1157 \r
1158     void executeLineageInference() {\r
1159         if ( ( _mainpanel.getCurrentPhylogeny() == null ) || ( _mainpanel.getCurrentPhylogeny().isEmpty() ) ) {\r
1160             return;\r
1161         }\r
1162         if ( !_mainpanel.getCurrentPhylogeny().isRooted() ) {\r
1163             JOptionPane.showMessageDialog( this,\r
1164                                            "Phylogeny is not rooted.",\r
1165                                            "Cannot infer ancestral taxonomies",\r
1166                                            JOptionPane.ERROR_MESSAGE );\r
1167             return;\r
1168         }\r
1169         final AncestralTaxonomyInferrer inferrer = new AncestralTaxonomyInferrer( this,\r
1170                                                                                   _mainpanel.getCurrentTreePanel(),\r
1171                                                                                   _mainpanel.getCurrentPhylogeny()\r
1172                                                                                           .copy() );\r
1173         new Thread( inferrer ).start();\r
1174     }\r
1175 \r
1176     void exit() {\r
1177         removeAllTextFrames();\r
1178         _mainpanel.terminate();\r
1179         _contentpane.removeAll();\r
1180         setVisible( false );\r
1181         dispose();\r
1182         System.exit( 0 );\r
1183     }\r
1184 \r
1185     void readPhylogeniesFromURL() {\r
1186         URL url = null;\r
1187         Phylogeny[] phys = null;\r
1188         final String message = "Please enter a complete URL, for example \"http://purl.org/phylo/treebase/phylows/study/TB2:S15480?format=nexus\"";\r
1189         final String url_string = JOptionPane.showInputDialog( this,\r
1190                                                                message,\r
1191                                                                "Use URL/webservice to obtain a phylogeny",\r
1192                                                                JOptionPane.QUESTION_MESSAGE );\r
1193         boolean nhx_or_nexus = false;\r
1194         if ( ( url_string != null ) && ( url_string.length() > 0 ) ) {\r
1195             try {\r
1196                 url = new URL( url_string );\r
1197                 PhylogenyParser parser = null;\r
1198                 if ( url.getHost().toLowerCase().indexOf( "tolweb" ) >= 0 ) {\r
1199                     parser = new TolParser();\r
1200                 }\r
1201                 else {\r
1202                     parser = ParserUtils.createParserDependingOnUrlContents( url, getConfiguration()\r
1203                             .isValidatePhyloXmlAgainstSchema() );\r
1204                 }\r
1205                 if ( parser instanceof NexusPhylogeniesParser ) {\r
1206                     nhx_or_nexus = true;\r
1207                 }\r
1208                 else if ( parser instanceof NHXParser ) {\r
1209                     nhx_or_nexus = true;\r
1210                 }\r
1211                 if ( _mainpanel.getCurrentTreePanel() != null ) {\r
1212                     _mainpanel.getCurrentTreePanel().setWaitCursor();\r
1213                 }\r
1214                 else {\r
1215                     _mainpanel.setWaitCursor();\r
1216                 }\r
1217                 final PhylogenyFactory factory = ParserBasedPhylogenyFactory.getInstance();\r
1218                 phys = factory.create( url.openStream(), parser );\r
1219             }\r
1220             catch ( final MalformedURLException e ) {\r
1221                 JOptionPane.showMessageDialog( this,\r
1222                                                "Malformed URL: " + url + "\n" + e.getLocalizedMessage(),\r
1223                                                "Malformed URL",\r
1224                                                JOptionPane.ERROR_MESSAGE );\r
1225             }\r
1226             catch ( final IOException e ) {\r
1227                 JOptionPane.showMessageDialog( this,\r
1228                                                "Could not read from " + url + "\n"\r
1229                                                        + ForesterUtil.wordWrap( e.getLocalizedMessage(), 80 ),\r
1230                                                "Failed to read URL",\r
1231                                                JOptionPane.ERROR_MESSAGE );\r
1232             }\r
1233             catch ( final Exception e ) {\r
1234                 JOptionPane.showMessageDialog( this,\r
1235                                                ForesterUtil.wordWrap( e.getLocalizedMessage(), 80 ),\r
1236                                                "Unexpected Exception",\r
1237                                                JOptionPane.ERROR_MESSAGE );\r
1238             }\r
1239             finally {\r
1240                 if ( _mainpanel.getCurrentTreePanel() != null ) {\r
1241                     _mainpanel.getCurrentTreePanel().setArrowCursor();\r
1242                 }\r
1243                 else {\r
1244                     _mainpanel.setArrowCursor();\r
1245                 }\r
1246             }\r
1247             if ( ( phys != null ) && ( phys.length > 0 ) ) {\r
1248                 if ( nhx_or_nexus && getOptions().isInternalNumberAreConfidenceForNhParsing() ) {\r
1249                     for( final Phylogeny phy : phys ) {\r
1250                         \r
1251                         PhylogenyMethods.transferInternalNodeNamesToConfidence( phy, "" );\r
1252                     }\r
1253                 }\r
1254                 AptxUtil.addPhylogeniesToTabs( phys,\r
1255                                                new File( url.getFile() ).getName(),\r
1256                                                new File( url.getFile() ).toString(),\r
1257                                                getConfiguration(),\r
1258                                                getMainPanel() );\r
1259                 _mainpanel.getControlPanel().showWhole();\r
1260             }\r
1261         }\r
1262         activateSaveAllIfNeeded();\r
1263         System.gc();\r
1264     }\r
1265 \r
1266     void setMsa( final Msa msa ) {\r
1267         _msa = msa;\r
1268     }\r
1269 \r
1270     void setMsaFile( final File msa_file ) {\r
1271         _msa_file = msa_file;\r
1272     }\r
1273 \r
1274     void setSeqs( final List<Sequence> seqs ) {\r
1275         _seqs = seqs;\r
1276     }\r
1277 \r
1278     void setSeqsFile( final File seqs_file ) {\r
1279         _seqs_file = seqs_file;\r
1280     }\r
1281 \r
1282     void writePhylogenyToGraphicsFile( final String file_name, final GraphicsExportType type ) {\r
1283         _mainpanel.getCurrentTreePanel().calcParametersForPainting( _mainpanel.getCurrentTreePanel().getWidth(),\r
1284                                                                     _mainpanel.getCurrentTreePanel().getHeight(),\r
1285                                                                     true );\r
1286         String file_written_to = "";\r
1287         boolean error = false;\r
1288         try {\r
1289             file_written_to = AptxUtil.writePhylogenyToGraphicsFile( file_name,\r
1290                                                                      _mainpanel.getCurrentTreePanel().getWidth(),\r
1291                                                                      _mainpanel.getCurrentTreePanel().getHeight(),\r
1292                                                                      _mainpanel.getCurrentTreePanel(),\r
1293                                                                      _mainpanel.getControlPanel(),\r
1294                                                                      type,\r
1295                                                                      getOptions() );\r
1296         }\r
1297         catch ( final IOException e ) {\r
1298             error = true;\r
1299             JOptionPane.showMessageDialog( this, e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE );\r
1300         }\r
1301         if ( !error ) {\r
1302             if ( ( file_written_to != null ) && ( file_written_to.length() > 0 ) ) {\r
1303                 JOptionPane.showMessageDialog( this,\r
1304                                                "Wrote image to: " + file_written_to,\r
1305                                                "Graphics Export",\r
1306                                                JOptionPane.INFORMATION_MESSAGE );\r
1307             }\r
1308             else {\r
1309                 JOptionPane.showMessageDialog( this,\r
1310                                                "There was an unknown problem when attempting to write to an image file: \""\r
1311                                                        + file_name + "\"",\r
1312                                                "Error",\r
1313                                                JOptionPane.ERROR_MESSAGE );\r
1314             }\r
1315         }\r
1316         _contentpane.repaint();\r
1317     }\r
1318 \r
1319     private void addExpressionValuesFromFile() {\r
1320         if ( ( getCurrentTreePanel() == null ) || ( getCurrentTreePanel().getPhylogeny() == null ) ) {\r
1321             JOptionPane.showMessageDialog( this,\r
1322                                            "Need to load evolutionary tree first",\r
1323                                            "Can Not Read Expression Values",\r
1324                                            JOptionPane.WARNING_MESSAGE );\r
1325             return;\r
1326         }\r
1327         final File my_dir = getCurrentDir();\r
1328         if ( my_dir != null ) {\r
1329             _values_filechooser.setCurrentDirectory( my_dir );\r
1330         }\r
1331         final int result = _values_filechooser.showOpenDialog( _contentpane );\r
1332         final File file = _values_filechooser.getSelectedFile();\r
1333         if ( ( file != null ) && ( file.length() > 0 ) && ( result == JFileChooser.APPROVE_OPTION ) ) {\r
1334             BasicTable<String> t = null;\r
1335             try {\r
1336                 t = BasicTableParser.parse( file, '\t' );\r
1337                 if ( t.getNumberOfColumns() < 2 ) {\r
1338                     t = BasicTableParser.parse( file, ',' );\r
1339                 }\r
1340                 if ( t.getNumberOfColumns() < 2 ) {\r
1341                     t = BasicTableParser.parse( file, ' ' );\r
1342                 }\r
1343             }\r
1344             catch ( final IOException e ) {\r
1345                 JOptionPane.showMessageDialog( this,\r
1346                                                e.getMessage(),\r
1347                                                "Could Not Read Expression Value Table",\r
1348                                                JOptionPane.ERROR_MESSAGE );\r
1349                 return;\r
1350             }\r
1351             if ( t.getNumberOfColumns() < 2 ) {\r
1352                 JOptionPane.showMessageDialog( this,\r
1353                                                "Table contains " + t.getNumberOfColumns() + " column(s)",\r
1354                                                "Problem with Expression Value Table",\r
1355                                                JOptionPane.ERROR_MESSAGE );\r
1356                 return;\r
1357             }\r
1358             if ( t.getNumberOfRows() < 1 ) {\r
1359                 JOptionPane.showMessageDialog( this,\r
1360                                                "Table contains zero rows",\r
1361                                                "Problem with Expression Value Table",\r
1362                                                JOptionPane.ERROR_MESSAGE );\r
1363                 return;\r
1364             }\r
1365             final Phylogeny phy = getCurrentTreePanel().getPhylogeny();\r
1366             if ( t.getNumberOfRows() != phy.getNumberOfExternalNodes() ) {\r
1367                 JOptionPane.showMessageDialog( this,\r
1368                                                "Table contains " + t.getNumberOfRows() + " rows, but tree contains "\r
1369                                                        + phy.getNumberOfExternalNodes() + " external nodes",\r
1370                                                "Warning",\r
1371                                                JOptionPane.WARNING_MESSAGE );\r
1372             }\r
1373             final DescriptiveStatistics stats = new BasicDescriptiveStatistics();\r
1374             int not_found = 0;\r
1375             for( final PhylogenyNodeIterator iter = phy.iteratorPreorder(); iter.hasNext(); ) {\r
1376                 final PhylogenyNode node = iter.next();\r
1377                 final String node_name = node.getName();\r
1378                 if ( !ForesterUtil.isEmpty( node_name ) ) {\r
1379                     int row = -1;\r
1380                     try {\r
1381                         row = t.findRow( node_name );\r
1382                     }\r
1383                     catch ( final IllegalArgumentException e ) {\r
1384                         JOptionPane\r
1385                                 .showMessageDialog( this,\r
1386                                                     e.getMessage(),\r
1387                                                     "Error Mapping Node Identifiers to Expression Value Identifiers",\r
1388                                                     JOptionPane.ERROR_MESSAGE );\r
1389                         return;\r
1390                     }\r
1391                     if ( row < 0 ) {\r
1392                         if ( node.isExternal() ) {\r
1393                             not_found++;\r
1394                         }\r
1395                         continue;\r
1396                     }\r
1397                     final List<Double> l = new ArrayList<Double>();\r
1398                     for( int col = 1; col < t.getNumberOfColumns(); ++col ) {\r
1399                         double d = -100;\r
1400                         try {\r
1401                             d = Double.parseDouble( t.getValueAsString( col, row ) );\r
1402                         }\r
1403                         catch ( final NumberFormatException e ) {\r
1404                             JOptionPane.showMessageDialog( this,\r
1405                                                            "Could not parse \"" + t.getValueAsString( col, row )\r
1406                                                                    + "\" into a decimal value",\r
1407                                                            "Issue with Expression Value Table",\r
1408                                                            JOptionPane.ERROR_MESSAGE );\r
1409                             return;\r
1410                         }\r
1411                         stats.addValue( d );\r
1412                         l.add( d );\r
1413                     }\r
1414                     if ( !l.isEmpty() ) {\r
1415                         if ( node.getNodeData().getProperties() != null ) {\r
1416                             node.getNodeData().getProperties()\r
1417                                     .removePropertiesWithGivenReferencePrefix( PhyloXmlUtil.VECTOR_PROPERTY_REF );\r
1418                         }\r
1419                         node.getNodeData().setVector( l );\r
1420                     }\r
1421                 }\r
1422             }\r
1423             if ( not_found > 0 ) {\r
1424                 JOptionPane.showMessageDialog( this, "Could not fine expression values for " + not_found\r
1425                         + " external node(s)", "Warning", JOptionPane.WARNING_MESSAGE );\r
1426             }\r
1427             getCurrentTreePanel().setStatisticsForExpressionValues( stats );\r
1428         }\r
1429     }\r
1430 \r
1431     private void addSequencesFromFile() {\r
1432         if ( ( getCurrentTreePanel() == null ) || ( getCurrentTreePanel().getPhylogeny() == null ) ) {\r
1433             JOptionPane.showMessageDialog( this,\r
1434                                            "Need to load evolutionary tree first",\r
1435                                            "Can Not Read Sequences",\r
1436                                            JOptionPane.WARNING_MESSAGE );\r
1437             return;\r
1438         }\r
1439         final File my_dir = getCurrentDir();\r
1440         if ( my_dir != null ) {\r
1441             _sequences_filechooser.setCurrentDirectory( my_dir );\r
1442         }\r
1443         final int result = _sequences_filechooser.showOpenDialog( _contentpane );\r
1444         final File file = _sequences_filechooser.getSelectedFile();\r
1445         List<Sequence> seqs = null;\r
1446         if ( ( file != null ) && !file.isDirectory() && ( result == JFileChooser.APPROVE_OPTION ) ) {\r
1447             try {\r
1448                 if ( FastaParser.isLikelyFasta( new FileInputStream( file ) ) ) {\r
1449                     seqs = FastaParser.parse( new FileInputStream( file ) );\r
1450                 }\r
1451                 else {\r
1452                     JOptionPane.showMessageDialog( this,\r
1453                                                    "Format does not appear to be Fasta",\r
1454                                                    "Multiple sequence file format error",\r
1455                                                    JOptionPane.ERROR_MESSAGE );\r
1456                     return;\r
1457                 }\r
1458             }\r
1459             catch ( final MsaFormatException e ) {\r
1460                 setArrowCursor();\r
1461                 JOptionPane.showMessageDialog( this,\r
1462                                                e.getLocalizedMessage(),\r
1463                                                "Multiple sequence file format error",\r
1464                                                JOptionPane.ERROR_MESSAGE );\r
1465                 return;\r
1466             }\r
1467             catch ( final IOException e ) {\r
1468                 setArrowCursor();\r
1469                 JOptionPane.showMessageDialog( this,\r
1470                                                e.getLocalizedMessage(),\r
1471                                                "Failed to read multiple sequence file",\r
1472                                                JOptionPane.ERROR_MESSAGE );\r
1473                 return;\r
1474             }\r
1475             catch ( final Exception e ) {\r
1476                 setArrowCursor();\r
1477                 e.printStackTrace();\r
1478                 JOptionPane.showMessageDialog( this,\r
1479                                                e.getLocalizedMessage(),\r
1480                                                "Unexpected error during reading of multiple sequence file",\r
1481                                                JOptionPane.ERROR_MESSAGE );\r
1482                 return;\r
1483             }\r
1484             if ( ( seqs == null ) || ( seqs.size() < 1 ) ) {\r
1485                 JOptionPane.showMessageDialog( this,\r
1486                                                "Multiple sequence file is empty",\r
1487                                                "Empty multiple sequence file",\r
1488                                                JOptionPane.ERROR_MESSAGE );\r
1489                 setArrowCursor();\r
1490                 return;\r
1491             }\r
1492         }\r
1493         if ( seqs != null ) {\r
1494             for( final Sequence seq : seqs ) {\r
1495                 System.out.println( seq.getIdentifier() );\r
1496             }\r
1497             final Phylogeny phy = getCurrentTreePanel().getPhylogeny();\r
1498             int total_counter = 0;\r
1499             int attached_counter = 0;\r
1500             for( final Sequence seq : seqs ) {\r
1501                 ++total_counter;\r
1502                 final String seq_name = seq.getIdentifier();\r
1503                 if ( !ForesterUtil.isEmpty( seq_name ) ) {\r
1504                     List<PhylogenyNode> nodes = phy.getNodesViaSequenceName( seq_name );\r
1505                     if ( nodes.isEmpty() ) {\r
1506                         nodes = phy.getNodesViaSequenceSymbol( seq_name );\r
1507                     }\r
1508                     if ( nodes.isEmpty() ) {\r
1509                         nodes = phy.getNodesViaGeneName( seq_name );\r
1510                     }\r
1511                     if ( nodes.isEmpty() ) {\r
1512                         nodes = phy.getNodes( seq_name );\r
1513                     }\r
1514                     if ( nodes.size() > 1 ) {\r
1515                         JOptionPane.showMessageDialog( this,\r
1516                                                        "Sequence name \"" + seq_name + "\" is not unique",\r
1517                                                        "Sequence name not unique",\r
1518                                                        JOptionPane.ERROR_MESSAGE );\r
1519                         setArrowCursor();\r
1520                         return;\r
1521                     }\r
1522                     final String[] a = seq_name.split( "\\s" );\r
1523                     if ( nodes.isEmpty() && ( a.length > 1 ) ) {\r
1524                         final String seq_name_split = a[ 0 ];\r
1525                         nodes = phy.getNodesViaSequenceName( seq_name_split );\r
1526                         if ( nodes.isEmpty() ) {\r
1527                             nodes = phy.getNodesViaSequenceSymbol( seq_name_split );\r
1528                         }\r
1529                         if ( nodes.isEmpty() ) {\r
1530                             nodes = phy.getNodes( seq_name_split );\r
1531                         }\r
1532                         if ( nodes.size() > 1 ) {\r
1533                             JOptionPane.showMessageDialog( this, "Split sequence name \"" + seq_name_split\r
1534                                     + "\" is not unique", "Sequence name not unique", JOptionPane.ERROR_MESSAGE );\r
1535                             setArrowCursor();\r
1536                             return;\r
1537                         }\r
1538                     }\r
1539                     if ( nodes.size() == 1 ) {\r
1540                         ++attached_counter;\r
1541                         final PhylogenyNode n = nodes.get( 0 );\r
1542                         if ( !n.getNodeData().isHasSequence() ) {\r
1543                             n.getNodeData().addSequence( new org.forester.phylogeny.data.Sequence() );\r
1544                         }\r
1545                         n.getNodeData().getSequence().setMolecularSequence( seq.getMolecularSequenceAsString() );\r
1546                         if ( ForesterUtil.isEmpty( n.getNodeData().getSequence().getName() ) ) {\r
1547                             n.getNodeData().getSequence().setName( seq_name );\r
1548                         }\r
1549                     }\r
1550                 }\r
1551             }\r
1552             if ( attached_counter > 0 ) {\r
1553                 int ext_nodes = 0;\r
1554                 int ext_nodes_with_seq = 0;\r
1555                 for( final PhylogenyNodeIterator iter = phy.iteratorExternalForward(); iter.hasNext(); ) {\r
1556                     ++ext_nodes;\r
1557                     final PhylogenyNode n = iter.next();\r
1558                     if ( n.getNodeData().isHasSequence()\r
1559                             && !ForesterUtil.isEmpty( n.getNodeData().getSequence().getMolecularSequence() ) ) {\r
1560                         ++ext_nodes_with_seq;\r
1561                     }\r
1562                 }\r
1563                 final String s;\r
1564                 if ( ext_nodes == ext_nodes_with_seq ) {\r
1565                     s = "All " + ext_nodes_with_seq + " external nodes now have a molecular sequence attached to them.";\r
1566                 }\r
1567                 else {\r
1568                     s = ext_nodes_with_seq + " out of " + ext_nodes\r
1569                             + " external nodes now have a molecular sequence attached to them.";\r
1570                 }\r
1571                 if ( ( attached_counter == total_counter ) && ( ext_nodes == ext_nodes_with_seq ) ) {\r
1572                     JOptionPane.showMessageDialog( this,\r
1573                                                    "Attached all " + total_counter + " sequences to tree nodes.\n" + s,\r
1574                                                    "All sequences attached",\r
1575                                                    JOptionPane.INFORMATION_MESSAGE );\r
1576                 }\r
1577                 else {\r
1578                     JOptionPane.showMessageDialog( this, "Attached " + attached_counter\r
1579                             + " sequences out of a total of " + total_counter + " sequences.\n" + s, attached_counter\r
1580                             + " sequences attached", JOptionPane.WARNING_MESSAGE );\r
1581                 }\r
1582             }\r
1583             else {\r
1584                 JOptionPane.showMessageDialog( this, "No maching tree node for any of the " + total_counter\r
1585                         + " sequences", "Could not attach any sequences", JOptionPane.ERROR_MESSAGE );\r
1586             }\r
1587         }\r
1588     }\r
1589 \r
1590     private void choosePdfWidth() {\r
1591         final String s = ( String ) JOptionPane.showInputDialog( this,\r
1592                                                                  "Please enter the default line width for PDF export.\n"\r
1593                                                                          + "[current value: "\r
1594                                                                          + getOptions().getPrintLineWidth() + "]\n",\r
1595                                                                  "Line Width for PDF Export",\r
1596                                                                  JOptionPane.QUESTION_MESSAGE,\r
1597                                                                  null,\r
1598                                                                  null,\r
1599                                                                  getOptions().getPrintLineWidth() );\r
1600         if ( !ForesterUtil.isEmpty( s ) ) {\r
1601             boolean success = true;\r
1602             float f = 0.0f;\r
1603             final String m_str = s.trim();\r
1604             if ( !ForesterUtil.isEmpty( m_str ) ) {\r
1605                 try {\r
1606                     f = Float.parseFloat( m_str );\r
1607                 }\r
1608                 catch ( final Exception ex ) {\r
1609                     success = false;\r
1610                 }\r
1611             }\r
1612             else {\r
1613                 success = false;\r
1614             }\r
1615             if ( success && ( f > 0.0 ) ) {\r
1616                 getOptions().setPrintLineWidth( f );\r
1617             }\r
1618         }\r
1619     }\r
1620 \r
1621     private void choosePrintSize() {\r
1622         final String s = ( String ) JOptionPane.showInputDialog( this,\r
1623                                                                  "Please enter values for width and height,\nseparated by a comma.\n"\r
1624                                                                          + "[current values: "\r
1625                                                                          + getOptions().getPrintSizeX() + ", "\r
1626                                                                          + getOptions().getPrintSizeY() + "]\n"\r
1627                                                                          + "[A4: " + Constants.A4_SIZE_X + ", "\r
1628                                                                          + Constants.A4_SIZE_Y + "]\n" + "[US Letter: "\r
1629                                                                          + Constants.US_LETTER_SIZE_X + ", "\r
1630                                                                          + Constants.US_LETTER_SIZE_Y + "]",\r
1631                                                                  "Default Size for Graphics Export",\r
1632                                                                  JOptionPane.QUESTION_MESSAGE,\r
1633                                                                  null,\r
1634                                                                  null,\r
1635                                                                  getOptions().getPrintSizeX() + ", "\r
1636                                                                          + getOptions().getPrintSizeY() );\r
1637         if ( !ForesterUtil.isEmpty( s ) && ( s.indexOf( ',' ) > 0 ) ) {\r
1638             boolean success = true;\r
1639             int x = 0;\r
1640             int y = 0;\r
1641             final String[] str_ary = s.split( "," );\r
1642             if ( str_ary.length == 2 ) {\r
1643                 final String x_str = str_ary[ 0 ].trim();\r
1644                 final String y_str = str_ary[ 1 ].trim();\r
1645                 if ( !ForesterUtil.isEmpty( x_str ) && !ForesterUtil.isEmpty( y_str ) ) {\r
1646                     try {\r
1647                         x = Integer.parseInt( x_str );\r
1648                         y = Integer.parseInt( y_str );\r
1649                     }\r
1650                     catch ( final Exception ex ) {\r
1651                         success = false;\r
1652                     }\r
1653                 }\r
1654                 else {\r
1655                     success = false;\r
1656                 }\r
1657             }\r
1658             else {\r
1659                 success = false;\r
1660             }\r
1661             if ( success && ( x > 1 ) && ( y > 1 ) ) {\r
1662                 getOptions().setPrintSizeX( x );\r
1663                 getOptions().setPrintSizeY( y );\r
1664             }\r
1665         }\r
1666     }\r
1667 \r
1668     private void closeCurrentPane() {\r
1669         if ( getMainPanel().getCurrentTreePanel() != null ) {\r
1670             if ( getMainPanel().getCurrentTreePanel().isEdited() ) {\r
1671                 final int r = JOptionPane.showConfirmDialog( this,\r
1672                                                              "Close tab despite potentially unsaved changes?",\r
1673                                                              "Close Tab?",\r
1674                                                              JOptionPane.YES_NO_OPTION );\r
1675                 if ( r != JOptionPane.YES_OPTION ) {\r
1676                     return;\r
1677                 }\r
1678             }\r
1679             getMainPanel().closeCurrentPane();\r
1680             activateSaveAllIfNeeded();\r
1681         }\r
1682     }\r
1683 \r
1684     private void collapse( final Phylogeny phy, final double m ) {\r
1685         final PhylogenyNodeIterator it = phy.iteratorPostorder();\r
1686         final List<PhylogenyNode> to_be_removed = new ArrayList<PhylogenyNode>();\r
1687         double min_support = Double.MAX_VALUE;\r
1688         boolean conf_present = false;\r
1689         while ( it.hasNext() ) {\r
1690             final PhylogenyNode n = it.next();\r
1691             if ( !n.isExternal() && !n.isRoot() ) {\r
1692                 final List<Confidence> c = n.getBranchData().getConfidences();\r
1693                 if ( ( c != null ) && ( c.size() > 0 ) ) {\r
1694                     conf_present = true;\r
1695                     double max = 0;\r
1696                     for( final Confidence confidence : c ) {\r
1697                         if ( confidence.getValue() > max ) {\r
1698                             max = confidence.getValue();\r
1699                         }\r
1700                     }\r
1701                     if ( max < getMinNotCollapseConfidenceValue() ) {\r
1702                         to_be_removed.add( n );\r
1703                     }\r
1704                     if ( max < min_support ) {\r
1705                         min_support = max;\r
1706                     }\r
1707                 }\r
1708             }\r
1709         }\r
1710         if ( conf_present ) {\r
1711             for( final PhylogenyNode node : to_be_removed ) {\r
1712                 PhylogenyMethods.removeNode( node, phy );\r
1713             }\r
1714             if ( to_be_removed.size() > 0 ) {\r
1715                 phy.externalNodesHaveChanged();\r
1716                 phy.clearHashIdToNodeMap();\r
1717                 phy.recalculateNumberOfExternalDescendants( true );\r
1718                 getCurrentTreePanel().resetNodeIdToDistToLeafMap();\r
1719                 getCurrentTreePanel().updateSetOfCollapsedExternalNodes();\r
1720                 getCurrentTreePanel().calculateLongestExtNodeInfo();\r
1721                 getCurrentTreePanel().setNodeInPreorderToNull();\r
1722                 getCurrentTreePanel().recalculateMaxDistanceToRoot();\r
1723                 getCurrentTreePanel().resetPreferredSize();\r
1724                 getCurrentTreePanel().setEdited( true );\r
1725                 getCurrentTreePanel().repaint();\r
1726                 repaint();\r
1727             }\r
1728             if ( to_be_removed.size() > 0 ) {\r
1729                 JOptionPane.showMessageDialog( this, "Collapsed " + to_be_removed.size()\r
1730                         + " branches with\nconfidence values below " + getMinNotCollapseConfidenceValue(), "Collapsed "\r
1731                         + to_be_removed.size() + " branches", JOptionPane.INFORMATION_MESSAGE );\r
1732             }\r
1733             else {\r
1734                 JOptionPane.showMessageDialog( this, "No branch collapsed,\nminimum confidence value per branch is "\r
1735                         + min_support, "No branch collapsed", JOptionPane.INFORMATION_MESSAGE );\r
1736             }\r
1737         }\r
1738         else {\r
1739             JOptionPane.showMessageDialog( this,\r
1740                                            "No branch collapsed because no confidence values present",\r
1741                                            "No confidence values present",\r
1742                                            JOptionPane.INFORMATION_MESSAGE );\r
1743         }\r
1744     }\r
1745 \r
1746     private void collapseBelowThreshold() {\r
1747         if ( getCurrentTreePanel() != null ) {\r
1748             final Phylogeny phy = getCurrentTreePanel().getPhylogeny();\r
1749             if ( ( phy != null ) && !phy.isEmpty() ) {\r
1750                 final String s = ( String ) JOptionPane.showInputDialog( this,\r
1751                                                                          "Please enter the minimum confidence value\n",\r
1752                                                                          "Minimal Confidence Value",\r
1753                                                                          JOptionPane.QUESTION_MESSAGE,\r
1754                                                                          null,\r
1755                                                                          null,\r
1756                                                                          getMinNotCollapseConfidenceValue() );\r
1757                 if ( !ForesterUtil.isEmpty( s ) ) {\r
1758                     boolean success = true;\r
1759                     double m = 0.0;\r
1760                     final String m_str = s.trim();\r
1761                     if ( !ForesterUtil.isEmpty( m_str ) ) {\r
1762                         try {\r
1763                             m = Double.parseDouble( m_str );\r
1764                         }\r
1765                         catch ( final Exception ex ) {\r
1766                             success = false;\r
1767                         }\r
1768                     }\r
1769                     else {\r
1770                         success = false;\r
1771                     }\r
1772                     if ( success && ( m >= 0.0 ) ) {\r
1773                         setMinNotCollapseConfidenceValue( m );\r
1774                         collapse( phy, m );\r
1775                     }\r
1776                 }\r
1777             }\r
1778         }\r
1779     }\r
1780 \r
1781     private PhyloXmlParser createPhyloXmlParser() {\r
1782         PhyloXmlParser xml_parser = null;\r
1783         if ( getConfiguration().isValidatePhyloXmlAgainstSchema() ) {\r
1784             try {\r
1785                 xml_parser = PhyloXmlParser.createPhyloXmlParserXsdValidating();\r
1786             }\r
1787             catch ( final Exception e ) {\r
1788                 JOptionPane.showMessageDialog( this,\r
1789                                                e.getLocalizedMessage(),\r
1790                                                "failed to create validating XML parser",\r
1791                                                JOptionPane.WARNING_MESSAGE );\r
1792             }\r
1793         }\r
1794         if ( xml_parser == null ) {\r
1795             xml_parser = PhyloXmlParser.createPhyloXmlParser();\r
1796         }\r
1797         return xml_parser;\r
1798     }\r
1799 \r
1800     private void executePhyleneticInference( final boolean from_unaligned_seqs ) {\r
1801         final PhyloInferenceDialog dialog = new PhyloInferenceDialog( this,\r
1802                                                                       getPhylogeneticInferenceOptions(),\r
1803                                                                       from_unaligned_seqs );\r
1804         dialog.activate();\r
1805         if ( dialog.getValue() == JOptionPane.OK_OPTION ) {\r
1806             if ( !from_unaligned_seqs ) {\r
1807                 if ( getMsa() != null ) {\r
1808                     final PhylogeneticInferrer inferrer = new PhylogeneticInferrer( getMsa(),\r
1809                                                                                     getPhylogeneticInferenceOptions()\r
1810                                                                                             .copy(), this );\r
1811                     new Thread( inferrer ).start();\r
1812                 }\r
1813                 else {\r
1814                     JOptionPane.showMessageDialog( this,\r
1815                                                    "No multiple sequence alignment selected",\r
1816                                                    "Phylogenetic Inference Not Launched",\r
1817                                                    JOptionPane.WARNING_MESSAGE );\r
1818                 }\r
1819             }\r
1820             else {\r
1821                 if ( getSeqs() != null ) {\r
1822                     final PhylogeneticInferrer inferrer = new PhylogeneticInferrer( getSeqs(),\r
1823                                                                                     getPhylogeneticInferenceOptions()\r
1824                                                                                             .copy(), this );\r
1825                     new Thread( inferrer ).start();\r
1826                 }\r
1827                 else {\r
1828                     JOptionPane.showMessageDialog( this,\r
1829                                                    "No input sequences selected",\r
1830                                                    "Phylogenetic Inference Not Launched",\r
1831                                                    JOptionPane.WARNING_MESSAGE );\r
1832                 }\r
1833             }\r
1834         }\r
1835     }\r
1836 \r
1837     private void extractTaxDataFromNodeNames() throws PhyloXmlDataFormatException {\r
1838         final StringBuilder sb = new StringBuilder();\r
1839         final StringBuilder sb_failed = new StringBuilder();\r
1840         int counter = 0;\r
1841         int counter_failed = 0;\r
1842         if ( getCurrentTreePanel() != null ) {\r
1843             final Phylogeny phy = getCurrentTreePanel().getPhylogeny();\r
1844             if ( ( phy != null ) && !phy.isEmpty() ) {\r
1845                 final PhylogenyNodeIterator it = phy.iteratorExternalForward();\r
1846                 while ( it.hasNext() ) {\r
1847                     final PhylogenyNode n = it.next();\r
1848                     final String name = n.getName().trim();\r
1849                     if ( !ForesterUtil.isEmpty( name ) ) {\r
1850                         final String nt = ParserUtils.extractTaxonomyDataFromNodeName( n,\r
1851                                                                                        TAXONOMY_EXTRACTION.AGGRESSIVE );\r
1852                         if ( !ForesterUtil.isEmpty( nt ) ) {\r
1853                             if ( counter < 15 ) {\r
1854                                 sb.append( name + ": " + nt + "\n" );\r
1855                             }\r
1856                             else if ( counter == 15 ) {\r
1857                                 sb.append( "...\n" );\r
1858                             }\r
1859                             counter++;\r
1860                         }\r
1861                         else {\r
1862                             if ( counter_failed < 15 ) {\r
1863                                 sb_failed.append( name + "\n" );\r
1864                             }\r
1865                             else if ( counter_failed == 15 ) {\r
1866                                 sb_failed.append( "...\n" );\r
1867                             }\r
1868                             counter_failed++;\r
1869                         }\r
1870                     }\r
1871                 }\r
1872                 if ( counter > 0 ) {\r
1873                     String failed = "";\r
1874                     String all = "all ";\r
1875                     if ( counter_failed > 0 ) {\r
1876                         all = "";\r
1877                         failed = "\nCould not extract taxonomic data for " + counter_failed\r
1878                                 + " named external nodes:\n" + sb_failed;\r
1879                     }\r
1880                     JOptionPane.showMessageDialog( this,\r
1881                                                    "Extracted taxonomic data from " + all + counter\r
1882                                                            + " named external nodes:\n" + sb.toString() + failed,\r
1883                                                    "Taxonomic Data Extraction Completed",\r
1884                                                    counter_failed > 0 ? JOptionPane.WARNING_MESSAGE\r
1885                                                            : JOptionPane.INFORMATION_MESSAGE );\r
1886                 }\r
1887                 else {\r
1888                     JOptionPane\r
1889                             .showMessageDialog( this,\r
1890                                                 "Could not extract any taxonomic data.\nMaybe node names are empty\n"\r
1891                                                         + "or not in the forms \"XYZ_CAEEL\", \"XYZ_6239\", or \"XYZ_Caenorhabditis_elegans\"\n"\r
1892                                                         + "or nodes already have taxonomic data?\n",\r
1893                                                 "No Taxonomic Data Extracted",\r
1894                                                 JOptionPane.ERROR_MESSAGE );\r
1895                 }\r
1896             }\r
1897         }\r
1898     }\r
1899 \r
1900     private ControlPanel getControlPanel() {\r
1901         return getMainPanel().getControlPanel();\r
1902     }\r
1903 \r
1904     private File getCurrentDir() {\r
1905         if ( ( _current_dir == null ) || !_current_dir.canRead() ) {\r
1906             if ( ForesterUtil.isWindows() ) {\r
1907                 try {\r
1908                     _current_dir = new File( WindowsUtils.getCurrentUserDesktopPath() );\r
1909                 }\r
1910                 catch ( final Exception e ) {\r
1911                     _current_dir = null;\r
1912                 }\r
1913             }\r
1914         }\r
1915         if ( ( _current_dir == null ) || !_current_dir.canRead() ) {\r
1916             if ( System.getProperty( "user.home" ) != null ) {\r
1917                 _current_dir = new File( System.getProperty( "user.home" ) );\r
1918             }\r
1919             else if ( System.getProperty( "user.dir" ) != null ) {\r
1920                 _current_dir = new File( System.getProperty( "user.dir" ) );\r
1921             }\r
1922         }\r
1923         return _current_dir;\r
1924     }\r
1925 \r
1926     private double getMinNotCollapseConfidenceValue() {\r
1927         return _min_not_collapse;\r
1928     }\r
1929 \r
1930     private PhylogeneticInferenceOptions getPhylogeneticInferenceOptions() {\r
1931         if ( _phylogenetic_inference_options == null ) {\r
1932             _phylogenetic_inference_options = new PhylogeneticInferenceOptions();\r
1933         }\r
1934         return _phylogenetic_inference_options;\r
1935     }\r
1936 \r
1937     private boolean isUnsavedDataPresent() {\r
1938         final List<TreePanel> tps = getMainPanel().getTreePanels();\r
1939         for( final TreePanel tp : tps ) {\r
1940             if ( tp.isEdited() ) {\r
1941                 return true;\r
1942             }\r
1943         }\r
1944         return false;\r
1945     }\r
1946 \r
1947     private void moveNodeNamesToSeqNames() throws PhyloXmlDataFormatException {\r
1948         if ( getCurrentTreePanel() != null ) {\r
1949             final Phylogeny phy = getCurrentTreePanel().getPhylogeny();\r
1950             if ( ( phy != null ) && !phy.isEmpty() ) {\r
1951                 PhylogenyMethods\r
1952                         .transferNodeNameToField( phy, PhylogenyMethods.PhylogenyNodeField.SEQUENCE_NAME, false );\r
1953             }\r
1954         }\r
1955     }\r
1956 \r
1957     private void moveNodeNamesToTaxSn() throws PhyloXmlDataFormatException {\r
1958         if ( getCurrentTreePanel() != null ) {\r
1959             final Phylogeny phy = getCurrentTreePanel().getPhylogeny();\r
1960             if ( ( phy != null ) && !phy.isEmpty() ) {\r
1961                 PhylogenyMethods.transferNodeNameToField( phy,\r
1962                                                           PhylogenyMethods.PhylogenyNodeField.TAXONOMY_SCIENTIFIC_NAME,\r
1963                                                           false );\r
1964             }\r
1965         }\r
1966     }\r
1967 \r
1968     private void newTree() {\r
1969         final Phylogeny[] phys = new Phylogeny[ 1 ];\r
1970         final Phylogeny phy = new Phylogeny();\r
1971         final PhylogenyNode node = new PhylogenyNode();\r
1972         phy.setRoot( node );\r
1973         phy.setRooted( true );\r
1974         phys[ 0 ] = phy;\r
1975         AptxUtil.addPhylogeniesToTabs( phys, "", "", getConfiguration(), getMainPanel() );\r
1976         _mainpanel.getControlPanel().showWhole();\r
1977         _mainpanel.getCurrentTreePanel().setPhylogenyGraphicsType( PHYLOGENY_GRAPHICS_TYPE.RECTANGULAR );\r
1978         _mainpanel.getOptions().setPhylogenyGraphicsType( PHYLOGENY_GRAPHICS_TYPE.RECTANGULAR );\r
1979         if ( getMainPanel().getMainFrame() == null ) {\r
1980             // Must be "E" applet version.\r
1981             ( ( ArchaeopteryxE ) ( ( MainPanelApplets ) getMainPanel() ).getApplet() )\r
1982                     .setSelectedTypeInTypeMenu( PHYLOGENY_GRAPHICS_TYPE.RECTANGULAR );\r
1983         }\r
1984         else {\r
1985             getMainPanel().getMainFrame().setSelectedTypeInTypeMenu( PHYLOGENY_GRAPHICS_TYPE.RECTANGULAR );\r
1986         }\r
1987         activateSaveAllIfNeeded();\r
1988         System.gc();\r
1989     }\r
1990 \r
1991     private void obtainDetailedTaxonomicInformation() {\r
1992         if ( getCurrentTreePanel() != null ) {\r
1993             final Phylogeny phy = getCurrentTreePanel().getPhylogeny();\r
1994             if ( ( phy != null ) && !phy.isEmpty() ) {\r
1995                 final TaxonomyDataManager t = new TaxonomyDataManager( this,\r
1996                                                                        _mainpanel.getCurrentTreePanel(),\r
1997                                                                        phy.copy(),\r
1998                                                                        false,\r
1999                                                                        true );\r
2000                 new Thread( t ).start();\r
2001             }\r
2002         }\r
2003     }\r
2004 \r
2005     private void obtainDetailedTaxonomicInformationDelete() {\r
2006         if ( getCurrentTreePanel() != null ) {\r
2007             final Phylogeny phy = getCurrentTreePanel().getPhylogeny();\r
2008             if ( ( phy != null ) && !phy.isEmpty() ) {\r
2009                 final TaxonomyDataManager t = new TaxonomyDataManager( this,\r
2010                                                                        _mainpanel.getCurrentTreePanel(),\r
2011                                                                        phy.copy(),\r
2012                                                                        true,\r
2013                                                                        true );\r
2014                 new Thread( t ).start();\r
2015             }\r
2016         }\r
2017     }\r
2018 \r
2019     private void obtainSequenceInformation() {\r
2020         if ( getCurrentTreePanel() != null ) {\r
2021             final Phylogeny phy = getCurrentTreePanel().getPhylogeny();\r
2022             if ( ( phy != null ) && !phy.isEmpty() ) {\r
2023                 final SequenceDataRetriver u = new SequenceDataRetriver( this,\r
2024                                                                          _mainpanel.getCurrentTreePanel(),\r
2025                                                                          phy.copy() );\r
2026                 new Thread( u ).start();\r
2027             }\r
2028         }\r
2029     }\r
2030 \r
2031     private void print() {\r
2032         if ( ( getCurrentTreePanel() == null ) || ( getCurrentTreePanel().getPhylogeny() == null )\r
2033                 || getCurrentTreePanel().getPhylogeny().isEmpty() ) {\r
2034             return;\r
2035         }\r
2036         if ( !getOptions().isPrintUsingActualSize() ) {\r
2037             getCurrentTreePanel().calcParametersForPainting( getOptions().getPrintSizeX() - 80,\r
2038                                                              getOptions().getPrintSizeY() - 140,\r
2039                                                              true );\r
2040             getCurrentTreePanel().resetPreferredSize();\r
2041             getCurrentTreePanel().repaint();\r
2042         }\r
2043         final String job_name = Constants.PRG_NAME;\r
2044         boolean error = false;\r
2045         String printer_name = null;\r
2046         try {\r
2047             printer_name = Printer.print( getCurrentTreePanel(), job_name );\r
2048         }\r
2049         catch ( final Exception e ) {\r
2050             error = true;\r
2051             JOptionPane.showMessageDialog( this, e.getMessage(), "Printing Error", JOptionPane.ERROR_MESSAGE );\r
2052         }\r
2053         if ( !error && ( printer_name != null ) ) {\r
2054             String msg = "Printing data sent to printer";\r
2055             if ( printer_name.length() > 1 ) {\r
2056                 msg += " [" + printer_name + "]";\r
2057             }\r
2058             JOptionPane.showMessageDialog( this, msg, "Printing...", JOptionPane.INFORMATION_MESSAGE );\r
2059         }\r
2060         if ( !getOptions().isPrintUsingActualSize() ) {\r
2061             getControlPanel().showWhole();\r
2062         }\r
2063     }\r
2064 \r
2065     private void printPhylogenyToPdf( final String file_name ) {\r
2066         if ( !getOptions().isPrintUsingActualSize() ) {\r
2067             getCurrentTreePanel().calcParametersForPainting( getOptions().getPrintSizeX(),\r
2068                                                              getOptions().getPrintSizeY(),\r
2069                                                              true );\r
2070             getCurrentTreePanel().resetPreferredSize();\r
2071             getCurrentTreePanel().repaint();\r
2072         }\r
2073         String pdf_written_to = "";\r
2074         boolean error = false;\r
2075         try {\r
2076             if ( getOptions().isPrintUsingActualSize() ) {\r
2077                 pdf_written_to = PdfExporter.writePhylogenyToPdf( file_name,\r
2078                                                                   getCurrentTreePanel(),\r
2079                                                                   getCurrentTreePanel().getWidth(),\r
2080                                                                   getCurrentTreePanel().getHeight() );\r
2081             }\r
2082             else {\r
2083                 pdf_written_to = PdfExporter.writePhylogenyToPdf( file_name, getCurrentTreePanel(), getOptions()\r
2084                         .getPrintSizeX(), getOptions().getPrintSizeY() );\r
2085             }\r
2086         }\r
2087         catch ( final IOException e ) {\r
2088             error = true;\r
2089             JOptionPane.showMessageDialog( this, e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE );\r
2090         }\r
2091         if ( !error ) {\r
2092             if ( !ForesterUtil.isEmpty( pdf_written_to ) ) {\r
2093                 JOptionPane.showMessageDialog( this,\r
2094                                                "Wrote PDF to: " + pdf_written_to,\r
2095                                                "Information",\r
2096                                                JOptionPane.INFORMATION_MESSAGE );\r
2097             }\r
2098             else {\r
2099                 JOptionPane.showMessageDialog( this,\r
2100                                                "There was an unknown problem when attempting to write to PDF file: \""\r
2101                                                        + file_name + "\"",\r
2102                                                "Error",\r
2103                                                JOptionPane.ERROR_MESSAGE );\r
2104             }\r
2105         }\r
2106         if ( !getOptions().isPrintUsingActualSize() ) {\r
2107             getControlPanel().showWhole();\r
2108         }\r
2109     }\r
2110 \r
2111     private void readPhylogeniesFromFile() {\r
2112         boolean exception = false;\r
2113         Phylogeny[] phys = null;\r
2114         // Set an initial directory if none set yet\r
2115         final File my_dir = getCurrentDir();\r
2116         _open_filechooser.setMultiSelectionEnabled( true );\r
2117         // Open file-open dialog and set current directory\r
2118         if ( my_dir != null ) {\r
2119             _open_filechooser.setCurrentDirectory( my_dir );\r
2120         }\r
2121         final int result = _open_filechooser.showOpenDialog( _contentpane );\r
2122         // All done: get the file\r
2123         final File[] files = _open_filechooser.getSelectedFiles();\r
2124         setCurrentDir( _open_filechooser.getCurrentDirectory() );\r
2125         boolean nhx_or_nexus = false;\r
2126         if ( ( files != null ) && ( files.length > 0 ) && ( result == JFileChooser.APPROVE_OPTION ) ) {\r
2127             for( final File file : files ) {\r
2128                 if ( ( file != null ) && !file.isDirectory() ) {\r
2129                     if ( _mainpanel.getCurrentTreePanel() != null ) {\r
2130                         _mainpanel.getCurrentTreePanel().setWaitCursor();\r
2131                     }\r
2132                     else {\r
2133                         _mainpanel.setWaitCursor();\r
2134                     }\r
2135                     if ( ( _open_filechooser.getFileFilter() == MainFrameApplication.nhfilter )\r
2136                             || ( _open_filechooser.getFileFilter() == MainFrameApplication.nhxfilter ) ) {\r
2137                         try {\r
2138                             final NHXParser nhx = new NHXParser();\r
2139                             setSpecialOptionsForNhxParser( nhx );\r
2140                             phys = PhylogenyMethods.readPhylogenies( nhx, file );\r
2141                             nhx_or_nexus = true;\r
2142                         }\r
2143                         catch ( final Exception e ) {\r
2144                             exception = true;\r
2145                             exceptionOccuredDuringOpenFile( e );\r
2146                         }\r
2147                     }\r
2148                     else if ( _open_filechooser.getFileFilter() == MainFrameApplication.xmlfilter ) {\r
2149                         warnIfNotPhyloXmlValidation( getConfiguration() );\r
2150                         try {\r
2151                             final PhyloXmlParser xml_parser = createPhyloXmlParser();\r
2152                             phys = PhylogenyMethods.readPhylogenies( xml_parser, file );\r
2153                         }\r
2154                         catch ( final Exception e ) {\r
2155                             exception = true;\r
2156                             exceptionOccuredDuringOpenFile( e );\r
2157                         }\r
2158                     }\r
2159                     else if ( _open_filechooser.getFileFilter() == MainFrameApplication.tolfilter ) {\r
2160                         try {\r
2161                             phys = PhylogenyMethods.readPhylogenies( new TolParser(), file );\r
2162                         }\r
2163                         catch ( final Exception e ) {\r
2164                             exception = true;\r
2165                             exceptionOccuredDuringOpenFile( e );\r
2166                         }\r
2167                     }\r
2168                     else if ( _open_filechooser.getFileFilter() == MainFrameApplication.nexusfilter ) {\r
2169                         try {\r
2170                             final NexusPhylogeniesParser nex = new NexusPhylogeniesParser();\r
2171                             setSpecialOptionsForNexParser( nex );\r
2172                             phys = PhylogenyMethods.readPhylogenies( nex, file );\r
2173                             nhx_or_nexus = true;\r
2174                         }\r
2175                         catch ( final Exception e ) {\r
2176                             exception = true;\r
2177                             exceptionOccuredDuringOpenFile( e );\r
2178                         }\r
2179                     }\r
2180                     // "*.*":\r
2181                     else {\r
2182                         try {\r
2183                             final PhylogenyParser parser = ParserUtils\r
2184                                     .createParserDependingOnFileType( file, getConfiguration()\r
2185                                             .isValidatePhyloXmlAgainstSchema() );\r
2186                             if ( parser instanceof NexusPhylogeniesParser ) {\r
2187                                 final NexusPhylogeniesParser nex = ( NexusPhylogeniesParser ) parser;\r
2188                                 setSpecialOptionsForNexParser( nex );\r
2189                                 nhx_or_nexus = true;\r
2190                             }\r
2191                             else if ( parser instanceof NHXParser ) {\r
2192                                 final NHXParser nhx = ( NHXParser ) parser;\r
2193                                 setSpecialOptionsForNhxParser( nhx );\r
2194                                 nhx_or_nexus = true;\r
2195                             }\r
2196                             else if ( parser instanceof PhyloXmlParser ) {\r
2197                                 warnIfNotPhyloXmlValidation( getConfiguration() );\r
2198                             }\r
2199                             phys = PhylogenyMethods.readPhylogenies( parser, file );\r
2200                         }\r
2201                         catch ( final Exception e ) {\r
2202                             exception = true;\r
2203                             exceptionOccuredDuringOpenFile( e );\r
2204                         }\r
2205                     }\r
2206                     if ( _mainpanel.getCurrentTreePanel() != null ) {\r
2207                         _mainpanel.getCurrentTreePanel().setArrowCursor();\r
2208                     }\r
2209                     else {\r
2210                         _mainpanel.setArrowCursor();\r
2211                     }\r
2212                     if ( !exception && ( phys != null ) && ( phys.length > 0 ) ) {\r
2213                         boolean one_desc = false;\r
2214                         if ( nhx_or_nexus ) {\r
2215                             for( final Phylogeny phy : phys ) {\r
2216                                 if ( getOptions().isInternalNumberAreConfidenceForNhParsing() ) {\r
2217                                     PhylogenyMethods.transferInternalNodeNamesToConfidence( phy, "" );\r
2218                                 }\r
2219                                 if ( PhylogenyMethods.getMinimumDescendentsPerInternalNodes( phy ) == 1 ) {\r
2220                                     one_desc = true;\r
2221                                     break;\r
2222                                 }\r
2223                             }\r
2224                         }\r
2225                         AptxUtil.addPhylogeniesToTabs( phys,\r
2226                                                        file.getName(),\r
2227                                                        file.getAbsolutePath(),\r
2228                                                        getConfiguration(),\r
2229                                                        getMainPanel() );\r
2230                         _mainpanel.getControlPanel().showWhole();\r
2231                         if ( nhx_or_nexus && one_desc ) {\r
2232                             JOptionPane\r
2233                                     .showMessageDialog( this,\r
2234                                                         "One or more trees contain (a) node(s) with one descendant, "\r
2235                                                                 + ForesterUtil.LINE_SEPARATOR\r
2236                                                                 + "possibly indicating illegal parentheses within node names.",\r
2237                                                         "Warning: Possible Error in New Hampshire Formatted Data",\r
2238                                                         JOptionPane.WARNING_MESSAGE );\r
2239                         }\r
2240                     }\r
2241                 }\r
2242             }\r
2243         }\r
2244         activateSaveAllIfNeeded();\r
2245         System.gc();\r
2246     }\r
2247 \r
2248     private void readSpeciesTreeFromFile() {\r
2249         Phylogeny t = null;\r
2250         boolean exception = false;\r
2251         final File my_dir = getCurrentDir();\r
2252         _open_filechooser_for_species_tree.setSelectedFile( new File( "" ) );\r
2253         if ( my_dir != null ) {\r
2254             _open_filechooser_for_species_tree.setCurrentDirectory( my_dir );\r
2255         }\r
2256         final int result = _open_filechooser_for_species_tree.showOpenDialog( _contentpane );\r
2257         final File file = _open_filechooser_for_species_tree.getSelectedFile();\r
2258         if ( ( file != null ) && ( result == JFileChooser.APPROVE_OPTION ) ) {\r
2259             if ( _open_filechooser_for_species_tree.getFileFilter() == MainFrameApplication.xmlfilter ) {\r
2260                 try {\r
2261                     final Phylogeny[] trees = PhylogenyMethods.readPhylogenies( PhyloXmlParser\r
2262                             .createPhyloXmlParserXsdValidating(), file );\r
2263                     t = trees[ 0 ];\r
2264                 }\r
2265                 catch ( final Exception e ) {\r
2266                     exception = true;\r
2267                     exceptionOccuredDuringOpenFile( e );\r
2268                 }\r
2269             }\r
2270             else if ( _open_filechooser_for_species_tree.getFileFilter() == MainFrameApplication.tolfilter ) {\r
2271                 try {\r
2272                     final Phylogeny[] trees = PhylogenyMethods.readPhylogenies( new TolParser(), file );\r
2273                     t = trees[ 0 ];\r
2274                 }\r
2275                 catch ( final Exception e ) {\r
2276                     exception = true;\r
2277                     exceptionOccuredDuringOpenFile( e );\r
2278                 }\r
2279             }\r
2280             // "*.*":\r
2281             else {\r
2282                 try {\r
2283                     final Phylogeny[] trees = PhylogenyMethods.readPhylogenies( PhyloXmlParser\r
2284                             .createPhyloXmlParserXsdValidating(), file );\r
2285                     t = trees[ 0 ];\r
2286                 }\r
2287                 catch ( final Exception e ) {\r
2288                     exception = true;\r
2289                     exceptionOccuredDuringOpenFile( e );\r
2290                 }\r
2291             }\r
2292             if ( !exception && ( t != null ) && !t.isRooted() ) {\r
2293                 exception = true;\r
2294                 t = null;\r
2295                 JOptionPane.showMessageDialog( this,\r
2296                                                "Species tree is not rooted",\r
2297                                                "Species tree not loaded",\r
2298                                                JOptionPane.ERROR_MESSAGE );\r
2299             }\r
2300             if ( !exception && ( t != null ) ) {\r
2301                 final Set<Taxonomy> tax_set = new HashSet<Taxonomy>();\r
2302                 for( final PhylogenyNodeIterator it = t.iteratorExternalForward(); it.hasNext(); ) {\r
2303                     final PhylogenyNode node = it.next();\r
2304                     if ( !node.getNodeData().isHasTaxonomy() ) {\r
2305                         exception = true;\r
2306                         t = null;\r
2307                         JOptionPane\r
2308                                 .showMessageDialog( this,\r
2309                                                     "Species tree contains external node(s) without taxonomy information",\r
2310                                                     "Species tree not loaded",\r
2311                                                     JOptionPane.ERROR_MESSAGE );\r
2312                         break;\r
2313                     }\r
2314                     else {\r
2315                         if ( tax_set.contains( node.getNodeData().getTaxonomy() ) ) {\r
2316                             exception = true;\r
2317                             t = null;\r
2318                             JOptionPane.showMessageDialog( this,\r
2319                                                            "Taxonomy ["\r
2320                                                                    + node.getNodeData().getTaxonomy().asSimpleText()\r
2321                                                                    + "] is not unique in species tree",\r
2322                                                            "Species tree not loaded",\r
2323                                                            JOptionPane.ERROR_MESSAGE );\r
2324                             break;\r
2325                         }\r
2326                         else {\r
2327                             tax_set.add( node.getNodeData().getTaxonomy() );\r
2328                         }\r
2329                     }\r
2330                 }\r
2331             }\r
2332             if ( !exception && ( t != null ) ) {\r
2333                 setSpeciesTree( t );\r
2334                 JOptionPane.showMessageDialog( this,\r
2335                                                "Species tree successfully loaded",\r
2336                                                "Species tree loaded",\r
2337                                                JOptionPane.INFORMATION_MESSAGE );\r
2338             }\r
2339             _contentpane.repaint();\r
2340             System.gc();\r
2341         }\r
2342     }\r
2343 \r
2344     private void setArrowCursor() {\r
2345         try {\r
2346             _mainpanel.getCurrentTreePanel().setArrowCursor();\r
2347         }\r
2348         catch ( final Exception ex ) {\r
2349             // Do nothing.\r
2350         }\r
2351     }\r
2352 \r
2353     private void setCurrentDir( final File current_dir ) {\r
2354         _current_dir = current_dir;\r
2355     }\r
2356 \r
2357     private void setMinNotCollapseConfidenceValue( final double min_not_collapse ) {\r
2358         _min_not_collapse = min_not_collapse;\r
2359     }\r
2360 \r
2361     private void setPhylogeneticInferenceOptions( final PhylogeneticInferenceOptions phylogenetic_inference_options ) {\r
2362         _phylogenetic_inference_options = phylogenetic_inference_options;\r
2363     }\r
2364 \r
2365     private void setSpecialOptionsForNexParser( final NexusPhylogeniesParser nex ) {\r
2366         nex.setReplaceUnderscores( getOptions().isReplaceUnderscoresInNhParsing() );\r
2367         nex.setTaxonomyExtraction( getOptions().getTaxonomyExtraction() );\r
2368     }\r
2369 \r
2370     private void setSpecialOptionsForNhxParser( final NHXParser nhx ) {\r
2371         nhx.setReplaceUnderscores( getOptions().isReplaceUnderscoresInNhParsing() );\r
2372         nhx.setTaxonomyExtraction( getOptions().getTaxonomyExtraction() );\r
2373         nhx.setAllowErrorsInDistanceToParent( getOptions().isAllowErrorsInDistanceToParent() );\r
2374     }\r
2375 \r
2376     private void writeAllToFile() {\r
2377         if ( ( getMainPanel().getTabbedPane() == null ) || ( getMainPanel().getTabbedPane().getTabCount() < 1 ) ) {\r
2378             return;\r
2379         }\r
2380         final File my_dir = getCurrentDir();\r
2381         if ( my_dir != null ) {\r
2382             _save_filechooser.setCurrentDirectory( my_dir );\r
2383         }\r
2384         _save_filechooser.setSelectedFile( new File( "" ) );\r
2385         final int result = _save_filechooser.showSaveDialog( _contentpane );\r
2386         final File file = _save_filechooser.getSelectedFile();\r
2387         setCurrentDir( _save_filechooser.getCurrentDirectory() );\r
2388         if ( ( file != null ) && ( result == JFileChooser.APPROVE_OPTION ) ) {\r
2389             if ( file.exists() ) {\r
2390                 final int i = JOptionPane.showConfirmDialog( this,\r
2391                                                              file + " already exists. Overwrite?",\r
2392                                                              "Warning",\r
2393                                                              JOptionPane.OK_CANCEL_OPTION,\r
2394                                                              JOptionPane.WARNING_MESSAGE );\r
2395                 if ( i != JOptionPane.OK_OPTION ) {\r
2396                     return;\r
2397                 }\r
2398                 else {\r
2399                     try {\r
2400                         file.delete();\r
2401                     }\r
2402                     catch ( final Exception e ) {\r
2403                         JOptionPane.showMessageDialog( this,\r
2404                                                        "Failed to delete: " + file,\r
2405                                                        "Error",\r
2406                                                        JOptionPane.WARNING_MESSAGE );\r
2407                     }\r
2408                 }\r
2409             }\r
2410             final int count = getMainPanel().getTabbedPane().getTabCount();\r
2411             final List<Phylogeny> trees = new ArrayList<Phylogeny>();\r
2412             for( int i = 0; i < count; ++i ) {\r
2413                 final Phylogeny phy = getMainPanel().getPhylogeny( i );\r
2414                 if ( ForesterUtil.isEmpty( phy.getName() )\r
2415                         && !ForesterUtil.isEmpty( getMainPanel().getTabbedPane().getTitleAt( i ) ) ) {\r
2416                     phy.setName( getMainPanel().getTabbedPane().getTitleAt( i ) );\r
2417                 }\r
2418                 trees.add( phy );\r
2419                 getMainPanel().getTreePanels().get( i ).setEdited( false );\r
2420             }\r
2421             final PhylogenyWriter writer = new PhylogenyWriter();\r
2422             try {\r
2423                 writer.toPhyloXML( file, trees, 0, ForesterUtil.LINE_SEPARATOR );\r
2424             }\r
2425             catch ( final IOException e ) {\r
2426                 JOptionPane.showMessageDialog( this,\r
2427                                                "Failed to write to: " + file,\r
2428                                                "Error",\r
2429                                                JOptionPane.WARNING_MESSAGE );\r
2430             }\r
2431         }\r
2432     }\r
2433 \r
2434     private boolean writeAsNewHampshire( final Phylogeny t, boolean exception, final File file ) {\r
2435         try {\r
2436             final PhylogenyWriter writer = new PhylogenyWriter();\r
2437             writer.toNewHampshire( t, true, getOptions().getNhConversionSupportValueStyle(), file );\r
2438         }\r
2439         catch ( final Exception e ) {\r
2440             exception = true;\r
2441             exceptionOccuredDuringSaveAs( e );\r
2442         }\r
2443         return exception;\r
2444     }\r
2445 \r
2446     private boolean writeAsNexus( final Phylogeny t, boolean exception, final File file ) {\r
2447         try {\r
2448             final PhylogenyWriter writer = new PhylogenyWriter();\r
2449             writer.toNexus( file, t, getOptions().getNhConversionSupportValueStyle() );\r
2450         }\r
2451         catch ( final Exception e ) {\r
2452             exception = true;\r
2453             exceptionOccuredDuringSaveAs( e );\r
2454         }\r
2455         return exception;\r
2456     }\r
2457 \r
2458     private boolean writeAsPhyloXml( final Phylogeny t, boolean exception, final File file ) {\r
2459         try {\r
2460             final PhylogenyWriter writer = new PhylogenyWriter();\r
2461             writer.toPhyloXML( file, t, 0 );\r
2462         }\r
2463         catch ( final Exception e ) {\r
2464             exception = true;\r
2465             exceptionOccuredDuringSaveAs( e );\r
2466         }\r
2467         return exception;\r
2468     }\r
2469 \r
2470     private void writeToFile( final Phylogeny t ) {\r
2471         if ( t == null ) {\r
2472             return;\r
2473         }\r
2474         String initial_filename = null;\r
2475         if ( getMainPanel().getCurrentTreePanel().getTreeFile() != null ) {\r
2476             try {\r
2477                 initial_filename = getMainPanel().getCurrentTreePanel().getTreeFile().getCanonicalPath();\r
2478             }\r
2479             catch ( final IOException e ) {\r
2480                 initial_filename = null;\r
2481             }\r
2482         }\r
2483         if ( !ForesterUtil.isEmpty( initial_filename ) ) {\r
2484             _save_filechooser.setSelectedFile( new File( initial_filename ) );\r
2485         }\r
2486         else {\r
2487             _save_filechooser.setSelectedFile( new File( "" ) );\r
2488         }\r
2489         final File my_dir = getCurrentDir();\r
2490         if ( my_dir != null ) {\r
2491             _save_filechooser.setCurrentDirectory( my_dir );\r
2492         }\r
2493         final int result = _save_filechooser.showSaveDialog( _contentpane );\r
2494         final File file = _save_filechooser.getSelectedFile();\r
2495         setCurrentDir( _save_filechooser.getCurrentDirectory() );\r
2496         boolean exception = false;\r
2497         if ( ( file != null ) && ( result == JFileChooser.APPROVE_OPTION ) ) {\r
2498             if ( file.exists() ) {\r
2499                 final int i = JOptionPane.showConfirmDialog( this,\r
2500                                                              file + " already exists.\nOverwrite?",\r
2501                                                              "Overwrite?",\r
2502                                                              JOptionPane.OK_CANCEL_OPTION,\r
2503                                                              JOptionPane.QUESTION_MESSAGE );\r
2504                 if ( i != JOptionPane.OK_OPTION ) {\r
2505                     return;\r
2506                 }\r
2507                 else {\r
2508                     final File to = new File( file.getAbsoluteFile().toString() + Constants.BACKUP_FILE_SUFFIX );\r
2509                     try {\r
2510                         ForesterUtil.copyFile( file, to );\r
2511                     }\r
2512                     catch ( final Exception e ) {\r
2513                         JOptionPane.showMessageDialog( this,\r
2514                                                        "Failed to create backup copy " + to,\r
2515                                                        "Failed to Create Backup Copy",\r
2516                                                        JOptionPane.WARNING_MESSAGE );\r
2517                     }\r
2518                     try {\r
2519                         file.delete();\r
2520                     }\r
2521                     catch ( final Exception e ) {\r
2522                         JOptionPane.showMessageDialog( this,\r
2523                                                        "Failed to delete: " + file,\r
2524                                                        "Failed to Delete",\r
2525                                                        JOptionPane.WARNING_MESSAGE );\r
2526                     }\r
2527                 }\r
2528             }\r
2529             if ( _save_filechooser.getFileFilter() == MainFrameApplication.nhfilter ) {\r
2530                 exception = writeAsNewHampshire( t, exception, file );\r
2531             }\r
2532             else if ( _save_filechooser.getFileFilter() == MainFrameApplication.xmlfilter ) {\r
2533                 exception = writeAsPhyloXml( t, exception, file );\r
2534             }\r
2535             else if ( _save_filechooser.getFileFilter() == MainFrameApplication.nexusfilter ) {\r
2536                 exception = writeAsNexus( t, exception, file );\r
2537             }\r
2538             // "*.*":\r
2539             else {\r
2540                 final String file_name = file.getName().trim().toLowerCase();\r
2541                 if ( file_name.endsWith( ".nh" ) || file_name.endsWith( ".newick" ) || file_name.endsWith( ".phy" )\r
2542                         || file_name.endsWith( ".tree" ) ) {\r
2543                     exception = writeAsNewHampshire( t, exception, file );\r
2544                 }\r
2545                 else if ( file_name.endsWith( ".nex" ) || file_name.endsWith( ".nexus" ) ) {\r
2546                     exception = writeAsNexus( t, exception, file );\r
2547                 }\r
2548                 // XML is default:\r
2549                 else {\r
2550                     exception = writeAsPhyloXml( t, exception, file );\r
2551                 }\r
2552             }\r
2553             if ( !exception ) {\r
2554                 getMainPanel().setTitleOfSelectedTab( file.getName() );\r
2555                 getMainPanel().getCurrentTreePanel().setTreeFile( file );\r
2556                 getMainPanel().getCurrentTreePanel().setEdited( false );\r
2557             }\r
2558         }\r
2559     }\r
2560 \r
2561     private void writeToGraphicsFile( final Phylogeny t, final GraphicsExportType type ) {\r
2562         if ( ( t == null ) || t.isEmpty() ) {\r
2563             return;\r
2564         }\r
2565         String initial_filename = "";\r
2566         if ( getMainPanel().getCurrentTreePanel().getTreeFile() != null ) {\r
2567             initial_filename = getMainPanel().getCurrentTreePanel().getTreeFile().toString();\r
2568         }\r
2569         if ( initial_filename.indexOf( '.' ) > 0 ) {\r
2570             initial_filename = initial_filename.substring( 0, initial_filename.lastIndexOf( '.' ) );\r
2571         }\r
2572         initial_filename = initial_filename + "." + type;\r
2573         _writetographics_filechooser.setSelectedFile( new File( initial_filename ) );\r
2574         final File my_dir = getCurrentDir();\r
2575         if ( my_dir != null ) {\r
2576             _writetographics_filechooser.setCurrentDirectory( my_dir );\r
2577         }\r
2578         final int result = _writetographics_filechooser.showSaveDialog( _contentpane );\r
2579         File file = _writetographics_filechooser.getSelectedFile();\r
2580         setCurrentDir( _writetographics_filechooser.getCurrentDirectory() );\r
2581         if ( ( file != null ) && ( result == JFileChooser.APPROVE_OPTION ) ) {\r
2582             if ( !file.toString().toLowerCase().endsWith( type.toString() ) ) {\r
2583                 file = new File( file.toString() + "." + type );\r
2584             }\r
2585             if ( file.exists() ) {\r
2586                 final int i = JOptionPane.showConfirmDialog( this,\r
2587                                                              file + " already exists. Overwrite?",\r
2588                                                              "Warning",\r
2589                                                              JOptionPane.OK_CANCEL_OPTION,\r
2590                                                              JOptionPane.WARNING_MESSAGE );\r
2591                 if ( i != JOptionPane.OK_OPTION ) {\r
2592                     return;\r
2593                 }\r
2594                 else {\r
2595                     try {\r
2596                         file.delete();\r
2597                     }\r
2598                     catch ( final Exception e ) {\r
2599                         JOptionPane.showMessageDialog( this,\r
2600                                                        "Failed to delete: " + file,\r
2601                                                        "Error",\r
2602                                                        JOptionPane.WARNING_MESSAGE );\r
2603                     }\r
2604                 }\r
2605             }\r
2606             writePhylogenyToGraphicsFile( file.toString(), type );\r
2607         }\r
2608     }\r
2609 \r
2610     private void writeToPdf( final Phylogeny t ) {\r
2611         if ( ( t == null ) || t.isEmpty() ) {\r
2612             return;\r
2613         }\r
2614         String initial_filename = "";\r
2615         if ( getMainPanel().getCurrentTreePanel().getTreeFile() != null ) {\r
2616             initial_filename = getMainPanel().getCurrentTreePanel().getTreeFile().toString();\r
2617         }\r
2618         if ( initial_filename.indexOf( '.' ) > 0 ) {\r
2619             initial_filename = initial_filename.substring( 0, initial_filename.lastIndexOf( '.' ) );\r
2620         }\r
2621         initial_filename = initial_filename + ".pdf";\r
2622         _writetopdf_filechooser.setSelectedFile( new File( initial_filename ) );\r
2623         final File my_dir = getCurrentDir();\r
2624         if ( my_dir != null ) {\r
2625             _writetopdf_filechooser.setCurrentDirectory( my_dir );\r
2626         }\r
2627         final int result = _writetopdf_filechooser.showSaveDialog( _contentpane );\r
2628         File file = _writetopdf_filechooser.getSelectedFile();\r
2629         setCurrentDir( _writetopdf_filechooser.getCurrentDirectory() );\r
2630         if ( ( file != null ) && ( result == JFileChooser.APPROVE_OPTION ) ) {\r
2631             if ( !file.toString().toLowerCase().endsWith( ".pdf" ) ) {\r
2632                 file = new File( file.toString() + ".pdf" );\r
2633             }\r
2634             if ( file.exists() ) {\r
2635                 final int i = JOptionPane.showConfirmDialog( this,\r
2636                                                              file + " already exists. Overwrite?",\r
2637                                                              "WARNING",\r
2638                                                              JOptionPane.OK_CANCEL_OPTION,\r
2639                                                              JOptionPane.WARNING_MESSAGE );\r
2640                 if ( i != JOptionPane.OK_OPTION ) {\r
2641                     return;\r
2642                 }\r
2643             }\r
2644             printPhylogenyToPdf( file.toString() );\r
2645         }\r
2646     }\r
2647 \r
2648     public static MainFrameApplication createInstance( final Phylogeny[] phys, final Configuration config ) {\r
2649         return new MainFrameApplication( phys, config );\r
2650     }\r
2651 \r
2652     public static MainFrame createInstance( final Phylogeny[] phys,\r
2653                                             final Configuration config,\r
2654                                             final String title,\r
2655                                             final File current_dir ) {\r
2656         return new MainFrameApplication( phys, config, title, current_dir );\r
2657     }\r
2658 \r
2659     static MainFrame createInstance( final Phylogeny[] phys, final Configuration config, final String title ) {\r
2660         return new MainFrameApplication( phys, config, title );\r
2661     }\r
2662 \r
2663     static MainFrame createInstance( final Phylogeny[] phys, final String config_file_name, final String title ) {\r
2664         return new MainFrameApplication( phys, config_file_name, title );\r
2665     }\r
2666 \r
2667     static void setTextForGraphicsSizeChooserMenuItem( final JMenuItem mi, final Options o ) {\r
2668         mi.setText( "Enter Default Size for Graphics Export... (current: " + o.getPrintSizeX() + ", "\r
2669                 + o.getPrintSizeY() + ")" );\r
2670     }\r
2671 \r
2672     static void setTextForPdfLineWidthChooserMenuItem( final JMenuItem mi, final Options o ) {\r
2673         mi.setText( "Enter Default Line Width for PDF Export... (current: " + o.getPrintLineWidth() + ")" );\r
2674     }\r
2675 \r
2676     static void warnIfNotPhyloXmlValidation( final Configuration c ) {\r
2677         if ( !c.isValidatePhyloXmlAgainstSchema() ) {\r
2678             JOptionPane\r
2679                     .showMessageDialog( null,\r
2680                                         ForesterUtil\r
2681                                                 .wordWrap( "phyloXML XSD-based validation is turned off [enable with line 'validate_against_phyloxml_xsd_schem: true' in configuration file]",\r
2682                                                            80 ),\r
2683                                         "Warning",\r
2684                                         JOptionPane.WARNING_MESSAGE );\r
2685         }\r
2686     }\r
2687 } // MainFrameApplication.\r
2688 \r
2689 class DefaultFilter extends FileFilter {\r
2690 \r
2691     @Override\r
2692     public boolean accept( final File f ) {\r
2693         final String file_name = f.getName().trim().toLowerCase();\r
2694         return file_name.endsWith( ".nh" ) || file_name.endsWith( ".newick" ) || file_name.endsWith( ".phy" )\r
2695                 || file_name.endsWith( ".nwk" ) || file_name.endsWith( ".phb" ) || file_name.endsWith( ".ph" )\r
2696                 || file_name.endsWith( ".tr" ) || file_name.endsWith( ".dnd" ) || file_name.endsWith( ".tree" )\r
2697                 || file_name.endsWith( ".nhx" ) || file_name.endsWith( ".xml" ) || file_name.endsWith( ".phyloxml" )\r
2698                 || file_name.endsWith( "phylo.xml" ) || file_name.endsWith( ".pxml" ) || file_name.endsWith( ".nexus" )\r
2699                 || file_name.endsWith( ".nx" ) || file_name.endsWith( ".nex" ) || file_name.endsWith( ".tre" )\r
2700                 || file_name.endsWith( ".zip" ) || file_name.endsWith( ".tol" ) || file_name.endsWith( ".tolxml" )\r
2701                 || file_name.endsWith( ".con" ) || f.isDirectory();\r
2702     }\r
2703 \r
2704     @Override\r
2705     public String getDescription() {\r
2706         return "All supported files (*.xml, *.phyloxml, *phylo.xml, *.nhx, *.nh, *.newick, *.nex, *.nexus, *.phy, *.tre, *.tree, *.tol, ...)";\r
2707     }\r
2708 }\r
2709 \r
2710 class GraphicsFileFilter extends FileFilter {\r
2711 \r
2712     @Override\r
2713     public boolean accept( final File f ) {\r
2714         final String file_name = f.getName().trim().toLowerCase();\r
2715         return file_name.endsWith( ".jpg" ) || file_name.endsWith( ".jpeg" ) || file_name.endsWith( ".png" )\r
2716                 || file_name.endsWith( ".gif" ) || file_name.endsWith( ".bmp" ) || f.isDirectory();\r
2717     }\r
2718 \r
2719     @Override\r
2720     public String getDescription() {\r
2721         return "Image files (*.jpg, *.jpeg, *.png, *.gif, *.bmp)";\r
2722     }\r
2723 }\r
2724 \r
2725 class MsaFileFilter extends FileFilter {\r
2726 \r
2727     @Override\r
2728     public boolean accept( final File f ) {\r
2729         final String file_name = f.getName().trim().toLowerCase();\r
2730         return file_name.endsWith( ".msa" ) || file_name.endsWith( ".aln" ) || file_name.endsWith( ".fasta" )\r
2731                 || file_name.endsWith( ".fas" ) || file_name.endsWith( ".fa" ) || f.isDirectory();\r
2732     }\r
2733 \r
2734     @Override\r
2735     public String getDescription() {\r
2736         return "Multiple sequence alignment files (*.msa, *.aln, *.fasta, *.fa, *.fas)";\r
2737     }\r
2738 }\r
2739 \r
2740 class NexusFilter extends FileFilter {\r
2741 \r
2742     @Override\r
2743     public boolean accept( final File f ) {\r
2744         final String file_name = f.getName().trim().toLowerCase();\r
2745         return file_name.endsWith( ".nex" ) || file_name.endsWith( ".nexus" ) || file_name.endsWith( ".nx" )\r
2746                 || file_name.endsWith( ".tre" ) || f.isDirectory();\r
2747     }\r
2748 \r
2749     @Override\r
2750     public String getDescription() {\r
2751         return "Nexus files (*.nex, *.nexus, *.nx, *.tre)";\r
2752     }\r
2753 } // NexusFilter\r
2754 \r
2755 class NHFilter extends FileFilter {\r
2756 \r
2757     @Override\r
2758     public boolean accept( final File f ) {\r
2759         final String file_name = f.getName().trim().toLowerCase();\r
2760         return file_name.endsWith( ".nh" ) || file_name.endsWith( ".newick" ) || file_name.endsWith( ".phy" )\r
2761                 || file_name.endsWith( ".tr" ) || file_name.endsWith( ".tree" ) || file_name.endsWith( ".dnd" )\r
2762                 || file_name.endsWith( ".ph" ) || file_name.endsWith( ".phb" ) || file_name.endsWith( ".nwk" )\r
2763                 || f.isDirectory();\r
2764     }\r
2765 \r
2766     @Override\r
2767     public String getDescription() {\r
2768         return "New Hampshire - Newick files (*.nh, *.newick, *.phy, *.tree, *.dnd, *.tr, *.ph, *.phb, *.nwk)";\r
2769     }\r
2770 } // NHFilter\r
2771 \r
2772 class NHXFilter extends FileFilter {\r
2773 \r
2774     @Override\r
2775     public boolean accept( final File f ) {\r
2776         final String file_name = f.getName().trim().toLowerCase();\r
2777         return file_name.endsWith( ".nhx" ) || f.isDirectory();\r
2778     }\r
2779 \r
2780     @Override\r
2781     public String getDescription() {\r
2782         return "NHX files (*.nhx) [deprecated]";\r
2783     }\r
2784 }\r
2785 \r
2786 class PdfFilter extends FileFilter {\r
2787 \r
2788     @Override\r
2789     public boolean accept( final File f ) {\r
2790         return f.getName().trim().toLowerCase().endsWith( ".pdf" ) || f.isDirectory();\r
2791     }\r
2792 \r
2793     @Override\r
2794     public String getDescription() {\r
2795         return "PDF files (*.pdf)";\r
2796     }\r
2797 } // PdfFilter\r
2798 \r
2799 class SequencesFileFilter extends FileFilter {\r
2800 \r
2801     @Override\r
2802     public boolean accept( final File f ) {\r
2803         final String file_name = f.getName().trim().toLowerCase();\r
2804         return file_name.endsWith( ".fasta" ) || file_name.endsWith( ".fa" ) || file_name.endsWith( ".fas" )\r
2805                 || file_name.endsWith( ".seqs" ) || f.isDirectory();\r
2806     }\r
2807 \r
2808     @Override\r
2809     public String getDescription() {\r
2810         return "Sequences files (*.fasta, *.fa, *.fas, *.seqs )";\r
2811     }\r
2812 }\r
2813 \r
2814 class TolFilter extends FileFilter {\r
2815 \r
2816     @Override\r
2817     public boolean accept( final File f ) {\r
2818         final String file_name = f.getName().trim().toLowerCase();\r
2819         return ( file_name.endsWith( ".tol" ) || file_name.endsWith( ".tolxml" ) || file_name.endsWith( ".zip" ) || f\r
2820                 .isDirectory() ) && ( !file_name.endsWith( ".xml.zip" ) );\r
2821     }\r
2822 \r
2823     @Override\r
2824     public String getDescription() {\r
2825         return "Tree of Life files (*.tol, *.tolxml)";\r
2826     }\r
2827 } // TolFilter\r
2828 \r
2829 class XMLFilter extends FileFilter {\r
2830 \r
2831     @Override\r
2832     public boolean accept( final File f ) {\r
2833         final String file_name = f.getName().trim().toLowerCase();\r
2834         return file_name.endsWith( ".xml" ) || file_name.endsWith( ".phyloxml" ) || file_name.endsWith( "phylo.xml" )\r
2835                 || file_name.endsWith( ".pxml" ) || file_name.endsWith( ".zip" ) || f.isDirectory();\r
2836     }\r
2837 \r
2838     @Override\r
2839     public String getDescription() {\r
2840         return "phyloXML files (*.xml, *.phyloxml, *phylo.xml, *.pxml, *.zip)";\r
2841     }\r
2842 } // XMLFilter\r