a06adaf101e87512c67c2d5686761900f234ec91
[jalview.git] / forester / java / src / org / forester / archaeopteryx / MainFrame.java
1 // $Id:
2 // FORESTER -- software libraries and applications
3 // for evolutionary biology research and applications.
4 //
5 // Copyright (C) 2008-2010 Christian M. Zmasek
6 // All rights reserved
7 //
8 // This library is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU Lesser General Public
10 // License as published by the Free Software Foundation; either
11 // version 2.1 of the License, or (at your option) any later version.
12 //
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // Lesser General Public License for more details.
17 //
18 // You should have received a copy of the GNU Lesser General Public
19 // License along with this library; if not, write to the Free Software
20 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
21 //
22 // Contact: phylosoft @ gmail . com
23 // WWW: https://sites.google.com/site/cmzmasek/home/software/forester
24
25 package org.forester.archaeopteryx;
26
27 import java.awt.Color;
28 import java.awt.Component;
29 import java.awt.Container;
30 import java.awt.Font;
31 import java.awt.event.ActionEvent;
32 import java.awt.event.ActionListener;
33 import java.io.File;
34 import java.io.IOException;
35 import java.util.ArrayList;
36 import java.util.LinkedList;
37 import java.util.List;
38 import java.util.Locale;
39 import java.util.Map;
40 import java.util.NoSuchElementException;
41
42 import javax.swing.Box;
43 import javax.swing.JApplet;
44 import javax.swing.JCheckBoxMenuItem;
45 import javax.swing.JFileChooser;
46 import javax.swing.JFrame;
47 import javax.swing.JLabel;
48 import javax.swing.JMenu;
49 import javax.swing.JMenuBar;
50 import javax.swing.JMenuItem;
51 import javax.swing.JOptionPane;
52 import javax.swing.JPanel;
53 import javax.swing.JRadioButtonMenuItem;
54 import javax.swing.JTextField;
55 import javax.swing.SwingUtilities;
56 import javax.swing.filechooser.FileFilter;
57
58 import org.forester.archaeopteryx.AptxUtil.GraphicsExportType;
59 import org.forester.archaeopteryx.Options.CLADOGRAM_TYPE;
60 import org.forester.archaeopteryx.Options.NODE_LABEL_DIRECTION;
61 import org.forester.archaeopteryx.Options.PHYLOGENY_GRAPHICS_TYPE;
62 import org.forester.archaeopteryx.tools.AncestralTaxonomyInferrer;
63 import org.forester.archaeopteryx.tools.InferenceManager;
64 import org.forester.archaeopteryx.tools.ProcessPool;
65 import org.forester.archaeopteryx.tools.ProcessRunning;
66 import org.forester.io.parsers.nhx.NHXParser.TAXONOMY_EXTRACTION;
67 import org.forester.io.writers.PhylogenyWriter;
68 import org.forester.phylogeny.Phylogeny;
69 import org.forester.phylogeny.PhylogenyMethods;
70 import org.forester.phylogeny.PhylogenyMethods.DESCENDANT_SORT_PRIORITY;
71 import org.forester.phylogeny.PhylogenyNode;
72 import org.forester.phylogeny.PhylogenyNode.NH_CONVERSION_SUPPORT_VALUE_STYLE;
73 import org.forester.phylogeny.data.Annotation;
74 import org.forester.phylogeny.data.NodeDataField;
75 import org.forester.phylogeny.data.NodeVisualData.NodeFill;
76 import org.forester.phylogeny.data.NodeVisualData.NodeShape;
77 import org.forester.phylogeny.iterators.PhylogenyNodeIterator;
78 import org.forester.sdi.GSDI;
79 import org.forester.sdi.GSDIR;
80 import org.forester.sdi.SDIException;
81 import org.forester.util.ForesterConstants;
82 import org.forester.util.ForesterUtil;
83 import org.forester.util.WindowsUtils;
84
85 public abstract class MainFrame extends JFrame implements ActionListener {
86
87     final static NHFilter            nhfilter                                = new NHFilter();
88     final static NHXFilter           nhxfilter                               = new NHXFilter();
89     final static XMLFilter           xmlfilter                               = new XMLFilter();
90     final static TolFilter           tolfilter                               = new TolFilter();
91     final static NexusFilter         nexusfilter                             = new NexusFilter();
92     final static PdfFilter           pdffilter                               = new PdfFilter();
93     final static GraphicsFileFilter  graphicsfilefilter                      = new GraphicsFileFilter();
94     final static MsaFileFilter       msafilter                               = new MsaFileFilter();
95     final static SequencesFileFilter seqsfilter                              = new SequencesFileFilter();
96     final static DefaultFilter       defaultfilter                           = new DefaultFilter();
97     static final String              USE_MOUSEWHEEL_SHIFT_TO_ROTATE          = "rotate with mousewheel + Shift (or A and S), D toggles between horizontal and radial labels";
98     static final String              PHYLOXML_REF_TOOL_TIP                   = AptxConstants.PHYLOXML_REFERENCE;                                                                                                                                                //TODO //FIXME
99     static final String              APTX_REF_TOOL_TIP                       = AptxConstants.APTX_REFERENCE;
100     private static final long        serialVersionUID                        = 3655000897845508358L;
101     final static Font                menu_font                               = new Font( Configuration.getDefaultFontFamilyName(),
102                                                                                          Font.PLAIN,
103                                                                                          10 );
104     static final String              TYPE_MENU_HEADER                        = "Type";
105     static final String              RECTANGULAR_TYPE_CBMI_LABEL             = "Rectangular";
106     static final String              EURO_TYPE_CBMI_LABEL                    = "Euro Type";
107     static final String              CURVED_TYPE_CBMI_LABEL                  = "Curved";
108     static final String              TRIANGULAR_TYPE_CBMI_LABEL              = "Triangular";
109     static final String              CONVEX_TYPE_CBMI_LABEL                  = "Convex";
110     static final String              ROUNDED_TYPE_CBMI_LABEL                 = "Rounded";
111     static final String              UNROOTED_TYPE_CBMI_LABEL                = "Unrooted (alpha)";                                                                                                                                                          //TODO
112     static final String              CIRCULAR_TYPE_CBMI_LABEL                = "Circular (alpha)";                                                                                                                                                          //TODO
113     static final String              OPTIONS_HEADER                          = "Options";
114     static final String              SEARCH_SUBHEADER                        = "Search:";
115     static final String              DISPLAY_SUBHEADER                       = "Display:";
116     static final String              SEARCH_TERMS_ONLY_LABEL                 = "Match Complete Terms Only";
117     static final String              SEARCH_REGEX_LABEL                      = "Search with Regular Expressions";
118     static final String              SEARCH_CASE_SENSITIVE_LABEL             = "Case Sensitive";
119     static final String              INVERSE_SEARCH_RESULT_LABEL             = "Negate Result";
120     static final String              COLOR_BY_TAXONOMIC_GROUP                = "Colorize by Taxonomic Group";
121     static final String              DISPLAY_SCALE_LABEL                     = "Scale";
122     static final String              NON_LINED_UP_CLADOGRAMS_LABEL           = "Non-Lined Up Cladogram";
123     static final String              LABEL_DIRECTION_LABEL                   = "Radial Labels";
124     static final String              LABEL_DIRECTION_TIP                     = "To use radial node labels in radial and unrooted display types";
125     static final String              SEARCH_WITH_REGEX_TIP                   = "To search using regular expressions (~Java/Perl syntax). For example, use \"^B.+\\d{2,}$\" to search for everything starting with a B and ending with at least two digits.";
126     static final String              SCREEN_ANTIALIAS_LABEL                  = "Antialias";
127     static final String              COLOR_LABELS_LABEL                      = "Colorize Labels Same as Parent Branch";
128     static final String              BG_GRAD_LABEL                           = "Background Color Gradient";
129     static final String              DISPLAY_NODE_BOXES_LABEL_EXT            = "Shapes for External Nodes";
130     static final String              DISPLAY_NODE_BOXES_LABEL_INT            = "Shapes for Internal Nodes";
131     static final String              DISPLAY_NODE_BOXES_LABEL_MARKED         = "Shapes for Nodes with Visual Data";
132     static final String              SHOW_OVERVIEW_LABEL                     = "Overview";
133     static final String              FONT_SIZE_MENU_LABEL                    = "Font Size";
134     static final String              NONUNIFORM_CLADOGRAMS_LABEL             = "Lined Up Cladogram";
135     static final String              SHOW_DOMAIN_LABELS_LABEL                = "Domain Labels";
136     static final String              SHOW_ANN_REF_SOURCE_LABEL               = "Seq Annotation Ref Sources";
137     static final String              COLOR_LABELS_TIP                        = "To use parent branch colors for node labels as well, need to turn off taxonomy dependent colorization and turn on branch colorization for this to become apparent";
138     static final String              ABBREV_SN_LABEL                         = "Abbreviate Scientific Taxonomic Names";
139     static final String              TAXONOMY_COLORIZE_NODE_SHAPES_LABEL     = "Colorize Node Shapes According to Taxonomy";
140     static final String              CYCLE_NODE_SHAPE_LABEL                  = "Cycle Node Shapes";
141     static final String              CYCLE_NODE_FILL_LABEL                   = "Cycle Node Fill Type";
142     static final String              CHOOSE_NODE_SIZE_LABEL                  = "Choose Node Shape Size";
143     static final String              SHOW_CONF_STDDEV_LABEL                  = "Confidence Standard Deviations";
144     static final String              USE_BRACKETS_FOR_CONF_IN_NH_LABEL       = "Use Brackets for Confidence Values";
145     static final String              USE_INTERNAL_NAMES_FOR_CONF_IN_NH_LABEL = "Use Internal Node Names for Confidence Values";
146     static final String              SHOW_BASIC_TREE_INFORMATION_LABEL       = "Basic Tree Information";
147     static final String              RIGHT_LINE_UP_DOMAINS                   = "Right-align Domain Architectures";
148     static final String              LINE_UP_RENDERABLE_DATA                 = "Line Up Diagrams (such as Domain Architectures)";
149     static final String              INFER_ANCESTOR_TAXONOMIES               = "Infer Ancestor Taxonomies";
150     static final String              OBTAIN_DETAILED_TAXONOMIC_INFORMATION   = "Obtain Detailed Taxonomic Information";
151     JMenuBar                         _jmenubar;
152     JMenu                            _file_jmenu;
153     JMenu                            _tools_menu;
154     JMenu                            _view_jmenu;
155     JMenu                            _options_jmenu;
156     JMenu                            _font_size_menu;
157     JMenu                            _help_jmenu;
158     JMenuItem[]                      _load_phylogeny_from_webservice_menu_items;
159     // Analysis menu
160     JMenu                            _analysis_menu;
161     JMenuItem                        _load_species_tree_item;
162     JMenuItem                        _gsdi_item;
163     JMenuItem                        _gsdir_item;
164     JMenuItem                        _lineage_inference;
165     // file menu:
166     JMenuItem                        _open_item;
167     JMenuItem                        _open_url_item;
168     JMenuItem                        _save_item;
169     JMenuItem                        _save_all_item;
170     JMenuItem                        _close_item;
171     JMenuItem                        _exit_item;
172     JMenuItem                        _new_item;
173     JMenuItem                        _print_item;
174     JMenuItem                        _write_to_pdf_item;
175     JMenuItem                        _write_to_jpg_item;
176     JMenuItem                        _write_to_gif_item;
177     JMenuItem                        _write_to_tif_item;
178     JMenuItem                        _write_to_png_item;
179     JMenuItem                        _write_to_bmp_item;
180     // tools menu:
181     JMenuItem                        _midpoint_root_item;
182     JMenuItem                        _taxcolor_item;
183     JMenuItem                        _confcolor_item;
184     JMenuItem                        _color_rank_jmi;
185     JMenuItem                        _collapse_species_specific_subtrees;
186     
187     JMenuItem                        _obtain_detailed_taxonomic_information_jmi;
188     JMenuItem                        _obtain_detailed_taxonomic_information_deleting_jmi;
189     JMenuItem                        _obtain_seq_information_jmi;
190     JMenuItem                        _move_node_names_to_tax_sn_jmi;
191     JMenuItem                        _move_node_names_to_seq_names_jmi;
192     JMenuItem                        _extract_tax_code_from_node_names_jmi;
193     JMenuItem                        _annotate_item;
194     JMenuItem                        _remove_branch_color_item;
195     JMenuItem                        _remove_visual_styles_item;
196     JMenuItem                        _delete_selected_nodes_item;
197     JMenuItem                        _delete_not_selected_nodes_item;
198     // font size menu:
199     JMenuItem                        _super_tiny_fonts_item;
200     JMenuItem                        _tiny_fonts_item;
201     JMenuItem                        _small_fonts_item;
202     JMenuItem                        _medium_fonts_item;
203     JMenuItem                        _large_fonts_item;
204     // options menu:
205     // _  screen and print
206     JMenuItem                        _choose_font_mi;
207     JMenuItem                        _switch_colors_mi;
208     JCheckBoxMenuItem                _label_direction_cbmi;
209     // _  screen display
210     JCheckBoxMenuItem                _screen_antialias_cbmi;
211     JCheckBoxMenuItem                _background_gradient_cbmi;
212     JRadioButtonMenuItem             _non_lined_up_cladograms_rbmi;
213     JRadioButtonMenuItem             _ext_node_dependent_cladogram_rbmi;
214     JCheckBoxMenuItem                _color_by_taxonomic_group_cbmi;
215     JCheckBoxMenuItem                _show_scale_cbmi;                                                                                                                                                                                                      //TODO fix me
216     JCheckBoxMenuItem                _show_overview_cbmi;
217     JCheckBoxMenuItem                _show_domain_labels;
218     JCheckBoxMenuItem                _show_annotation_ref_source;
219     JCheckBoxMenuItem                _abbreviate_scientific_names;
220     JCheckBoxMenuItem                _color_labels_same_as_parent_branch;
221     JMenuItem                        _overview_placment_mi;
222     JMenuItem                        _choose_minimal_confidence_mi;
223     JCheckBoxMenuItem                _show_default_node_shapes_internal_cbmi;
224     JCheckBoxMenuItem                _show_default_node_shapes_external_cbmi;
225     JCheckBoxMenuItem                _show_default_node_shapes_for_marked_cbmi;
226     JMenuItem                        _cycle_node_shape_mi;
227     JMenuItem                        _cycle_node_fill_mi;
228     JMenuItem                        _choose_node_size_mi;
229     JMenuItem                        _cycle_data_return;
230     JCheckBoxMenuItem                _show_confidence_stddev_cbmi;
231     JCheckBoxMenuItem                _right_line_up_domains_cbmi;
232     JCheckBoxMenuItem                _line_up_renderable_data_cbmi;
233     JCheckBoxMenuItem                _collapsed_with_average_height_cbmi;
234     JCheckBoxMenuItem                _show_abbreviated_labels_for_collapsed_nodes_cbmi;
235     // _  print
236     JCheckBoxMenuItem                _graphics_export_visible_only_cbmi;
237     JCheckBoxMenuItem                _antialias_print_cbmi;
238     JCheckBoxMenuItem                _print_black_and_white_cbmi;
239     //JMenuItem                        _print_size_mi;
240     JMenuItem                        _choose_pdf_width_mi;
241     // _  parsing
242     JCheckBoxMenuItem                _internal_number_are_confidence_for_nh_parsing_cbmi;
243     JRadioButtonMenuItem             _extract_taxonomy_no_rbmi;
244     JRadioButtonMenuItem             _extract_taxonomy_agressive_rbmi;
245     JRadioButtonMenuItem             _extract_taxonomy_pfam_strict_rbmi;
246     JRadioButtonMenuItem             _extract_taxonomy_pfam_relaxed_rbmi;
247     JCheckBoxMenuItem                _replace_underscores_cbmi;
248     JCheckBoxMenuItem                _allow_errors_in_distance_to_parent_cbmi;
249     JCheckBoxMenuItem                _use_brackets_for_conf_in_nh_export_cbmi;
250     JCheckBoxMenuItem                _use_internal_names_for_conf_in_nh_export_cbmi;
251     JCheckBoxMenuItem                _parse_beast_style_extended_nexus_tags_cbmi;
252     // _  search
253     JCheckBoxMenuItem                _search_case_senstive_cbmi;
254     JCheckBoxMenuItem                _search_whole_words_only_cbmi;
255     JCheckBoxMenuItem                _inverse_search_result_cbmi;
256     JCheckBoxMenuItem                _search_with_regex_cbmi;
257     JCheckBoxMenuItem                _color_all_found_nodes_when_coloring_subtree_cbmi;
258     // type menu:
259     JMenu                            _type_menu;
260     JCheckBoxMenuItem                _rectangular_type_cbmi;
261     JCheckBoxMenuItem                _triangular_type_cbmi;
262     JCheckBoxMenuItem                _curved_type_cbmi;
263     JCheckBoxMenuItem                _convex_type_cbmi;
264     JCheckBoxMenuItem                _euro_type_cbmi;
265     JCheckBoxMenuItem                _rounded_type_cbmi;
266     JCheckBoxMenuItem                _unrooted_type_cbmi;
267     JCheckBoxMenuItem                _circular_type_cbmi;
268     // view as text menu:
269     JMenuItem                        _view_as_NH_item;
270     JMenuItem                        _view_as_XML_item;
271     JMenuItem                        _view_as_nexus_item;
272     JMenuItem                        _display_basic_information_item;
273     // help menu:
274     JMenuItem                        _about_item;
275     JMenuItem                        _help_item;
276     JMenuItem                        _website_item;
277     JMenuItem                        _mailing_list_item;
278     JMenuItem                        _phyloxml_website_item;
279     JMenuItem                        _phyloxml_ref_item;
280     JMenuItem                        _aptx_ref_item;
281     //
282     File                             _current_dir;
283     JFileChooser                     _writetopdf_filechooser;
284     JFileChooser                     _save_filechooser;
285     JFileChooser                     _writetographics_filechooser;
286     // process menu:
287     JMenu                            _process_menu;
288     MainPanel                        _mainpanel;
289     Container                        _contentpane;
290     final LinkedList<TextFrame>      _textframes                             = new LinkedList<TextFrame>();                                                                                                                                                  ;
291     Configuration                    _configuration;
292     Options                          _options;
293     private Phylogeny                _species_tree;
294     InferenceManager                 _inference_manager;
295     final ProcessPool                _process_pool;
296     private String                   _previous_node_annotation_ref;
297
298     MainFrame() {
299         _process_pool = ProcessPool.createInstance();
300         _writetopdf_filechooser = new JFileChooser();
301         _writetopdf_filechooser.setMultiSelectionEnabled( false );
302         _writetopdf_filechooser.addChoosableFileFilter( pdffilter );
303         _writetographics_filechooser = new JFileChooser();
304         _writetographics_filechooser.setMultiSelectionEnabled( false );
305         _writetographics_filechooser.addChoosableFileFilter( graphicsfilefilter );
306         _save_filechooser = new JFileChooser();
307         _save_filechooser.setMultiSelectionEnabled( false );
308         _save_filechooser.setFileFilter( xmlfilter );
309         _save_filechooser.addChoosableFileFilter( nhfilter );
310         _save_filechooser.addChoosableFileFilter( nexusfilter );
311         _save_filechooser.addChoosableFileFilter( _save_filechooser.getAcceptAllFileFilter() );
312         try {
313             final String home_dir = System.getProperty( "user.home" );
314             _save_filechooser.setCurrentDirectory( new File( home_dir ) );
315             _writetopdf_filechooser.setCurrentDirectory( new File( home_dir ) );
316             _writetographics_filechooser.setCurrentDirectory( new File( home_dir ) );
317         }
318         catch ( final Exception e ) {
319             e.printStackTrace();
320             // Do nothing. Not important.
321         }
322     }
323
324     /**
325      * Action performed.
326      */
327     @Override
328     public void actionPerformed( final ActionEvent e ) {
329         final Object o = e.getSource();
330         boolean is_applet = false;
331         JApplet applet = null;
332         if ( getCurrentTreePanel() != null ) {
333             is_applet = getCurrentTreePanel().isApplet();
334             if ( is_applet ) {
335                 applet = getCurrentTreePanel().obtainApplet();
336             }
337         }
338         if ( o == _exit_item ) {
339             close();
340         }
341         else if ( o == _gsdi_item ) {
342             if ( isSubtreeDisplayed() ) {
343                 return;
344             }
345             executeGSDI();
346         }
347         else if ( o == _gsdir_item ) {
348             if ( isSubtreeDisplayed() ) {
349                 return;
350             }
351             executeGSDIR();
352         }
353         else if ( o == _taxcolor_item ) {
354             taxColor();
355         }
356         else if ( o == _confcolor_item ) {
357             confColor();
358         }
359         else if ( o == _color_rank_jmi ) {
360             colorRank();
361         }
362         else if ( o == _collapse_species_specific_subtrees ) {
363             if ( isSubtreeDisplayed() ) {
364                 return;
365             }
366             if ( getCurrentTreePanel() != null ) {
367                 getCurrentTreePanel().collapseSpeciesSpecificSubtrees();
368             }
369         }
370         else if ( o == _remove_branch_color_item ) {
371             if ( isSubtreeDisplayed() ) {
372                 return;
373             }
374             removeBranchColors();
375         }
376         else if ( o == _remove_visual_styles_item ) {
377             if ( isSubtreeDisplayed() ) {
378                 return;
379             }
380             removeVisualStyles();
381         }
382         else if ( o == _midpoint_root_item ) {
383             if ( isSubtreeDisplayed() ) {
384                 return;
385             }
386             midpointRoot();
387         }
388         else if ( o == _delete_selected_nodes_item ) {
389             if ( isSubtreeDisplayed() ) {
390                 return;
391             }
392             deleteSelectedNodes( true );
393         }
394         else if ( o == _delete_not_selected_nodes_item ) {
395             if ( isSubtreeDisplayed() ) {
396                 return;
397             }
398             deleteSelectedNodes( false );
399         }
400         else if ( o == _annotate_item ) {
401             annotateSequences();
402         }
403         else if ( o == _switch_colors_mi ) {
404             switchColors();
405         }
406         else if ( o == _display_basic_information_item ) {
407             if ( getCurrentTreePanel() != null ) {
408                 displayBasicInformation( getCurrentTreePanel().getTreeFile() );
409             }
410         }
411         else if ( o == _view_as_NH_item ) {
412             viewAsNH();
413         }
414         else if ( o == _view_as_XML_item ) {
415             viewAsXML();
416         }
417         else if ( o == _view_as_nexus_item ) {
418             viewAsNexus();
419         }
420         else if ( o == _super_tiny_fonts_item ) {
421             if ( getCurrentTreePanel() != null ) {
422                 getCurrentTreePanel().setSuperTinyFonts();
423                 getCurrentTreePanel().repaint();
424             }
425         }
426         else if ( o == _tiny_fonts_item ) {
427             if ( getCurrentTreePanel() != null ) {
428                 getCurrentTreePanel().setTinyFonts();
429                 getCurrentTreePanel().repaint();
430             }
431         }
432         else if ( o == _small_fonts_item ) {
433             if ( getCurrentTreePanel() != null ) {
434                 getCurrentTreePanel().setSmallFonts();
435                 getCurrentTreePanel().repaint();
436             }
437         }
438         else if ( o == _medium_fonts_item ) {
439             if ( getCurrentTreePanel() != null ) {
440                 getCurrentTreePanel().setMediumFonts();
441                 getCurrentTreePanel().repaint();
442             }
443         }
444         else if ( o == _large_fonts_item ) {
445             if ( getCurrentTreePanel() != null ) {
446                 getCurrentTreePanel().setLargeFonts();
447                 getCurrentTreePanel().repaint();
448             }
449         }
450         else if ( o == _choose_font_mi ) {
451             chooseFont();
452         }
453         else if ( o == _choose_minimal_confidence_mi ) {
454             chooseMinimalConfidence();
455         }
456         else if ( o == _choose_node_size_mi ) {
457             chooseNodeSize( getOptions(), this );
458         }
459         else if ( o == _overview_placment_mi ) {
460             MainFrame.cycleOverview( getOptions(), getCurrentTreePanel() );
461         }
462         else if ( o == _cycle_node_fill_mi ) {
463             MainFrame.cycleNodeFill( getOptions() );
464         }
465         else if ( o == _cycle_node_shape_mi ) {
466             MainFrame.cycleNodeShape( getOptions() );
467         }
468         else if ( o == _cycle_data_return ) {
469             MainFrame.cycleNodeDataReturn( getOptions(), getConfiguration() );
470         }
471         else if ( o == _screen_antialias_cbmi ) {
472             updateOptions( getOptions() );
473             updateScreenTextAntialias( getMainPanel().getTreePanels() );
474         }
475         else if ( o == _background_gradient_cbmi ) {
476             updateOptions( getOptions() );
477         }
478         else if ( o == _show_domain_labels ) {
479             updateOptions( getOptions() );
480         }
481         else if ( o == _show_annotation_ref_source ) {
482             updateOptions( getOptions() );
483         }
484         else if ( o == _abbreviate_scientific_names ) {
485             updateOptions( getOptions() );
486         }
487         else if ( o == _color_labels_same_as_parent_branch ) {
488             updateOptions( getOptions() );
489         }
490         else if ( o == _show_default_node_shapes_internal_cbmi ) {
491             updateOptions( getOptions() );
492         }
493         else if ( o == _show_default_node_shapes_external_cbmi ) {
494             updateOptions( getOptions() );
495         }
496         else if ( o == _show_default_node_shapes_for_marked_cbmi ) {
497             updateOptions( getOptions() );
498         }
499         else if ( o == _non_lined_up_cladograms_rbmi ) {
500             updateOptions( getOptions() );
501             showWhole();
502         }
503         else if ( o == _ext_node_dependent_cladogram_rbmi ) {
504             updateOptions( getOptions() );
505             showWhole();
506         }
507         else if ( o == _search_case_senstive_cbmi ) {
508             updateOptions( getOptions() );
509             getMainPanel().getControlPanel().search0();
510             getMainPanel().getControlPanel().search1();
511         }
512         else if ( o == _search_whole_words_only_cbmi ) {
513             if ( ( _search_with_regex_cbmi != null ) && _search_whole_words_only_cbmi.isSelected() ) {
514                 _search_with_regex_cbmi.setSelected( false );
515             }
516             updateOptions( getOptions() );
517             getMainPanel().getControlPanel().search0();
518             getMainPanel().getControlPanel().search1();
519         }
520         else if ( o == _inverse_search_result_cbmi ) {
521             updateOptions( getOptions() );
522             getMainPanel().getControlPanel().search0();
523             getMainPanel().getControlPanel().search1();
524         }
525         else if ( o == _search_with_regex_cbmi ) {
526             if ( ( _search_whole_words_only_cbmi != null ) && _search_with_regex_cbmi.isSelected() ) {
527                 _search_whole_words_only_cbmi.setSelected( false );
528             }
529             if ( ( _search_case_senstive_cbmi != null ) && _search_with_regex_cbmi.isSelected() ) {
530                 _search_case_senstive_cbmi.setSelected( true );
531             }
532             updateOptions( getOptions() );
533             getMainPanel().getControlPanel().search0();
534             getMainPanel().getControlPanel().search1();
535         }
536         else if ( o == _color_all_found_nodes_when_coloring_subtree_cbmi ) {
537             updateOptions( getOptions() );
538         }
539         else if ( o == _parse_beast_style_extended_nexus_tags_cbmi ) {
540             updateOptions( getOptions() );
541         }
542         else if ( o == _show_scale_cbmi ) {
543             updateOptions( getOptions() );
544         }
545         else if ( o == _color_by_taxonomic_group_cbmi ) {
546             updateOptions( getOptions() );
547         }
548         else if ( o == _show_confidence_stddev_cbmi ) {
549             updateOptions( getOptions() );
550         }
551         else if ( o == _use_brackets_for_conf_in_nh_export_cbmi ) {
552             if ( _use_brackets_for_conf_in_nh_export_cbmi.isSelected() ) {
553                 _use_internal_names_for_conf_in_nh_export_cbmi.setSelected( false );
554             }
555             updateOptions( getOptions() );
556         }
557         else if ( o == _use_internal_names_for_conf_in_nh_export_cbmi ) {
558             if ( _use_internal_names_for_conf_in_nh_export_cbmi.isSelected() ) {
559                 _use_brackets_for_conf_in_nh_export_cbmi.setSelected( false );
560             }
561             updateOptions( getOptions() );
562         }
563         else if ( o == _label_direction_cbmi ) {
564             updateOptions( getOptions() );
565         }
566         else if ( o == _show_overview_cbmi ) {
567             updateOptions( getOptions() );
568             if ( getCurrentTreePanel() != null ) {
569                 getCurrentTreePanel().updateOvSizes();
570             }
571         }
572         else if ( o == _line_up_renderable_data_cbmi ) {
573             if ( !_line_up_renderable_data_cbmi.isSelected() ) {
574                 _right_line_up_domains_cbmi.setSelected( false );
575             }
576             updateOptions( getOptions() );
577         }
578         
579         else if ( o == _collapsed_with_average_height_cbmi ) {
580             if ( _collapsed_with_average_height_cbmi.isSelected() ) {
581                 _collapsed_with_average_height_cbmi.setSelected( true );
582             }
583             updateOptions( getOptions() );
584         }
585         else if ( o == _show_abbreviated_labels_for_collapsed_nodes_cbmi ) {
586             if ( _show_abbreviated_labels_for_collapsed_nodes_cbmi.isSelected() ) {
587                 _show_abbreviated_labels_for_collapsed_nodes_cbmi.setSelected( true );
588             }
589             updateOptions( getOptions() );
590         }
591         else if ( o == _right_line_up_domains_cbmi ) {
592             if ( _right_line_up_domains_cbmi.isSelected() ) {
593                 _line_up_renderable_data_cbmi.setSelected( true );
594             }
595             updateOptions( getOptions() );
596         }
597         else if ( ( o == _rectangular_type_cbmi ) || ( o == _triangular_type_cbmi ) || ( o == _curved_type_cbmi )
598                 || ( o == _convex_type_cbmi ) || ( o == _euro_type_cbmi ) || ( o == _rounded_type_cbmi )
599                 || ( o == _unrooted_type_cbmi ) || ( o == _circular_type_cbmi ) ) {
600             typeChanged( o );
601         }
602         else if ( o == _about_item ) {
603             about();
604         }
605         else if ( o == _help_item ) {
606             try {
607                 AptxUtil.openWebsite( AptxConstants.APTX_DOC_SITE, is_applet, applet );
608             }
609             catch ( final IOException e1 ) {
610                 ForesterUtil.printErrorMessage( AptxConstants.PRG_NAME, e1.toString() );
611             }
612         }
613         else if ( o == _website_item ) {
614             try {
615                 AptxUtil.openWebsite( AptxConstants.APTX_WEB_SITE, is_applet, applet );
616             }
617             catch ( final IOException e1 ) {
618                 ForesterUtil.printErrorMessage( AptxConstants.PRG_NAME, e1.toString() );
619             }
620         }
621         else if ( o == _mailing_list_item ) {
622             try {
623                 AptxUtil.openWebsite( AptxConstants.APTX_MAILING_LIST, is_applet, applet );
624             }
625             catch ( final IOException e1 ) {
626                 ForesterUtil.printErrorMessage( AptxConstants.PRG_NAME, e1.toString() );
627             }
628         }
629         else if ( o == _phyloxml_website_item ) {
630             try {
631                 AptxUtil.openWebsite( AptxConstants.PHYLOXML_WEB_SITE, is_applet, applet );
632             }
633             catch ( final IOException e1 ) {
634                 ForesterUtil.printErrorMessage( AptxConstants.PRG_NAME, e1.toString() );
635             }
636         }
637         else if ( o == _aptx_ref_item ) {
638             try {
639                 AptxUtil.openWebsite( AptxConstants.APTX_REFERENCE_URL, is_applet, applet );
640             }
641             catch ( final IOException e1 ) {
642                 ForesterUtil.printErrorMessage( AptxConstants.PRG_NAME, e1.toString() );
643             }
644         }
645         else if ( o == _phyloxml_ref_item ) {
646             try {
647                 AptxUtil.openWebsite( AptxConstants.PHYLOXML_REFERENCE_URL, is_applet, applet );
648             }
649             catch ( final IOException e1 ) {
650                 ForesterUtil.printErrorMessage( AptxConstants.PRG_NAME, e1.toString() );
651             }
652         }
653         else if ( o == _write_to_pdf_item ) {
654             final File curr_dir = writeToPdf( _mainpanel.getCurrentPhylogeny(),
655                                               getMainPanel(),
656                                               _writetopdf_filechooser,
657                                               _current_dir,
658                                               getContentPane(),
659                                               this );
660             if ( curr_dir != null ) {
661                 setCurrentDir( curr_dir );
662             }
663         }
664         else if ( o == _save_all_item ) {
665             writeAllToFile();
666         }
667         else if ( o == _write_to_jpg_item ) {
668             final File new_dir = writeToGraphicsFile( _mainpanel.getCurrentPhylogeny(),
669                                                       GraphicsExportType.JPG,
670                                                       _mainpanel,
671                                                       _writetographics_filechooser,
672                                                       this,
673                                                       getContentPane(),
674                                                       _current_dir );
675             if ( new_dir != null ) {
676                 setCurrentDir( new_dir );
677             }
678         }
679         else if ( o == _write_to_gif_item ) {
680             final File new_dir = writeToGraphicsFile( _mainpanel.getCurrentPhylogeny(),
681                                                       GraphicsExportType.GIF,
682                                                       _mainpanel,
683                                                       _writetographics_filechooser,
684                                                       this,
685                                                       getContentPane(),
686                                                       _current_dir );
687             if ( new_dir != null ) {
688                 setCurrentDir( new_dir );
689             }
690         }
691         else if ( o == _write_to_tif_item ) {
692             final File new_dir = writeToGraphicsFile( _mainpanel.getCurrentPhylogeny(),
693                                                       GraphicsExportType.TIFF,
694                                                       _mainpanel,
695                                                       _writetographics_filechooser,
696                                                       this,
697                                                       getContentPane(),
698                                                       _current_dir );
699             if ( new_dir != null ) {
700                 setCurrentDir( new_dir );
701             }
702         }
703         else if ( o == _write_to_bmp_item ) {
704             final File new_dir = writeToGraphicsFile( _mainpanel.getCurrentPhylogeny(),
705                                                       GraphicsExportType.BMP,
706                                                       _mainpanel,
707                                                       _writetographics_filechooser,
708                                                       this,
709                                                       getContentPane(),
710                                                       _current_dir );
711             if ( new_dir != null ) {
712                 setCurrentDir( new_dir );
713             }
714         }
715         else if ( o == _write_to_png_item ) {
716             final File new_dir = writeToGraphicsFile( _mainpanel.getCurrentPhylogeny(),
717                                                       GraphicsExportType.PNG,
718                                                       _mainpanel,
719                                                       _writetographics_filechooser,
720                                                       this,
721                                                       getContentPane(),
722                                                       _current_dir );
723             if ( new_dir != null ) {
724                 setCurrentDir( new_dir );
725             }
726         }
727         else if ( o == _print_item ) {
728             print( getCurrentTreePanel(), getOptions(), this );
729         }
730         else if ( o == _save_item ) {
731             final File new_dir = writeToFile( _mainpanel.getCurrentPhylogeny(),
732                                               getMainPanel(),
733                                               _save_filechooser,
734                                               _current_dir,
735                                               getContentPane(),
736                                               this );
737             if ( new_dir != null ) {
738                 setCurrentDir( new_dir );
739             }
740         }
741         else if ( o == _graphics_export_visible_only_cbmi ) {
742             updateOptions( getOptions() );
743         }
744         else if ( o == _antialias_print_cbmi ) {
745             updateOptions( getOptions() );
746         }
747         else if ( o == _print_black_and_white_cbmi ) {
748             updateOptions( getOptions() );
749         }
750         else if ( o == _choose_pdf_width_mi ) {
751             choosePdfWidth();
752         }
753         else if ( o == _lineage_inference ) {
754             if ( isSubtreeDisplayed() ) {
755                 JOptionPane.showMessageDialog( this,
756                                                "Subtree is shown.",
757                                                "Cannot infer ancestral taxonomies",
758                                                JOptionPane.ERROR_MESSAGE );
759                 return;
760             }
761             executeLineageInference();
762         }
763         else {
764             if ( _load_phylogeny_from_webservice_menu_items != null ) {
765                 for( int i = 0; i < _load_phylogeny_from_webservice_menu_items.length; ++i ) {
766                     if ( o == _load_phylogeny_from_webservice_menu_items[ i ] ) {
767                         readPhylogeniesFromWebservice( i );
768                     }
769                 }
770             }
771         }
772         _contentpane.repaint();
773     }
774
775     public Configuration getConfiguration() {
776         return _configuration;
777     }
778
779     /**
780      * This method returns the current external node data which
781      * has been selected by the user by clicking the "Return ..."
782      * menu item. This method is expected to be called from Javascript or
783      * something like it.
784      *
785      * @return current external node data as String
786      */
787     public String getCurrentExternalNodesDataBuffer() {
788         return getCurrentTreePanel().getCurrentExternalNodesDataBufferAsString();
789     }
790
791     public int getCurrentExternalNodesDataBufferChangeCounter() {
792         return getCurrentTreePanel().getCurrentExternalNodesDataBufferChangeCounter();
793     }
794
795     public int getCurrentExternalNodesDataBufferLength() {
796         return getCurrentTreePanel().getCurrentExternalNodesDataBufferAsString().length();
797     }
798
799     public InferenceManager getInferenceManager() {
800         return _inference_manager;
801     }
802
803     public MainPanel getMainPanel() {
804         return _mainpanel;
805     }
806
807     public Options getOptions() {
808         return _options;
809     }
810
811     public ProcessPool getProcessPool() {
812         return _process_pool;
813     }
814
815     public void showTextFrame( final String s, final String title ) {
816         checkTextFrames();
817         _textframes.addLast( TextFrame.instantiate( s, title, _textframes ) );
818     }
819
820     public void showWhole() {
821         _mainpanel.getControlPanel().showWhole();
822     }
823
824     public void updateProcessMenu() {
825         // In general Swing is not thread safe.
826         // See "Swing's Threading Policy".
827         SwingUtilities.invokeLater( new Runnable() {
828
829             @Override
830             public void run() {
831                 doUpdateProcessMenu();
832             }
833         } );
834     }
835
836     private void annotateSequences() {
837         if ( getCurrentTreePanel() != null ) {
838             List<PhylogenyNode> nodes = null;
839             if ( ( getCurrentTreePanel().getFoundNodes0() != null )
840                     || ( getCurrentTreePanel().getFoundNodes1() != null ) ) {
841                 nodes = getCurrentTreePanel().getFoundNodesAsListOfPhylogenyNodes();
842             }
843             if ( ( nodes == null ) || nodes.isEmpty() ) {
844                 JOptionPane
845                         .showMessageDialog( this,
846                                             "Need to select nodes, either via direct selection or via the \"Search\" function",
847                                             "No nodes selected for annotation",
848                                             JOptionPane.ERROR_MESSAGE );
849                 return;
850             }
851             final Phylogeny phy = getMainPanel().getCurrentPhylogeny();
852             if ( ( phy != null ) && !phy.isEmpty() ) {
853                 final JTextField ref_field = new JTextField( 10 );
854                 final JTextField desc_filed = new JTextField( 20 );
855                 ref_field.setText( ForesterUtil.isEmpty( getPreviousNodeAnnotationReference() ) ? ""
856                         : getPreviousNodeAnnotationReference() );
857                 final JPanel my_panel = new JPanel();
858                 my_panel.add( new JLabel( "Reference " ) );
859                 my_panel.add( ref_field );
860                 my_panel.add( Box.createHorizontalStrut( 15 ) );
861                 my_panel.add( new JLabel( "Description " ) );
862                 my_panel.add( desc_filed );
863                 final int result = JOptionPane.showConfirmDialog( null,
864                                                                   my_panel,
865                                                                   "Enter the sequence annotation(s) for the "
866                                                                           + nodes.size() + " selected nodes",
867                                                                   JOptionPane.OK_CANCEL_OPTION );
868                 if ( result == JOptionPane.OK_OPTION ) {
869                     String ref = ref_field.getText();
870                     String desc = desc_filed.getText();
871                     if ( !ForesterUtil.isEmpty( ref ) ) {
872                         ref = ref.trim();
873                         ref = ref.replaceAll( "\\s+", " " );
874                         if ( ( ref.indexOf( ':' ) < 1 ) || ( ref.indexOf( ':' ) > ( ref.length() - 2 ) )
875                                 || ( ref.length() < 3 ) ) {
876                             JOptionPane.showMessageDialog( this,
877                                                            "Reference needs to be in the form of \"GO:1234567\"",
878                                                            "Illegal Format for Annotation Reference",
879                                                            JOptionPane.ERROR_MESSAGE );
880                             return;
881                         }
882                     }
883                     if ( ref != null ) {
884                         setPreviousNodeAnnotationReference( ref );
885                     }
886                     if ( desc != null ) {
887                         desc = desc.trim();
888                         desc = desc.replaceAll( "\\s+", " " );
889                     }
890                     if ( !ForesterUtil.isEmpty( ref ) || !ForesterUtil.isEmpty( desc ) ) {
891                         for( final PhylogenyNode n : nodes ) {
892                             ForesterUtil.ensurePresenceOfSequence( n );
893                             final Annotation ann = ForesterUtil.isEmpty( ref ) ? new Annotation()
894                                     : new Annotation( ref );
895                             if ( !ForesterUtil.isEmpty( desc ) ) {
896                                 ann.setDesc( desc );
897                             }
898                             n.getNodeData().getSequence().addAnnotation( ann );
899                         }
900                     }
901                     getMainPanel().getControlPanel().showAnnotations();
902                 }
903             }
904         }
905     }
906
907     private void chooseFont() {
908         final FontChooser fc = new FontChooser();
909         fc.setFont( getMainPanel().getTreeFontSet().getLargeFont() );
910         fc.showDialog( this, "Select the Base Font" );
911         getMainPanel().getTreeFontSet().setBaseFont( fc.getFont() );
912         getControlPanel().displayedPhylogenyMightHaveChanged( true );
913         if ( getMainPanel().getCurrentTreePanel() != null ) {
914             getMainPanel().getCurrentTreePanel().resetPreferredSize();
915             getMainPanel().getCurrentTreePanel().updateOvSizes();
916         }
917        
918         repaint();
919     }
920
921     private void chooseMinimalConfidence() {
922         final String s = ( String ) JOptionPane
923                 .showInputDialog( this,
924                                   "Please enter the minimum for confidence values to be displayed.\n"
925                                           + "[current value: " + getOptions().getMinConfidenceValue() + "]\n",
926                                   "Minimal Confidence Value",
927                                   JOptionPane.QUESTION_MESSAGE,
928                                   null,
929                                   null,
930                                   getOptions().getMinConfidenceValue() );
931         if ( !ForesterUtil.isEmpty( s ) ) {
932             boolean success = true;
933             double m = 0.0;
934             final String m_str = s.trim();
935             if ( !ForesterUtil.isEmpty( m_str ) ) {
936                 try {
937                     m = Double.parseDouble( m_str );
938                 }
939                 catch ( final Exception ex ) {
940                     success = false;
941                 }
942             }
943             else {
944                 success = false;
945             }
946             if ( success && ( m >= 0.0 ) ) {
947                 getOptions().setMinConfidenceValue( m );
948             }
949         }
950     }
951
952     private void deleteSelectedNodes( final boolean delete ) {
953         final Phylogeny phy = getMainPanel().getCurrentPhylogeny();
954         if ( ( phy == null ) || ( phy.getNumberOfExternalNodes() < 2 ) ) {
955             return;
956         }
957         final List<PhylogenyNode> nodes = new ArrayList<PhylogenyNode>();
958         if ( ( getCurrentTreePanel().getFoundNodes0() != null ) || ( getCurrentTreePanel().getFoundNodes1() != null ) ) {
959             final List<PhylogenyNode> all_selected_nodes = getCurrentTreePanel().getFoundNodesAsListOfPhylogenyNodes();
960             for( final PhylogenyNode n : all_selected_nodes ) {
961                 if ( n.isExternal() ) {
962                     nodes.add( n );
963                 }
964             }
965         }
966         String function = "Retain";
967         if ( delete ) {
968             function = "Delete";
969         }
970         if ( ( nodes == null ) || nodes.isEmpty() ) {
971             JOptionPane
972                     .showMessageDialog( this,
973                                         "Need to select external nodes, either via direct selection or via the \"Search\" function",
974                                         "No external nodes selected to " + function.toLowerCase(),
975                                         JOptionPane.ERROR_MESSAGE );
976             return;
977         }
978         final int todo = nodes.size();
979         final int ext = phy.getNumberOfExternalNodes();
980         int res = todo;
981         if ( delete ) {
982             res = ext - todo;
983         }
984         if ( res < 1 ) {
985             JOptionPane.showMessageDialog( this,
986                                            "Cannot delete all nodes",
987                                            "Attempt to delete all nodes ",
988                                            JOptionPane.ERROR_MESSAGE );
989             return;
990         }
991         final int result = JOptionPane.showConfirmDialog( null, function + " " + todo
992                 + " external node(s), from a total of " + ext + " external nodes," + "\nresulting in tree with " + res
993                 + " nodes?", function + " external nodes", JOptionPane.OK_CANCEL_OPTION );
994         if ( result == JOptionPane.OK_OPTION ) {
995             if ( !delete ) {
996                 final List<PhylogenyNode> to_delete = new ArrayList<PhylogenyNode>();
997                 for( final PhylogenyNodeIterator it = phy.iteratorExternalForward(); it.hasNext(); ) {
998                     final PhylogenyNode n = it.next();
999                     if ( !nodes.contains( n ) ) {
1000                         to_delete.add( n );
1001                     }
1002                 }
1003                 for( final PhylogenyNode n : to_delete ) {
1004                     phy.deleteSubtree( n, true );
1005                 }
1006             }
1007             else {
1008                 for( final PhylogenyNode n : nodes ) {
1009                     phy.deleteSubtree( n, true );
1010                 }
1011             }
1012             resetSearch();
1013             getCurrentTreePanel().setNodeInPreorderToNull();
1014             phy.externalNodesHaveChanged();
1015             phy.clearHashIdToNodeMap();
1016             phy.recalculateNumberOfExternalDescendants( true );
1017             getCurrentTreePanel().resetNodeIdToDistToLeafMap();
1018             getCurrentTreePanel().setEdited( true );
1019             repaint();
1020         }
1021     }
1022
1023     private void doUpdateProcessMenu() {
1024         if ( _process_pool.size() > 0 ) {
1025             if ( _process_menu == null ) {
1026                 _process_menu = createMenu( "", getConfiguration() );
1027                 _process_menu.setForeground( Color.RED );
1028             }
1029             _process_menu.removeAll();
1030             final String text = "processes running: " + _process_pool.size();
1031             _process_menu.setText( text );
1032             _jmenubar.add( _process_menu );
1033             for( int i = 0; i < _process_pool.size(); ++i ) {
1034                 final ProcessRunning p = _process_pool.getProcessByIndex( i );
1035                 _process_menu.add( customizeJMenuItem( new JMenuItem( p.getName() + " [" + p.getStart() + "]" ) ) );
1036             }
1037         }
1038         else {
1039             if ( _process_menu != null ) {
1040                 _process_menu.removeAll();
1041                 _jmenubar.remove( _process_menu );
1042             }
1043         }
1044         _jmenubar.validate();
1045         _jmenubar.repaint();
1046         repaint();
1047     }
1048
1049     private String getPreviousNodeAnnotationReference() {
1050         return _previous_node_annotation_ref;
1051     }
1052
1053     private void removeBranchColors() {
1054         if ( getMainPanel().getCurrentPhylogeny() != null ) {
1055             AptxUtil.removeBranchColors( getMainPanel().getCurrentPhylogeny() );
1056         }
1057     }
1058
1059     private void removeVisualStyles() {
1060         if ( getMainPanel().getCurrentPhylogeny() != null ) {
1061             AptxUtil.removeVisualStyles( getMainPanel().getCurrentPhylogeny() );
1062         }
1063     }
1064
1065     private void setPreviousNodeAnnotationReference( final String previous_node_annotation_ref ) {
1066         _previous_node_annotation_ref = previous_node_annotation_ref;
1067     }
1068
1069     private void writeAllToFile() {
1070         if ( ( getMainPanel().getTabbedPane() == null ) || ( getMainPanel().getTabbedPane().getTabCount() < 1 ) ) {
1071             return;
1072         }
1073         final File my_dir = getCurrentDir();
1074         if ( my_dir != null ) {
1075             _save_filechooser.setCurrentDirectory( my_dir );
1076         }
1077         _save_filechooser.setSelectedFile( new File( "" ) );
1078         final int result = _save_filechooser.showSaveDialog( _contentpane );
1079         final File file = _save_filechooser.getSelectedFile();
1080         setCurrentDir( _save_filechooser.getCurrentDirectory() );
1081         if ( ( file != null ) && ( result == JFileChooser.APPROVE_OPTION ) ) {
1082             if ( file.exists() ) {
1083                 final int i = JOptionPane.showConfirmDialog( this,
1084                                                              file + " already exists. Overwrite?",
1085                                                              "Warning",
1086                                                              JOptionPane.OK_CANCEL_OPTION,
1087                                                              JOptionPane.WARNING_MESSAGE );
1088                 if ( i != JOptionPane.OK_OPTION ) {
1089                     return;
1090                 }
1091                 else {
1092                     try {
1093                         file.delete();
1094                     }
1095                     catch ( final Exception e ) {
1096                         JOptionPane.showMessageDialog( this,
1097                                                        "Failed to delete: " + file,
1098                                                        "Error",
1099                                                        JOptionPane.WARNING_MESSAGE );
1100                     }
1101                 }
1102             }
1103             final int count = getMainPanel().getTabbedPane().getTabCount();
1104             final List<Phylogeny> trees = new ArrayList<Phylogeny>();
1105             for( int i = 0; i < count; ++i ) {
1106                 final Phylogeny phy = getMainPanel().getPhylogeny( i );
1107                 if ( ForesterUtil.isEmpty( phy.getName() )
1108                         && !ForesterUtil.isEmpty( getMainPanel().getTabbedPane().getTitleAt( i ) ) ) {
1109                     phy.setName( getMainPanel().getTabbedPane().getTitleAt( i ) );
1110                 }
1111                 trees.add( phy );
1112                 getMainPanel().getTreePanels().get( i ).setEdited( false );
1113             }
1114             final PhylogenyWriter writer = new PhylogenyWriter();
1115             try {
1116                 writer.toPhyloXML( file, trees, 0, ForesterUtil.LINE_SEPARATOR );
1117             }
1118             catch ( final IOException e ) {
1119                 JOptionPane.showMessageDialog( this,
1120                                                "Failed to write to: " + file,
1121                                                "Error",
1122                                                JOptionPane.WARNING_MESSAGE );
1123             }
1124         }
1125     }
1126
1127     void activateSaveAllIfNeeded() {
1128         if ( ( getMainPanel().getTabbedPane() != null ) && ( getMainPanel().getTabbedPane().getTabCount() > 1 ) ) {
1129             _save_all_item.setEnabled( true );
1130         }
1131         else {
1132             _save_all_item.setEnabled( false );
1133         }
1134     }
1135
1136     void buildFileMenu() {
1137         _file_jmenu = MainFrame.createMenu( "File", getConfiguration() );
1138         _file_jmenu.add( _save_item = new JMenuItem( "Save Tree As..." ) );
1139         _file_jmenu.addSeparator();
1140         _file_jmenu.add( _write_to_pdf_item = new JMenuItem( "Export to PDF file ..." ) );
1141         if ( AptxUtil.canWriteFormat( "tif" ) || AptxUtil.canWriteFormat( "tiff" ) || AptxUtil.canWriteFormat( "TIF" ) ) {
1142             _file_jmenu.add( _write_to_tif_item = new JMenuItem( "Export to TIFF file..." ) );
1143         }
1144         _file_jmenu.add( _write_to_png_item = new JMenuItem( "Export to PNG file..." ) );
1145         _file_jmenu.add( _write_to_jpg_item = new JMenuItem( "Export to JPG file..." ) );
1146         if ( AptxUtil.canWriteFormat( "gif" ) ) {
1147             _file_jmenu.add( _write_to_gif_item = new JMenuItem( "Export to GIF file..." ) );
1148         }
1149         if ( AptxUtil.canWriteFormat( "bmp" ) ) {
1150             _file_jmenu.add( _write_to_bmp_item = new JMenuItem( "Export to BMP file..." ) );
1151         }
1152         _file_jmenu.addSeparator();
1153         _file_jmenu.add( _print_item = new JMenuItem( "Print..." ) );
1154         _file_jmenu.addSeparator();
1155         _file_jmenu.add( _exit_item = new JMenuItem( "Exit" ) );
1156         customizeJMenuItem( _save_item );
1157         customizeJMenuItem( _write_to_pdf_item );
1158         customizeJMenuItem( _write_to_png_item );
1159         customizeJMenuItem( _write_to_jpg_item );
1160         customizeJMenuItem( _write_to_gif_item );
1161         customizeJMenuItem( _write_to_tif_item );
1162         customizeJMenuItem( _write_to_bmp_item );
1163         customizeJMenuItem( _print_item );
1164         customizeJMenuItem( _exit_item );
1165         _jmenubar.add( _file_jmenu );
1166     }
1167
1168     void buildFontSizeMenu() {
1169         _font_size_menu = createMenu( FONT_SIZE_MENU_LABEL, getConfiguration() );
1170         _font_size_menu.add( _super_tiny_fonts_item = new JMenuItem( "Super Tiny Fonts" ) );
1171         _font_size_menu.add( _tiny_fonts_item = new JMenuItem( "Tiny Fonts" ) );
1172         _font_size_menu.add( _small_fonts_item = new JMenuItem( "Small Fonts" ) );
1173         _font_size_menu.add( _medium_fonts_item = new JMenuItem( "Medium Fonts" ) );
1174         _font_size_menu.add( _large_fonts_item = new JMenuItem( "Large Fonts" ) );
1175         customizeJMenuItem( _super_tiny_fonts_item );
1176         customizeJMenuItem( _tiny_fonts_item );
1177         customizeJMenuItem( _small_fonts_item );
1178         customizeJMenuItem( _medium_fonts_item );
1179         customizeJMenuItem( _large_fonts_item );
1180         _jmenubar.add( _font_size_menu );
1181     }
1182
1183     void buildHelpMenu() {
1184         _help_jmenu = createMenu( "Help", getConfiguration() );
1185         _help_jmenu.add( _help_item = new JMenuItem( "Documentation" ) );
1186         _help_jmenu.addSeparator();
1187         _help_jmenu.add( _website_item = new JMenuItem( "Archaeopteryx Home" ) );
1188         _help_jmenu.add( _mailing_list_item = new JMenuItem( "Mailing List" ) );
1189         _aptx_ref_item = new JMenuItem( "Archaeopteryx Reference" ); //TODO need to add this...
1190         _help_jmenu.add( _phyloxml_website_item = new JMenuItem( "phyloXML Home" ) );
1191         _help_jmenu.add( _phyloxml_ref_item = new JMenuItem( "phyloXML Reference" ) );
1192         _help_jmenu.addSeparator();
1193         _help_jmenu.add( _about_item = new JMenuItem( "About" ) );
1194         customizeJMenuItem( _help_item );
1195         customizeJMenuItem( _website_item );
1196         customizeJMenuItem( _mailing_list_item );
1197         customizeJMenuItem( _phyloxml_website_item );
1198         customizeJMenuItem( _aptx_ref_item );
1199         customizeJMenuItem( _phyloxml_ref_item );
1200         customizeJMenuItem( _about_item );
1201         _phyloxml_ref_item.setToolTipText( PHYLOXML_REF_TOOL_TIP );
1202         _aptx_ref_item.setToolTipText( APTX_REF_TOOL_TIP );
1203         _jmenubar.add( _help_jmenu );
1204     }
1205
1206     void buildTypeMenu() {
1207         _type_menu = createMenu( TYPE_MENU_HEADER, getConfiguration() );
1208         _type_menu.add( _rectangular_type_cbmi = new JCheckBoxMenuItem( MainFrame.RECTANGULAR_TYPE_CBMI_LABEL ) );
1209         _type_menu.add( _euro_type_cbmi = new JCheckBoxMenuItem( MainFrame.EURO_TYPE_CBMI_LABEL ) );
1210         _type_menu.add( _rounded_type_cbmi = new JCheckBoxMenuItem( MainFrame.ROUNDED_TYPE_CBMI_LABEL ) );
1211         _type_menu.add( _curved_type_cbmi = new JCheckBoxMenuItem( MainFrame.CURVED_TYPE_CBMI_LABEL ) );
1212         _type_menu.add( _triangular_type_cbmi = new JCheckBoxMenuItem( MainFrame.TRIANGULAR_TYPE_CBMI_LABEL ) );
1213         _type_menu.add( _convex_type_cbmi = new JCheckBoxMenuItem( MainFrame.CONVEX_TYPE_CBMI_LABEL ) );
1214         _type_menu.add( _unrooted_type_cbmi = new JCheckBoxMenuItem( MainFrame.UNROOTED_TYPE_CBMI_LABEL ) );
1215         _type_menu.add( _circular_type_cbmi = new JCheckBoxMenuItem( MainFrame.CIRCULAR_TYPE_CBMI_LABEL ) );
1216         customizeCheckBoxMenuItem( _rectangular_type_cbmi, false );
1217         customizeCheckBoxMenuItem( _triangular_type_cbmi, false );
1218         customizeCheckBoxMenuItem( _euro_type_cbmi, false );
1219         customizeCheckBoxMenuItem( _rounded_type_cbmi, false );
1220         customizeCheckBoxMenuItem( _curved_type_cbmi, false );
1221         customizeCheckBoxMenuItem( _convex_type_cbmi, false );
1222         customizeCheckBoxMenuItem( _unrooted_type_cbmi, false );
1223         customizeCheckBoxMenuItem( _circular_type_cbmi, false );
1224         _triangular_type_cbmi.setToolTipText( "not suitable for phylograms" );
1225         _curved_type_cbmi.setToolTipText( "not suitable for phylograms" );
1226         _unrooted_type_cbmi.setToolTipText( MainFrame.USE_MOUSEWHEEL_SHIFT_TO_ROTATE );
1227         _circular_type_cbmi.setToolTipText( MainFrame.USE_MOUSEWHEEL_SHIFT_TO_ROTATE );
1228         initializeTypeMenu( getOptions() );
1229         _jmenubar.add( _type_menu );
1230     }
1231
1232     void buildViewMenu() {
1233         _view_jmenu = createMenu( "View", getConfiguration() );
1234         _view_jmenu.add( _display_basic_information_item = new JMenuItem( SHOW_BASIC_TREE_INFORMATION_LABEL ) );
1235         _view_jmenu.addSeparator();
1236         _view_jmenu.add( _view_as_XML_item = new JMenuItem( "as phyloXML" ) );
1237         _view_jmenu.add( _view_as_NH_item = new JMenuItem( "as Newick" ) );
1238         _view_jmenu.add( _view_as_nexus_item = new JMenuItem( "as Nexus" ) );
1239         customizeJMenuItem( _display_basic_information_item );
1240         customizeJMenuItem( _view_as_NH_item );
1241         customizeJMenuItem( _view_as_XML_item );
1242         customizeJMenuItem( _view_as_nexus_item );
1243         _jmenubar.add( _view_jmenu );
1244     }
1245
1246     void checkTextFrames() {
1247         if ( _textframes.size() > 5 ) {
1248             try {
1249                 if ( _textframes.getFirst() != null ) {
1250                     _textframes.getFirst().removeMe();
1251                 }
1252                 else {
1253                     _textframes.removeFirst();
1254                 }
1255             }
1256             catch ( final NoSuchElementException e ) {
1257                 // Ignore.
1258             }
1259         }
1260     }
1261
1262     void choosePdfWidth() {
1263         final String s = ( String ) JOptionPane.showInputDialog( this,
1264                                                                  "Please enter the default line width for PDF export.\n"
1265                                                                          + "[current value: "
1266                                                                          + getOptions().getPrintLineWidth() + "]\n",
1267                                                                  "Line Width for PDF Export",
1268                                                                  JOptionPane.QUESTION_MESSAGE,
1269                                                                  null,
1270                                                                  null,
1271                                                                  getOptions().getPrintLineWidth() );
1272         if ( !ForesterUtil.isEmpty( s ) ) {
1273             boolean success = true;
1274             float f = 0.0f;
1275             final String m_str = s.trim();
1276             if ( !ForesterUtil.isEmpty( m_str ) ) {
1277                 try {
1278                     f = Float.parseFloat( m_str );
1279                 }
1280                 catch ( final Exception ex ) {
1281                     success = false;
1282                 }
1283             }
1284             else {
1285                 success = false;
1286             }
1287             if ( success && ( f > 0.0 ) ) {
1288                 getOptions().setPrintLineWidth( f );
1289             }
1290         }
1291     }
1292
1293     void close() {
1294         removeAllTextFrames();
1295         if ( _mainpanel != null ) {
1296             _mainpanel.terminate();
1297         }
1298         if ( _contentpane != null ) {
1299             _contentpane.removeAll();
1300         }
1301         setVisible( false );
1302         dispose();
1303     }
1304
1305     void colorRank() {
1306         if ( _mainpanel.getCurrentTreePanel() != null ) {
1307             final Map<String, Integer> present_ranks = AptxUtil.getRankCounts( _mainpanel.getCurrentTreePanel().getPhylogeny());
1308             final String[] ranks = AptxUtil.getAllPossibleRanks(present_ranks);
1309             String rank = ( String ) JOptionPane
1310                     .showInputDialog( this,
1311                                       "What rank should the colorization be based on",
1312                                       "Rank Selection",
1313                                       JOptionPane.QUESTION_MESSAGE,
1314                                       null,
1315                                       ranks,
1316                                       null );
1317             if ( !ForesterUtil.isEmpty( rank ) ) {
1318                 if ( rank.indexOf( '(' ) > 0 ) {
1319                     rank = rank.substring( 0, rank.indexOf( '(' ) ).trim();
1320                 }
1321                 _mainpanel.getCurrentTreePanel().colorRank( rank );
1322             }
1323         }
1324     }
1325
1326     void confColor() {
1327         if ( _mainpanel.getCurrentTreePanel() != null ) {
1328             _mainpanel.getCurrentTreePanel().confColor();
1329         }
1330     }
1331
1332     void customizeCheckBoxMenuItem( final JCheckBoxMenuItem item, final boolean is_selected ) {
1333         if ( item != null ) {
1334             item.setFont( MainFrame.menu_font );
1335             if ( !getConfiguration().isUseNativeUI() ) {
1336                 item.setBackground( getConfiguration().getGuiMenuBackgroundColor() );
1337                 item.setForeground( getConfiguration().getGuiMenuTextColor() );
1338             }
1339             item.setSelected( is_selected );
1340             item.addActionListener( this );
1341         }
1342     }
1343
1344     JMenuItem customizeJMenuItem( final JMenuItem jmi ) {
1345         if ( jmi != null ) {
1346             jmi.setFont( MainFrame.menu_font );
1347             if ( !getConfiguration().isUseNativeUI() ) {
1348                 jmi.setBackground( getConfiguration().getGuiMenuBackgroundColor() );
1349                 jmi.setForeground( getConfiguration().getGuiMenuTextColor() );
1350             }
1351             jmi.addActionListener( this );
1352         }
1353         return jmi;
1354     }
1355
1356     void customizeRadioButtonMenuItem( final JRadioButtonMenuItem item, final boolean is_selected ) {
1357         if ( item != null ) {
1358             item.setFont( MainFrame.menu_font );
1359             if ( !getConfiguration().isUseNativeUI() ) {
1360                 item.setBackground( getConfiguration().getGuiMenuBackgroundColor() );
1361                 item.setForeground( getConfiguration().getGuiMenuTextColor() );
1362             }
1363             item.setSelected( is_selected );
1364             item.addActionListener( this );
1365         }
1366     }
1367
1368     void displayBasicInformation( final File treefile ) {
1369         if ( ( _mainpanel.getCurrentPhylogeny() != null ) && !_mainpanel.getCurrentPhylogeny().isEmpty() ) {
1370             String title = "Basic Information";
1371             if ( !ForesterUtil.isEmpty( _mainpanel.getCurrentPhylogeny().getName() ) ) {
1372                 title = title + " for \"" + _mainpanel.getCurrentPhylogeny().getName() + "\"";
1373             }
1374             showTextFrame( AptxUtil.createBasicInformation( _mainpanel.getCurrentPhylogeny(), treefile ), title );
1375         }
1376     }
1377
1378     void exceptionOccuredDuringOpenFile( final Exception e ) {
1379         try {
1380             _mainpanel.getCurrentTreePanel().setArrowCursor();
1381         }
1382         catch ( final Exception ex ) {
1383             // Do nothing.
1384         }
1385         JOptionPane.showMessageDialog( this,
1386                                        ForesterUtil.wordWrap( e.getLocalizedMessage(), 80 ),
1387                                        "Error during File|Open",
1388                                        JOptionPane.ERROR_MESSAGE );
1389     }
1390
1391     void executeGSDI() {
1392         if ( !isOKforSDI( false, true ) ) {
1393             return;
1394         }
1395         if ( !_mainpanel.getCurrentPhylogeny().isRooted() ) {
1396             JOptionPane.showMessageDialog( this,
1397                                            "Gene tree is not rooted.",
1398                                            "Cannot execute GSDI",
1399                                            JOptionPane.ERROR_MESSAGE );
1400             return;
1401         }
1402         final Phylogeny gene_tree = _mainpanel.getCurrentPhylogeny().copy();
1403         gene_tree.setAllNodesToNotCollapse();
1404         gene_tree.recalculateNumberOfExternalDescendants( false );
1405         GSDI gsdi = null;
1406         final Phylogeny species_tree = getSpeciesTree().copy();
1407         try {
1408             gsdi = new GSDI( gene_tree, species_tree, false, true, true, true );
1409         }
1410         catch ( final SDIException e ) {
1411             JOptionPane.showMessageDialog( this,
1412                                            e.getLocalizedMessage(),
1413                                            "Error during GSDI",
1414                                            JOptionPane.ERROR_MESSAGE );
1415             return;
1416         }
1417         catch ( final Exception e ) {
1418             AptxUtil.unexpectedException( e );
1419             return;
1420         }
1421         gene_tree.setRerootable( false );
1422         gene_tree.clearHashIdToNodeMap();
1423         gene_tree.recalculateNumberOfExternalDescendants( true );
1424         _mainpanel.addPhylogenyInNewTab( gene_tree, getConfiguration(), "gene tree", null );
1425         getMainPanel().getControlPanel().setShowEvents( true );
1426         showWhole();
1427         final int selected = _mainpanel.getTabbedPane().getSelectedIndex();
1428         _mainpanel.addPhylogenyInNewTab( species_tree, getConfiguration(), "species tree", null );
1429         showWhole();
1430         _mainpanel.getTabbedPane().setSelectedIndex( selected );
1431         showWhole();
1432         _mainpanel.getCurrentTreePanel().setEdited( true );
1433         final int poly = PhylogenyMethods.countNumberOfPolytomies( species_tree );
1434         if ( gsdi.getStrippedExternalGeneTreeNodes().size() > 0 ) {
1435             JOptionPane.showMessageDialog( this,
1436                                            "Duplications: " + gsdi.getDuplicationsSum() + "\n"
1437                                                    + "Potential duplications: "
1438                                                    + gsdi.getSpeciationOrDuplicationEventsSum() + "\n"
1439                                                    + "Speciations: " + gsdi.getSpeciationsSum() + "\n"
1440                                                    + "Stripped gene tree nodes: "
1441                                                    + gsdi.getStrippedExternalGeneTreeNodes().size() + "\n"
1442                                                    + "Taxonomy linkage based on: " + gsdi.getTaxCompBase() + "\n"
1443                                                    + "Number of polytomies in species tree used: " + poly + "\n",
1444                                            "GSDI successfully completed",
1445                                            JOptionPane.WARNING_MESSAGE );
1446         }
1447         else {
1448             JOptionPane.showMessageDialog( this,
1449                                            "Duplications: " + gsdi.getDuplicationsSum() + "\n"
1450                                                    + "Potential duplications: "
1451                                                    + gsdi.getSpeciationOrDuplicationEventsSum() + "\n"
1452                                                    + "Speciations: " + gsdi.getSpeciationsSum() + "\n"
1453                                                    + "Stripped gene tree nodes: "
1454                                                    + gsdi.getStrippedExternalGeneTreeNodes().size() + "\n"
1455                                                    + "Taxonomy linkage based on: " + gsdi.getTaxCompBase() + "\n"
1456                                                    + "Number of polytomies in species tree used: " + poly + "\n",
1457                                            "GSDI successfully completed",
1458                                            JOptionPane.INFORMATION_MESSAGE );
1459         }
1460     }
1461
1462     void executeGSDIR() {
1463         if ( !isOKforSDI( false, false ) ) {
1464             return;
1465         }
1466         final int p = PhylogenyMethods.countNumberOfPolytomies( _mainpanel.getCurrentPhylogeny() );
1467         if ( ( p > 0 )
1468                 && !( ( p == 1 ) && ( _mainpanel.getCurrentPhylogeny().getRoot().getNumberOfDescendants() == 3 ) ) ) {
1469             JOptionPane.showMessageDialog( this,
1470                                            "Gene tree is not completely binary",
1471                                            "Cannot execute GSDI",
1472                                            JOptionPane.ERROR_MESSAGE );
1473             return;
1474         }
1475         final Phylogeny gene_tree = _mainpanel.getCurrentPhylogeny().copy();
1476         gene_tree.setAllNodesToNotCollapse();
1477         gene_tree.recalculateNumberOfExternalDescendants( false );
1478         GSDIR gsdir = null;
1479         final Phylogeny species_tree = getSpeciesTree().copy();
1480         try {
1481             gsdir = new GSDIR( gene_tree, species_tree, true, true, true );
1482         }
1483         catch ( final SDIException e ) {
1484             JOptionPane.showMessageDialog( this,
1485                                            e.getLocalizedMessage(),
1486                                            "Error during GSDIR",
1487                                            JOptionPane.ERROR_MESSAGE );
1488             return;
1489         }
1490         catch ( final Exception e ) {
1491             AptxUtil.unexpectedException( e );
1492             return;
1493         }
1494         final Phylogeny result_gene_tree = gsdir.getMinDuplicationsSumGeneTree();
1495         result_gene_tree.setRerootable( false );
1496         result_gene_tree.clearHashIdToNodeMap();
1497         result_gene_tree.recalculateNumberOfExternalDescendants( true );
1498         PhylogenyMethods.orderAppearance( result_gene_tree.getRoot(), true, true, DESCENDANT_SORT_PRIORITY.NODE_NAME );
1499         _mainpanel.addPhylogenyInNewTab( result_gene_tree, getConfiguration(), "gene tree", null );
1500         getMainPanel().getControlPanel().setShowEvents( true );
1501         showWhole();
1502         final int selected = _mainpanel.getTabbedPane().getSelectedIndex();
1503         _mainpanel.addPhylogenyInNewTab( species_tree, getConfiguration(), "species tree", null );
1504         showWhole();
1505         _mainpanel.getTabbedPane().setSelectedIndex( selected );
1506         showWhole();
1507         _mainpanel.getCurrentTreePanel().setEdited( true );
1508         final int poly = PhylogenyMethods.countNumberOfPolytomies( species_tree );
1509         if ( gsdir.getStrippedExternalGeneTreeNodes().size() > 0 ) {
1510             JOptionPane.showMessageDialog( this,
1511                                            "Minimal duplications: " + gsdir.getMinDuplicationsSum() + "\n"
1512                                                    + "Speciations: " + gsdir.getSpeciationsSum() + "\n"
1513                                                    + "Stripped gene tree nodes: "
1514                                                    + gsdir.getStrippedExternalGeneTreeNodes().size() + "\n"
1515                                                    + "Taxonomy linkage based on: " + gsdir.getTaxCompBase() + "\n"
1516                                                    + "Number of polytomies in species tree used: " + poly + "\n",
1517                                            "GSDIR successfully completed",
1518                                            JOptionPane.WARNING_MESSAGE );
1519         }
1520         else {
1521             JOptionPane.showMessageDialog( this,
1522                                            "Minimal duplications: " + gsdir.getMinDuplicationsSum() + "\n"
1523                                                    + "Speciations: " + gsdir.getSpeciationsSum() + "\n"
1524                                                    + "Stripped gene tree nodes: "
1525                                                    + gsdir.getStrippedExternalGeneTreeNodes().size() + "\n"
1526                                                    + "Taxonomy linkage based on: " + gsdir.getTaxCompBase() + "\n"
1527                                                    + "Number of polytomies in species tree used: " + poly + "\n",
1528                                            "GSDIR successfully completed",
1529                                            JOptionPane.INFORMATION_MESSAGE );
1530         }
1531     }
1532
1533     void executeLineageInference() {
1534         if ( ( _mainpanel.getCurrentPhylogeny() == null ) || ( _mainpanel.getCurrentPhylogeny().isEmpty() ) ) {
1535             return;
1536         }
1537         if ( !_mainpanel.getCurrentPhylogeny().isRooted() ) {
1538             JOptionPane.showMessageDialog( this,
1539                                            "Phylogeny is not rooted.",
1540                                            "Cannot infer ancestral taxonomies",
1541                                            JOptionPane.ERROR_MESSAGE );
1542             return;
1543         }
1544         final AncestralTaxonomyInferrer inferrer = new AncestralTaxonomyInferrer( this,
1545                                                                                   _mainpanel.getCurrentTreePanel(),
1546                                                                                   _mainpanel.getCurrentPhylogeny()
1547                                                                                           .copy() );
1548         new Thread( inferrer ).start();
1549     }
1550
1551     boolean GAndSDoHaveMoreThanOneSpeciesInComman( final Phylogeny gene_tree ) {
1552         if ( ( gene_tree == null ) || gene_tree.isEmpty() ) {
1553             JOptionPane.showMessageDialog( this,
1554                                            "Gene tree and species tree have no species in common.",
1555                                            "Error during SDI",
1556                                            JOptionPane.ERROR_MESSAGE );
1557             return false;
1558         }
1559         else if ( gene_tree.getNumberOfExternalNodes() < 2 ) {
1560             JOptionPane.showMessageDialog( this,
1561                                            "Gene tree and species tree have only one species in common.",
1562                                            "Error during SDI",
1563                                            JOptionPane.ERROR_MESSAGE );
1564             return false;
1565         }
1566         else {
1567             return true;
1568         }
1569     }
1570
1571     ControlPanel getControlPanel() {
1572         return getMainPanel().getControlPanel();
1573     }
1574
1575     File getCurrentDir() {
1576         if ( ( _current_dir == null ) || !_current_dir.canRead() ) {
1577             if ( ForesterUtil.isWindows() ) {
1578                 try {
1579                     _current_dir = new File( WindowsUtils.getCurrentUserDesktopPath() );
1580                 }
1581                 catch ( final Exception e ) {
1582                     _current_dir = null;
1583                 }
1584             }
1585         }
1586         if ( ( _current_dir == null ) || !_current_dir.canRead() ) {
1587             if ( System.getProperty( "user.home" ) != null ) {
1588                 _current_dir = new File( System.getProperty( "user.home" ) );
1589             }
1590             else if ( System.getProperty( "user.dir" ) != null ) {
1591                 _current_dir = new File( System.getProperty( "user.dir" ) );
1592             }
1593         }
1594         return _current_dir;
1595     }
1596
1597     TreePanel getCurrentTreePanel() {
1598         return getMainPanel().getCurrentTreePanel();
1599     }
1600
1601     JMenu getHelpMenu() {
1602         return _help_jmenu;
1603     }
1604
1605     JCheckBoxMenuItem getlabelDirectionCbmi() {
1606         return _label_direction_cbmi;
1607     }
1608
1609     JMenuBar getMenuBarOfMainFrame() {
1610         return _jmenubar;
1611     }
1612
1613     final Phylogeny getSpeciesTree() {
1614         return _species_tree;
1615     }
1616
1617     void initializeTypeMenu( final Options options ) {
1618         setTypeMenuToAllUnselected();
1619         switch ( options.getPhylogenyGraphicsType() ) {
1620             case CONVEX:
1621                 _convex_type_cbmi.setSelected( true );
1622                 break;
1623             case CURVED:
1624                 _curved_type_cbmi.setSelected( true );
1625                 break;
1626             case EURO_STYLE:
1627                 _euro_type_cbmi.setSelected( true );
1628                 break;
1629             case ROUNDED:
1630                 _rounded_type_cbmi.setSelected( true );
1631                 break;
1632             case TRIANGULAR:
1633                 _triangular_type_cbmi.setSelected( true );
1634                 break;
1635             case UNROOTED:
1636                 _unrooted_type_cbmi.setSelected( true );
1637                 break;
1638             case CIRCULAR:
1639                 _circular_type_cbmi.setSelected( true );
1640                 break;
1641             default:
1642                 _rectangular_type_cbmi.setSelected( true );
1643                 break;
1644         }
1645     }
1646
1647     boolean isOKforSDI( final boolean species_tree_has_to_binary, final boolean gene_tree_has_to_binary ) {
1648         if ( ( _mainpanel.getCurrentPhylogeny() == null ) || _mainpanel.getCurrentPhylogeny().isEmpty() ) {
1649             return false;
1650         }
1651         else if ( ( getSpeciesTree() == null ) || getSpeciesTree().isEmpty() ) {
1652             JOptionPane.showMessageDialog( this,
1653                                            "No species tree loaded",
1654                                            "Cannot execute GSDI",
1655                                            JOptionPane.ERROR_MESSAGE );
1656             return false;
1657         }
1658         else if ( species_tree_has_to_binary && !getSpeciesTree().isCompletelyBinary() ) {
1659             JOptionPane.showMessageDialog( this,
1660                                            "Species tree is not completely binary",
1661                                            "Cannot execute GSDI",
1662                                            JOptionPane.ERROR_MESSAGE );
1663             return false;
1664         }
1665         else if ( gene_tree_has_to_binary && !_mainpanel.getCurrentPhylogeny().isCompletelyBinary() ) {
1666             JOptionPane.showMessageDialog( this,
1667                                            "Gene tree is not completely binary",
1668                                            "Cannot execute GSDI",
1669                                            JOptionPane.ERROR_MESSAGE );
1670             return false;
1671         }
1672         else {
1673             return true;
1674         }
1675     }
1676
1677     boolean isSubtreeDisplayed() {
1678         if ( getCurrentTreePanel() != null ) {
1679             if ( getCurrentTreePanel().isCurrentTreeIsSubtree() ) {
1680                 JOptionPane
1681                         .showMessageDialog( this,
1682                                             "This operation can only be performed on a complete tree, not on the currently displayed sub-tree only.",
1683                                             "Operation can not be exectuted on a sub-tree",
1684                                             JOptionPane.WARNING_MESSAGE );
1685                 return true;
1686             }
1687         }
1688         return false;
1689     }
1690
1691     void midpointRoot() {
1692         if ( _mainpanel.getCurrentTreePanel() != null ) {
1693             _mainpanel.getCurrentTreePanel().midpointRoot();
1694         }
1695     }
1696
1697     void readPhylogeniesFromWebservice( final int i ) {
1698         final UrlTreeReader reader = new UrlTreeReader( this, i );
1699         new Thread( reader ).start();
1700     }
1701
1702     void removeAllTextFrames() {
1703         for( final TextFrame tf : _textframes ) {
1704             if ( tf != null ) {
1705                 tf.close();
1706             }
1707         }
1708         _textframes.clear();
1709     }
1710
1711     void resetSearch() {
1712         getMainPanel().getCurrentTreePanel().setFoundNodes0( null );
1713         getMainPanel().getCurrentTreePanel().setFoundNodes1( null );
1714         getMainPanel().getControlPanel().setSearchFoundCountsOnLabel0( 0 );
1715         getMainPanel().getControlPanel().getSearchFoundCountsLabel0().setVisible( false );
1716         getMainPanel().getControlPanel().getSearchTextField0().setText( "" );
1717         getMainPanel().getControlPanel().getSearchResetButton0().setEnabled( false );
1718         getMainPanel().getControlPanel().getSearchResetButton0().setVisible( false );
1719         getMainPanel().getControlPanel().setSearchFoundCountsOnLabel1( 0 );
1720         getMainPanel().getControlPanel().getSearchFoundCountsLabel1().setVisible( false );
1721         getMainPanel().getControlPanel().getSearchTextField1().setText( "" );
1722         getMainPanel().getControlPanel().getSearchResetButton1().setEnabled( false );
1723         getMainPanel().getControlPanel().getSearchResetButton1().setVisible( false );
1724     }
1725
1726     void setConfiguration( final Configuration configuration ) {
1727         _configuration = configuration;
1728     }
1729
1730     void setCurrentDir( final File current_dir ) {
1731         _current_dir = current_dir;
1732     }
1733
1734     void setInferenceManager( final InferenceManager i ) {
1735         _inference_manager = i;
1736     }
1737
1738     void setOptions( final Options options ) {
1739         _options = options;
1740     }
1741
1742     void setSelectedTypeInTypeMenu( final PHYLOGENY_GRAPHICS_TYPE type ) {
1743         setTypeMenuToAllUnselected();
1744         switch ( type ) {
1745             case CIRCULAR:
1746                 _circular_type_cbmi.setSelected( true );
1747                 break;
1748             case CONVEX:
1749                 _convex_type_cbmi.setSelected( true );
1750                 break;
1751             case CURVED:
1752                 _curved_type_cbmi.setSelected( true );
1753                 break;
1754             case EURO_STYLE:
1755                 _euro_type_cbmi.setSelected( true );
1756                 break;
1757             case ROUNDED:
1758                 _rounded_type_cbmi.setSelected( true );
1759                 break;
1760             case RECTANGULAR:
1761                 _rectangular_type_cbmi.setSelected( true );
1762                 break;
1763             case TRIANGULAR:
1764                 _triangular_type_cbmi.setSelected( true );
1765                 break;
1766             case UNROOTED:
1767                 _unrooted_type_cbmi.setSelected( true );
1768                 break;
1769             default:
1770                 throw new IllegalArgumentException( "unknown type: " + type );
1771         }
1772     }
1773
1774     final void setSpeciesTree( final Phylogeny species_tree ) {
1775         _species_tree = species_tree;
1776     }
1777
1778     void setTypeMenuToAllUnselected() {
1779         _convex_type_cbmi.setSelected( false );
1780         _curved_type_cbmi.setSelected( false );
1781         _euro_type_cbmi.setSelected( false );
1782         _rounded_type_cbmi.setSelected( false );
1783         _triangular_type_cbmi.setSelected( false );
1784         _rectangular_type_cbmi.setSelected( false );
1785         _unrooted_type_cbmi.setSelected( false );
1786         _circular_type_cbmi.setSelected( false );
1787     }
1788
1789     void switchColors() {
1790         final TreeColorSet colorset = _mainpanel.getTreeColorSet();
1791         final ColorSchemeChooser csc = new ColorSchemeChooser( getMainPanel(), colorset );
1792         csc.setVisible( true );
1793     }
1794
1795     void taxColor() {
1796         if ( _mainpanel.getCurrentTreePanel() != null ) {
1797             _mainpanel.getCurrentTreePanel().taxColor();
1798         }
1799     }
1800
1801     void typeChanged( final Object o ) {
1802         updateTypeCheckboxes( getOptions(), o );
1803         updateOptions( getOptions() );
1804         if ( getCurrentTreePanel() != null ) {
1805             final PHYLOGENY_GRAPHICS_TYPE previous_type = getCurrentTreePanel().getPhylogenyGraphicsType();
1806             final PHYLOGENY_GRAPHICS_TYPE new_type = getOptions().getPhylogenyGraphicsType();
1807             if ( ( ( previous_type == PHYLOGENY_GRAPHICS_TYPE.UNROOTED ) && ( new_type != PHYLOGENY_GRAPHICS_TYPE.UNROOTED ) )
1808                     || ( ( previous_type == PHYLOGENY_GRAPHICS_TYPE.CIRCULAR ) && ( new_type != PHYLOGENY_GRAPHICS_TYPE.CIRCULAR ) )
1809                     || ( ( previous_type != PHYLOGENY_GRAPHICS_TYPE.UNROOTED ) && ( new_type == PHYLOGENY_GRAPHICS_TYPE.UNROOTED ) )
1810                     || ( ( previous_type != PHYLOGENY_GRAPHICS_TYPE.CIRCULAR ) && ( new_type == PHYLOGENY_GRAPHICS_TYPE.CIRCULAR ) ) ) {
1811                 getCurrentTreePanel().getControlPanel().showWhole();
1812             }
1813             if ( getCurrentTreePanel().isPhyHasBranchLengths() && ( new_type != PHYLOGENY_GRAPHICS_TYPE.CIRCULAR ) ) {
1814                 getCurrentTreePanel().getControlPanel().setDrawPhylogramEnabled( true );
1815             }
1816             else {
1817                 getCurrentTreePanel().getControlPanel().setDrawPhylogramEnabled( false );
1818             }
1819             getCurrentTreePanel().setPhylogenyGraphicsType( getOptions().getPhylogenyGraphicsType() );
1820             updateScreenTextAntialias( getMainPanel().getTreePanels() );
1821             if ( getCurrentTreePanel().getControlPanel().getDynamicallyHideData() != null ) {
1822                 if ( new_type == PHYLOGENY_GRAPHICS_TYPE.UNROOTED ) {
1823                     getCurrentTreePanel().getControlPanel().getDynamicallyHideData().setEnabled( false );
1824                 }
1825                 else {
1826                     getCurrentTreePanel().getControlPanel().getDynamicallyHideData().setEnabled( true );
1827                 }
1828             }
1829         }
1830     }
1831
1832     void updateOptions( final Options options ) {
1833         options.setAntialiasScreen( ( _screen_antialias_cbmi != null ) && _screen_antialias_cbmi.isSelected() );
1834         options.setBackgroundColorGradient( ( _background_gradient_cbmi != null )
1835                 && _background_gradient_cbmi.isSelected() );
1836         options.setShowDomainLabels( ( _show_domain_labels != null ) && _show_domain_labels.isSelected() );
1837         options.setShowAnnotationRefSource( ( _show_annotation_ref_source != null )
1838                 && _show_annotation_ref_source.isSelected() );
1839         options.setAbbreviateScientificTaxonNames( ( _abbreviate_scientific_names != null )
1840                 && _abbreviate_scientific_names.isSelected() );
1841         options.setColorLabelsSameAsParentBranch( ( _color_labels_same_as_parent_branch != null )
1842                 && _color_labels_same_as_parent_branch.isSelected() );
1843         options.setShowDefaultNodeShapesInternal( ( _show_default_node_shapes_internal_cbmi != null )
1844                 && _show_default_node_shapes_internal_cbmi.isSelected() );
1845         options.setShowDefaultNodeShapesExternal( ( _show_default_node_shapes_external_cbmi != null )
1846                 && _show_default_node_shapes_external_cbmi.isSelected() );
1847         options.setShowDefaultNodeShapesForMarkedNodes( ( _show_default_node_shapes_for_marked_cbmi != null )
1848                 && _show_default_node_shapes_for_marked_cbmi.isSelected() );
1849         if ( ( _non_lined_up_cladograms_rbmi != null ) && ( _non_lined_up_cladograms_rbmi.isSelected() ) ) {
1850             options.setCladogramType( CLADOGRAM_TYPE.NON_LINED_UP );
1851         }
1852         else if ( ( _ext_node_dependent_cladogram_rbmi != null ) && ( _ext_node_dependent_cladogram_rbmi.isSelected() ) ) {
1853             options.setCladogramType( CLADOGRAM_TYPE.LINED_UP );
1854         }
1855         options.setSearchCaseSensitive( ( _search_case_senstive_cbmi != null )
1856                 && _search_case_senstive_cbmi.isSelected() );
1857         if ( ( _show_scale_cbmi != null ) && _show_scale_cbmi.isEnabled() ) {
1858             options.setShowScale( _show_scale_cbmi.isSelected() );
1859         }
1860         if ( _label_direction_cbmi != null ) {
1861             if ( _label_direction_cbmi.isSelected() ) {
1862                 options.setNodeLabelDirection( NODE_LABEL_DIRECTION.RADIAL );
1863             }
1864             else {
1865                 options.setNodeLabelDirection( NODE_LABEL_DIRECTION.HORIZONTAL );
1866             }
1867         }
1868         options.setShowOverview( ( _show_overview_cbmi != null ) && _show_overview_cbmi.isSelected() );
1869         options.setShowConfidenceStddev( ( _show_confidence_stddev_cbmi != null )
1870                 && _show_confidence_stddev_cbmi.isSelected() );
1871         if ( ( _color_by_taxonomic_group_cbmi != null ) && _color_by_taxonomic_group_cbmi.isEnabled() ) {
1872             options.setColorByTaxonomicGroup( _color_by_taxonomic_group_cbmi.isSelected() );
1873         }
1874         options.setAntialiasPrint( ( _antialias_print_cbmi != null ) && _antialias_print_cbmi.isSelected() );
1875         if ( ( _use_brackets_for_conf_in_nh_export_cbmi != null )
1876                 && _use_brackets_for_conf_in_nh_export_cbmi.isSelected() ) {
1877             options.setNhConversionSupportValueStyle( NH_CONVERSION_SUPPORT_VALUE_STYLE.IN_SQUARE_BRACKETS );
1878         }
1879         else if ( ( _use_internal_names_for_conf_in_nh_export_cbmi != null )
1880                 && _use_internal_names_for_conf_in_nh_export_cbmi.isSelected() ) {
1881             options.setNhConversionSupportValueStyle( NH_CONVERSION_SUPPORT_VALUE_STYLE.AS_INTERNAL_NODE_NAMES );
1882         }
1883         else {
1884             options.setNhConversionSupportValueStyle( NH_CONVERSION_SUPPORT_VALUE_STYLE.NONE );
1885         }
1886         options.setPrintBlackAndWhite( ( _print_black_and_white_cbmi != null )
1887                 && _print_black_and_white_cbmi.isSelected() );
1888         options.setInternalNumberAreConfidenceForNhParsing( ( _internal_number_are_confidence_for_nh_parsing_cbmi != null )
1889                 && _internal_number_are_confidence_for_nh_parsing_cbmi.isSelected() );
1890         if ( ( _extract_taxonomy_pfam_strict_rbmi != null ) && _extract_taxonomy_pfam_strict_rbmi.isSelected() ) {
1891             options.setTaxonomyExtraction( TAXONOMY_EXTRACTION.PFAM_STYLE_STRICT );
1892         }
1893         else if ( ( _extract_taxonomy_pfam_relaxed_rbmi != null ) && _extract_taxonomy_pfam_relaxed_rbmi.isSelected() ) {
1894             options.setTaxonomyExtraction( TAXONOMY_EXTRACTION.PFAM_STYLE_RELAXED );
1895         }
1896         else if ( ( _extract_taxonomy_agressive_rbmi != null ) && _extract_taxonomy_agressive_rbmi.isSelected() ) {
1897             options.setTaxonomyExtraction( TAXONOMY_EXTRACTION.AGGRESSIVE );
1898         }
1899         else if ( ( _extract_taxonomy_no_rbmi != null ) && _extract_taxonomy_no_rbmi.isSelected() ) {
1900             options.setTaxonomyExtraction( TAXONOMY_EXTRACTION.NO );
1901         }
1902         options.setReplaceUnderscoresInNhParsing( ( _replace_underscores_cbmi != null )
1903                 && _replace_underscores_cbmi.isSelected() );
1904         options.setAllowErrorsInDistanceToParent( ( _allow_errors_in_distance_to_parent_cbmi != null )
1905                 && _allow_errors_in_distance_to_parent_cbmi.isSelected() );
1906         options.setMatchWholeTermsOnly( ( _search_whole_words_only_cbmi != null )
1907                 && _search_whole_words_only_cbmi.isSelected() );
1908         options.setSearchWithRegex( ( _search_with_regex_cbmi != null ) && _search_with_regex_cbmi.isSelected() );
1909         options.setInverseSearchResult( ( _inverse_search_result_cbmi != null )
1910                 && _inverse_search_result_cbmi.isSelected() );
1911         if ( _graphics_export_visible_only_cbmi != null ) {
1912             options.setGraphicsExportVisibleOnly( _graphics_export_visible_only_cbmi.isSelected() );    
1913         }
1914         if ( ( _rectangular_type_cbmi != null ) && _rectangular_type_cbmi.isSelected() ) {
1915             options.setPhylogenyGraphicsType( PHYLOGENY_GRAPHICS_TYPE.RECTANGULAR );
1916         }
1917         else if ( ( _triangular_type_cbmi != null ) && _triangular_type_cbmi.isSelected() ) {
1918             options.setPhylogenyGraphicsType( PHYLOGENY_GRAPHICS_TYPE.TRIANGULAR );
1919         }
1920         else if ( ( _curved_type_cbmi != null ) && _curved_type_cbmi.isSelected() ) {
1921             options.setPhylogenyGraphicsType( PHYLOGENY_GRAPHICS_TYPE.CURVED );
1922         }
1923         else if ( ( _convex_type_cbmi != null ) && _convex_type_cbmi.isSelected() ) {
1924             options.setPhylogenyGraphicsType( PHYLOGENY_GRAPHICS_TYPE.CONVEX );
1925         }
1926         else if ( ( _euro_type_cbmi != null ) && _euro_type_cbmi.isSelected() ) {
1927             options.setPhylogenyGraphicsType( PHYLOGENY_GRAPHICS_TYPE.EURO_STYLE );
1928         }
1929         else if ( ( _rounded_type_cbmi != null ) && _rounded_type_cbmi.isSelected() ) {
1930             options.setPhylogenyGraphicsType( PHYLOGENY_GRAPHICS_TYPE.ROUNDED );
1931         }
1932         else if ( ( _unrooted_type_cbmi != null ) && _unrooted_type_cbmi.isSelected() ) {
1933             options.setPhylogenyGraphicsType( PHYLOGENY_GRAPHICS_TYPE.UNROOTED );
1934         }
1935         else if ( ( _circular_type_cbmi != null ) && _circular_type_cbmi.isSelected() ) {
1936             options.setPhylogenyGraphicsType( PHYLOGENY_GRAPHICS_TYPE.CIRCULAR );
1937         }
1938         if ( ( _right_line_up_domains_cbmi != null ) && _right_line_up_domains_cbmi.isEnabled() ) {
1939             options.setRightLineUpDomains( _right_line_up_domains_cbmi.isSelected() );
1940         }
1941         if ( ( _line_up_renderable_data_cbmi != null ) && _line_up_renderable_data_cbmi.isEnabled() ) {
1942             options.setLineUpRendarableNodeData( _line_up_renderable_data_cbmi.isSelected() );
1943         }
1944         if ( ( _color_all_found_nodes_when_coloring_subtree_cbmi != null ) && _color_all_found_nodes_when_coloring_subtree_cbmi.isEnabled() ) {
1945             options.setColorAllFoundNodesWhenColoringSubtree( _color_all_found_nodes_when_coloring_subtree_cbmi.isSelected() );
1946         }
1947         if ( ( _parse_beast_style_extended_nexus_tags_cbmi != null ) && _parse_beast_style_extended_nexus_tags_cbmi.isEnabled() ) {
1948             options.setParseBeastStyleExtendedNexusTags(_parse_beast_style_extended_nexus_tags_cbmi.isSelected() );
1949         }
1950         if ( ( _collapsed_with_average_height_cbmi != null ) && _collapsed_with_average_height_cbmi.isEnabled() ) {
1951             options.setCollapsedWithAverageHeigh(_collapsed_with_average_height_cbmi.isSelected() );
1952         }
1953         if ( ( _show_abbreviated_labels_for_collapsed_nodes_cbmi != null ) && _show_abbreviated_labels_for_collapsed_nodes_cbmi.isEnabled() ) {
1954             options.setShowAbbreviatedLabelsForCollapsedNodes(_show_abbreviated_labels_for_collapsed_nodes_cbmi.isSelected() );
1955         }
1956         
1957     }
1958
1959     void updateTypeCheckboxes( final Options options, final Object o ) {
1960         setTypeMenuToAllUnselected();
1961         ( ( JCheckBoxMenuItem ) o ).setSelected( true );
1962     }
1963
1964     void viewAsNexus() {
1965         if ( ( _mainpanel.getCurrentPhylogeny() != null ) && !_mainpanel.getCurrentPhylogeny().isEmpty() ) {
1966             String title = "Nexus";
1967             if ( !ForesterUtil.isEmpty( _mainpanel.getCurrentPhylogeny().getName() ) ) {
1968                 title = "\"" + getMainPanel().getCurrentPhylogeny().getName() + "\" in " + title;
1969             }
1970             showTextFrame( _mainpanel.getCurrentPhylogeny().toNexus( getOptions().getNhConversionSupportValueStyle() ),
1971                            title );
1972         }
1973     }
1974
1975     void viewAsNH() {
1976         if ( ( _mainpanel.getCurrentPhylogeny() != null ) && !_mainpanel.getCurrentPhylogeny().isEmpty() ) {
1977             String title = "New Hampshire";
1978             if ( !ForesterUtil.isEmpty( _mainpanel.getCurrentPhylogeny().getName() ) ) {
1979                 title = "\"" + getMainPanel().getCurrentPhylogeny().getName() + "\" in " + title;
1980             }
1981             showTextFrame( _mainpanel.getCurrentPhylogeny().toNewHampshire( getOptions()
1982                                    .getNhConversionSupportValueStyle() ),
1983                            title );
1984         }
1985     }
1986
1987     void viewAsXML() {
1988         if ( ( _mainpanel.getCurrentPhylogeny() != null ) && !_mainpanel.getCurrentPhylogeny().isEmpty() ) {
1989             String title = "phyloXML";
1990             if ( !ForesterUtil.isEmpty( _mainpanel.getCurrentPhylogeny().getName() ) ) {
1991                 title = "\"" + getMainPanel().getCurrentPhylogeny().getName() + "\" in " + title;
1992             }
1993             showTextFrame( _mainpanel.getCurrentPhylogeny().toPhyloXML( 0 ), title );
1994         }
1995     }
1996
1997     private static void cycleNodeDataReturn( final Options op, final Configuration conf ) {
1998         switch ( op.getExtDescNodeDataToReturn() ) {
1999             case UNKNOWN:
2000                 op.setExtDescNodeDataToReturn( NodeDataField.DOMAINS_ALL );
2001                 break;
2002             case DOMAINS_ALL:
2003                 op.setExtDescNodeDataToReturn( NodeDataField.DOMAINS_COLLAPSED_PER_PROTEIN );
2004                 break;
2005             case DOMAINS_COLLAPSED_PER_PROTEIN:
2006                 op.setExtDescNodeDataToReturn( NodeDataField.SEQ_ANNOTATIONS );
2007                 break;
2008             case SEQ_ANNOTATIONS:
2009                 op.setExtDescNodeDataToReturn( NodeDataField.GO_TERM_IDS );
2010                 break;
2011             case GO_TERM_IDS:
2012                 op.setExtDescNodeDataToReturn( NodeDataField.SEQUENCE_MOL_SEQ_FASTA );
2013                 break;
2014             case SEQUENCE_MOL_SEQ_FASTA:
2015                 if ( ( conf != null ) && ( conf.getExtDescNodeDataToReturn() != null )
2016                         && ( conf.getExtDescNodeDataToReturn() != NodeDataField.DOMAINS_ALL )
2017                         && ( conf.getExtDescNodeDataToReturn() != NodeDataField.DOMAINS_COLLAPSED_PER_PROTEIN )
2018                         && ( conf.getExtDescNodeDataToReturn() != NodeDataField.SEQ_ANNOTATIONS )
2019                         && ( conf.getExtDescNodeDataToReturn() != NodeDataField.GO_TERM_IDS )
2020                         && ( conf.getExtDescNodeDataToReturn() != NodeDataField.SEQUENCE_MOL_SEQ_FASTA ) ) {
2021                     op.setExtDescNodeDataToReturn( conf.getExtDescNodeDataToReturn() );
2022                 }
2023                 else {
2024                     op.setExtDescNodeDataToReturn( NodeDataField.UNKNOWN );
2025                 }
2026                 break;
2027             default:
2028                 op.setExtDescNodeDataToReturn( NodeDataField.UNKNOWN );
2029         }
2030     }
2031
2032     /**
2033      * Display the about box.
2034      */
2035     void about() {
2036         final StringBuffer about = new StringBuffer( "Archaeopteryx\nVersion " + AptxConstants.VERSION + "\n" );
2037         about.append( "Copyright (C) 2016 Christian M Zmasek\n" );
2038         about.append( "All Rights Reserved\n" );
2039         about.append( "License: GNU Lesser General Public License (LGPL)\n" );
2040         about.append( "Last modified: " + AptxConstants.PRG_DATE + "\n" );
2041         about.append( "Based on: " + ForesterUtil.getForesterLibraryInformation() + "\n" );
2042         
2043         if  ( _configuration.isCouldReadConfigFile() ) {
2044             about.append( "Using configuration file: " + _configuration.config_filename + "\n" );
2045         }
2046         else {
2047             about.append( "Not using a configuration file\n" );
2048         }
2049         
2050         about.append( "phyloXML version : " + ForesterConstants.PHYLO_XML_VERSION + "\n" );
2051         about.append( "phyloXML location: " + ForesterConstants.PHYLO_XML_LOCATION + "\n" );
2052         if ( !ForesterUtil.isEmpty( ForesterUtil.JAVA_VERSION ) && !ForesterUtil.isEmpty( ForesterUtil.JAVA_VENDOR ) ) {
2053             about.append( "[your Java version: " + ForesterUtil.JAVA_VERSION + " " + ForesterUtil.JAVA_VENDOR + "]\n" );
2054         }
2055         if ( !ForesterUtil.isEmpty( ForesterUtil.OS_NAME ) && !ForesterUtil.isEmpty( ForesterUtil.OS_ARCH )
2056                 && !ForesterUtil.isEmpty( ForesterUtil.OS_VERSION ) ) {
2057             about.append( "[your OS: " + ForesterUtil.OS_NAME + " " + ForesterUtil.OS_ARCH + " "
2058                     + ForesterUtil.OS_VERSION + "]\n" );
2059         }
2060         final Runtime rt = java.lang.Runtime.getRuntime();
2061         final long free_memory = rt.freeMemory() / 1000000;
2062         final long total_memory = rt.totalMemory() / 1000000;
2063         about.append( "[free memory: " + free_memory + "MB, total memory: " + total_memory + "MB]\n" );
2064         about.append( "[locale: " + Locale.getDefault() + "]\n" );
2065         about.append( "References:\n" );
2066         about.append( AptxConstants.PHYLOXML_REFERENCE_SHORT + "\n" );
2067         about.append( "For more information & download:\n" );
2068         about.append( AptxConstants.APTX_WEB_SITE + "\n" );
2069         about.append( "Documentation:\n" );
2070         about.append( AptxConstants.APTX_DOC_SITE + "\n" );
2071         about.append( "Comments: " + AptxConstants.AUTHOR_EMAIL );
2072         JOptionPane.showMessageDialog( null, about, AptxConstants.PRG_NAME, JOptionPane.PLAIN_MESSAGE );
2073     }
2074
2075     static void chooseNodeSize( final Options options, final Component parent ) {
2076         final String s = ( String ) JOptionPane.showInputDialog( parent,
2077                                                                  "Please enter the default size for node shapes.\n"
2078                                                                          + "[current value: "
2079                                                                          + options.getDefaultNodeShapeSize() + "]\n",
2080                                                                  "Node Shape Size",
2081                                                                  JOptionPane.QUESTION_MESSAGE,
2082                                                                  null,
2083                                                                  null,
2084                                                                  options.getDefaultNodeShapeSize() );
2085         if ( !ForesterUtil.isEmpty( s ) ) {
2086             boolean success = true;
2087             double m = 0.0;
2088             final String m_str = s.trim();
2089             if ( !ForesterUtil.isEmpty( m_str ) ) {
2090                 try {
2091                     m = Double.parseDouble( m_str );
2092                 }
2093                 catch ( final Exception ex ) {
2094                     success = false;
2095                 }
2096             }
2097             else {
2098                 success = false;
2099             }
2100             if ( success && ( m >= 0.0 ) ) {
2101                 final short size = ForesterUtil.roundToShort( m );
2102                 if ( size >= 0.0 ) {
2103                     options.setDefaultNodeShapeSize( size );
2104                 }
2105             }
2106         }
2107     }
2108
2109     static String createCurrentFontDesc( final TreeFontSet tree_font_set ) {
2110         return tree_font_set.getLargeFont().getFamily() + " " + tree_font_set.getLargeFont().getSize();
2111     }
2112
2113     static JMenu createMenu( final String title, final Configuration conf ) {
2114         final JMenu jmenu = new JMenu( title );
2115         if ( !conf.isUseNativeUI() ) {
2116             jmenu.setFont( MainFrame.menu_font );
2117             jmenu.setBackground( conf.getGuiMenuBackgroundColor() );
2118             jmenu.setForeground( conf.getGuiMenuTextColor() );
2119         }
2120         return jmenu;
2121     }
2122
2123     static JMenuItem customizeMenuItemAsLabel( final JMenuItem label, final Configuration configuration ) {
2124         label.setFont( MainFrame.menu_font.deriveFont( Font.BOLD ) );
2125         if ( !configuration.isUseNativeUI() ) {
2126             label.setBackground( configuration.getGuiMenuBackgroundColor() );
2127             label.setForeground( configuration.getGuiMenuTextColor() );
2128             label.setOpaque( true );
2129         }
2130         label.setSelected( false );
2131         label.setEnabled( false );
2132         return label;
2133     }
2134
2135     static void cycleNodeFill( final Options op ) {
2136         switch ( op.getDefaultNodeFill() ) {
2137             case GRADIENT:
2138                 op.setDefaultNodeFill( NodeFill.SOLID );
2139                 break;
2140             case NONE:
2141                 op.setDefaultNodeFill( NodeFill.GRADIENT );
2142                 break;
2143             case SOLID:
2144                 op.setDefaultNodeFill( NodeFill.NONE );
2145                 break;
2146             default:
2147                 throw new RuntimeException( "unknown fill: " + op.getDefaultNodeFill() );
2148         }
2149     }
2150
2151     static void cycleNodeShape( final Options op ) {
2152         switch ( op.getDefaultNodeShape() ) {
2153             case CIRCLE:
2154                 op.setDefaultNodeShape( NodeShape.RECTANGLE );
2155                 break;
2156             case RECTANGLE:
2157                 op.setDefaultNodeShape( NodeShape.CIRCLE );
2158                 break;
2159             default:
2160                 throw new RuntimeException( "unknown shape: " + op.getDefaultNodeShape() );
2161         }
2162     }
2163
2164     static void cycleOverview( final Options op, final TreePanel tree_panel ) {
2165         switch ( op.getOvPlacement() ) {
2166             case LOWER_LEFT:
2167                 op.setOvPlacement( Options.OVERVIEW_PLACEMENT_TYPE.UPPER_LEFT );
2168                 break;
2169             case LOWER_RIGHT:
2170                 op.setOvPlacement( Options.OVERVIEW_PLACEMENT_TYPE.LOWER_LEFT );
2171                 break;
2172             case UPPER_LEFT:
2173                 op.setOvPlacement( Options.OVERVIEW_PLACEMENT_TYPE.UPPER_RIGHT );
2174                 break;
2175             case UPPER_RIGHT:
2176                 op.setOvPlacement( Options.OVERVIEW_PLACEMENT_TYPE.LOWER_RIGHT );
2177                 break;
2178             default:
2179                 throw new RuntimeException( "unknown placement: " + op.getOvPlacement() );
2180         }
2181         if ( tree_panel != null ) {
2182             tree_panel.updateOvSettings();
2183         }
2184     }
2185
2186     static void exceptionOccuredDuringSaveAs( final Exception e, final TreePanel tp, final Component comp ) {
2187         try {
2188             tp.setArrowCursor();
2189         }
2190         catch ( final Exception ex ) {
2191             // Do nothing.
2192         }
2193         JOptionPane.showMessageDialog( comp, "Exception" + e, "Error during File|SaveAs", JOptionPane.ERROR_MESSAGE );
2194     }
2195
2196     static void print( final TreePanel tp, final Options op, final Component c ) {
2197         if ( ( tp == null ) || ( tp.getPhylogeny() == null ) || tp.getPhylogeny().isEmpty() ) {
2198             return;
2199         }
2200         final String job_name = AptxConstants.PRG_NAME;
2201         boolean error = false;
2202         String printer_name = null;
2203         try {
2204             printer_name = Printer.print( tp, job_name );
2205         }
2206         catch ( final Exception e ) {
2207             error = true;
2208             JOptionPane.showMessageDialog( c, e.getMessage(), "Printing Error", JOptionPane.ERROR_MESSAGE );
2209         }
2210         if ( !error && ( printer_name != null ) ) {
2211             String msg = "Printing data sent to printer";
2212             if ( printer_name.length() > 1 ) {
2213                 msg += " [" + printer_name + "]";
2214             }
2215             JOptionPane.showMessageDialog( c, msg, "Printing...", JOptionPane.INFORMATION_MESSAGE );
2216         }
2217         if ( !op.isPrintUsingActualSize() ) {
2218             tp.getControlPanel().showWhole();
2219         }
2220     }
2221
2222     static void printPhylogenyToPdf( final String file_name,
2223                                      final Options opts,
2224                                      final TreePanel tp,
2225                                      final Component comp ) {
2226        
2227         String pdf_written_to = "";
2228         boolean error = false;
2229         try {
2230             if ( opts.isPrintUsingActualSize() ) {
2231                 pdf_written_to = PdfExporter.writePhylogenyToPdf( file_name, tp, tp.getWidth() , tp.getHeight()  );
2232             }
2233             else {
2234                 // Never false.
2235             }
2236         }
2237         catch ( final IOException e ) {
2238             error = true;
2239             JOptionPane.showMessageDialog( comp, e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE );
2240         }
2241         if ( !error ) {
2242             if ( !ForesterUtil.isEmpty( pdf_written_to ) ) {
2243                 JOptionPane.showMessageDialog( comp,
2244                                                "Wrote PDF to: " + pdf_written_to,
2245                                                "Information",
2246                                                JOptionPane.INFORMATION_MESSAGE );
2247             }
2248             else {
2249                 JOptionPane.showMessageDialog( comp,
2250                                                "There was an unknown problem when attempting to write to PDF file: \""
2251                                                        + file_name + "\"",
2252                                                "Error",
2253                                                JOptionPane.ERROR_MESSAGE );
2254             }
2255         }
2256         if ( !opts.isPrintUsingActualSize() ) {
2257             tp.getControlPanel().showWhole();
2258         }
2259     }
2260
2261     static void setCycleDataReturnMenuItem( final JMenuItem mi, final Options options ) {
2262         if ( ( options != null ) && ( options.getExtDescNodeDataToReturn() != null ) ) {
2263             mi.setText( "Cycle Node Return Data... (current: " + options.getExtDescNodeDataToReturn().toString() + ")" );
2264         }
2265         else {
2266             mi.setText( "Cycle Node Return Data..." );
2267         }
2268     }
2269
2270     static void setCycleNodeFillMenuItem( final JMenuItem mi, final Options options ) {
2271         if ( ( options != null ) && ( options.getDefaultNodeFill() != null ) ) {
2272             mi.setText( "Cycle Node Shape Fill Type... (current: "
2273                     + options.getDefaultNodeFill().toString().toLowerCase() + ")" );
2274         }
2275         else {
2276             mi.setText( "Cycle Node Shape Fill Type..." );
2277         }
2278     }
2279
2280     static void setCycleNodeShapeMenuItem( final JMenuItem mi, final Options options ) {
2281         if ( ( options != null ) && ( options.getDefaultNodeShape() != null ) ) {
2282             mi.setText( "Cycle Node Shape Fill Type... (current: "
2283                     + options.getDefaultNodeShape().toString().toLowerCase() + ")" );
2284         }
2285         else {
2286             mi.setText( "Cycle Node Shape Fill Type..." );
2287         }
2288     }
2289
2290     static void setOvPlacementColorChooseMenuItem( final JMenuItem mi, final Options options ) {
2291         if ( ( options != null ) && ( options.getOvPlacement() != null ) ) {
2292             mi.setText( "Cycle Overview Placement... (current: " + options.getOvPlacement() + ")" );
2293         }
2294         else {
2295             mi.setText( "Cycle Overview Placement..." );
2296         }
2297     }
2298
2299     static void setTextColorChooseMenuItem( final JMenuItem mi, final TreePanel tree_panel ) {
2300         if ( ( tree_panel != null ) && ( tree_panel.getTreeColorSet() != null ) ) {
2301             mi.setText( "Select Color Scheme... (current: " + tree_panel.getTreeColorSet().getCurrentColorSchemeName()
2302                     + ")" );
2303         }
2304         else {
2305             mi.setText( "Select Color Scheme..." );
2306         }
2307     }
2308
2309     static void setTextForFontChooserMenuItem( final JMenuItem mi, final String font_desc ) {
2310         mi.setText( "Select Default Font... (current: " + font_desc + ")" );
2311     }
2312
2313     static void setTextForPdfLineWidthChooserMenuItem( final JMenuItem mi, final Options o ) {
2314         mi.setText( "Enter Default Line Width for PDF Export... (current: " + o.getPrintLineWidth() + ")" );
2315     }
2316
2317     static void setTextMinSupportMenuItem( final JMenuItem mi, final Options options, final TreePanel current_tree_panel ) {
2318         if ( ( current_tree_panel == null ) || ( current_tree_panel.getPhylogeny() == null ) ) {
2319             mi.setEnabled( true );
2320         }
2321         else if ( AptxUtil.isHasAtLeastOneBranchWithSupportValues( current_tree_panel.getPhylogeny() ) ) {
2322             mi.setEnabled( true );
2323         }
2324         else {
2325             mi.setEnabled( false );
2326         }
2327         mi.setText( "Enter Min Confidence Value... (current: " + options.getMinConfidenceValue() + ")" );
2328     }
2329
2330     static void setTextNodeSizeMenuItem( final JMenuItem mi, final Options options ) {
2331         mi.setText( "Enter Default Node Shape Size... (current: " + options.getDefaultNodeShapeSize() + ")" );
2332     }
2333
2334     static void updateScreenTextAntialias( final List<TreePanel> treepanels ) {
2335         for( final TreePanel tree_panel : treepanels ) {
2336             tree_panel.setTextAntialias();
2337         }
2338     }
2339
2340     static boolean writeAsNewHampshire( final TreePanel tp, final Options op, boolean exception, final File file ) {
2341         try {
2342             final PhylogenyWriter writer = new PhylogenyWriter();
2343             writer.toNewHampshire( tp.getPhylogeny(), true, op.getNhConversionSupportValueStyle(), file );
2344         }
2345         catch ( final Exception e ) {
2346             exception = true;
2347             exceptionOccuredDuringSaveAs( e, tp, tp );
2348         }
2349         return exception;
2350     }
2351
2352     static boolean writeAsNexus( final TreePanel tp, final Options op, boolean exception, final File file ) {
2353         try {
2354             final PhylogenyWriter writer = new PhylogenyWriter();
2355             writer.toNexus( file, tp.getPhylogeny(), op.getNhConversionSupportValueStyle() );
2356         }
2357         catch ( final Exception e ) {
2358             exception = true;
2359             exceptionOccuredDuringSaveAs( e, tp, tp );
2360         }
2361         return exception;
2362     }
2363
2364     static boolean writeAsPhyloXml( final TreePanel tp, final Options op, boolean exception, final File file ) {
2365         try {
2366             final PhylogenyWriter writer = new PhylogenyWriter();
2367             writer.toPhyloXML( file, tp.getPhylogeny(), 0 );
2368         }
2369         catch ( final Exception e ) {
2370             exception = true;
2371             exceptionOccuredDuringSaveAs( e, tp, tp );
2372         }
2373         return exception;
2374     }
2375
2376     static void writePhylogenyToGraphicsFile( final String file_name,
2377                                               final GraphicsExportType type,
2378                                               final MainPanel mp,
2379                                               final Component comp,
2380                                               final Container contentpane ) {
2381         mp.getCurrentTreePanel().calcParametersForPainting( mp.getCurrentTreePanel().getWidth(),
2382                                                             mp.getCurrentTreePanel().getHeight() );
2383         String file_written_to = "";
2384         boolean error = false;
2385         try {
2386             file_written_to = AptxUtil.writePhylogenyToGraphicsFile( file_name,
2387                                                                      mp.getCurrentTreePanel().getWidth(),
2388                                                                      mp.getCurrentTreePanel().getHeight(),
2389                                                                      mp.getCurrentTreePanel(),
2390                                                                      mp.getControlPanel(),
2391                                                                      type,
2392                                                                      mp.getOptions() );
2393         }
2394         catch ( final IOException e ) {
2395             error = true;
2396             JOptionPane.showMessageDialog( comp, e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE );
2397         }
2398         if ( !error ) {
2399             if ( ( file_written_to != null ) && ( file_written_to.length() > 0 ) ) {
2400                 JOptionPane.showMessageDialog( comp,
2401                                                "Wrote image to: " + file_written_to,
2402                                                "Graphics Export",
2403                                                JOptionPane.INFORMATION_MESSAGE );
2404             }
2405             else {
2406                 JOptionPane.showMessageDialog( comp,
2407                                                "There was an unknown problem when attempting to write to an image file: \""
2408                                                        + file_name + "\"",
2409                                                "Error",
2410                                                JOptionPane.ERROR_MESSAGE );
2411             }
2412         }
2413         contentpane.repaint();
2414     }
2415
2416     static File writeToFile( final Phylogeny t,
2417                              final MainPanel mp,
2418                              final JFileChooser save_filechooser,
2419                              final File current_dir,
2420                              final Container contentpane,
2421                              final Component comp ) {
2422         File new_file = null;
2423         if ( t == null ) {
2424             return null;
2425         }
2426         String initial_filename = null;
2427         if ( mp.getCurrentTreePanel().getTreeFile() != null ) {
2428             try {
2429                 initial_filename = mp.getCurrentTreePanel().getTreeFile().getCanonicalPath();
2430             }
2431             catch ( final IOException e ) {
2432                 initial_filename = null;
2433             }
2434         }
2435         if ( !ForesterUtil.isEmpty( initial_filename ) ) {
2436             save_filechooser.setSelectedFile( new File( initial_filename ) );
2437         }
2438         else {
2439             save_filechooser.setSelectedFile( new File( "" ) );
2440         }
2441         final File my_dir = current_dir;
2442         if ( my_dir != null ) {
2443             save_filechooser.setCurrentDirectory( my_dir );
2444         }
2445         final int result = save_filechooser.showSaveDialog( contentpane );
2446         final File file = save_filechooser.getSelectedFile();
2447         new_file = save_filechooser.getCurrentDirectory();
2448         boolean exception = false;
2449         if ( ( file != null ) && ( result == JFileChooser.APPROVE_OPTION ) ) {
2450             if ( file.exists() ) {
2451                 final int i = JOptionPane.showConfirmDialog( comp,
2452                                                              file + " already exists.\nOverwrite?",
2453                                                              "Overwrite?",
2454                                                              JOptionPane.OK_CANCEL_OPTION,
2455                                                              JOptionPane.QUESTION_MESSAGE );
2456                 if ( i != JOptionPane.OK_OPTION ) {
2457                     return null;
2458                 }
2459                 else {
2460                     final File to = new File( file.getAbsoluteFile().toString() + AptxConstants.BACKUP_FILE_SUFFIX );
2461                     try {
2462                         ForesterUtil.copyFile( file, to );
2463                     }
2464                     catch ( final Exception e ) {
2465                         JOptionPane.showMessageDialog( comp,
2466                                                        "Failed to create backup copy " + to,
2467                                                        "Failed to Create Backup Copy",
2468                                                        JOptionPane.WARNING_MESSAGE );
2469                     }
2470                     try {
2471                         file.delete();
2472                     }
2473                     catch ( final Exception e ) {
2474                         JOptionPane.showMessageDialog( comp,
2475                                                        "Failed to delete: " + file,
2476                                                        "Failed to Delete",
2477                                                        JOptionPane.WARNING_MESSAGE );
2478                     }
2479                 }
2480             }
2481             if ( save_filechooser.getFileFilter() == MainFrame.nhfilter ) {
2482                 exception = writeAsNewHampshire( mp.getCurrentTreePanel(), mp.getOptions(), exception, file );
2483             }
2484             else if ( save_filechooser.getFileFilter() == MainFrame.xmlfilter ) {
2485                 exception = writeAsPhyloXml( mp.getCurrentTreePanel(), mp.getOptions(), exception, file );
2486             }
2487             else if ( save_filechooser.getFileFilter() == MainFrame.nexusfilter ) {
2488                 exception = writeAsNexus( mp.getCurrentTreePanel(), mp.getOptions(), exception, file );
2489             }
2490             // "*.*":
2491             else {
2492                 final String file_name = file.getName().trim().toLowerCase();
2493                 if ( file_name.endsWith( ".nh" ) || file_name.endsWith( ".newick" ) || file_name.endsWith( ".phy" )
2494                         || file_name.endsWith( ".tree" ) ) {
2495                     exception = writeAsNewHampshire( mp.getCurrentTreePanel(), mp.getOptions(), exception, file );
2496                 }
2497                 else if ( file_name.endsWith( ".nex" ) || file_name.endsWith( ".nexus" ) ) {
2498                     exception = writeAsNexus( mp.getCurrentTreePanel(), mp.getOptions(), exception, file );
2499                 }
2500                 // XML is default:
2501                 else {
2502                     exception = writeAsPhyloXml( mp.getCurrentTreePanel(), mp.getOptions(), exception, file );
2503                 }
2504             }
2505             if ( !exception ) {
2506                 mp.setTitleOfSelectedTab( file.getName() );
2507                 mp.getCurrentTreePanel().setTreeFile( file );
2508                 mp.getCurrentTreePanel().setEdited( false );
2509             }
2510         }
2511         return new_file;
2512     }
2513
2514     static File writeToGraphicsFile( final Phylogeny t,
2515                                      final GraphicsExportType type,
2516                                      final MainPanel mp,
2517                                      final JFileChooser writetographics_filechooser,
2518                                      final Component component,
2519                                      final Container contentpane,
2520                                      final File current_dir ) {
2521         File new_dir = null;
2522         if ( ( t == null ) || t.isEmpty() ) {
2523             return null;
2524         }
2525         String initial_filename = "";
2526         if ( mp.getCurrentTreePanel().getTreeFile() != null ) {
2527             initial_filename = mp.getCurrentTreePanel().getTreeFile().toString();
2528         }
2529         if ( initial_filename.indexOf( '.' ) > 0 ) {
2530             initial_filename = initial_filename.substring( 0, initial_filename.lastIndexOf( '.' ) );
2531         }
2532         initial_filename = initial_filename + "." + type;
2533         writetographics_filechooser.setSelectedFile( new File( initial_filename ) );
2534         final File my_dir = current_dir;
2535         if ( my_dir != null ) {
2536             writetographics_filechooser.setCurrentDirectory( my_dir );
2537         }
2538         final int result = writetographics_filechooser.showSaveDialog( contentpane );
2539         File file = writetographics_filechooser.getSelectedFile();
2540         //setCurrentDir( writetographics_filechooser.getCurrentDirectory() );
2541         new_dir = writetographics_filechooser.getCurrentDirectory();
2542         if ( ( file != null ) && ( result == JFileChooser.APPROVE_OPTION ) ) {
2543             if ( !file.toString().toLowerCase().endsWith( type.toString() ) ) {
2544                 file = new File( file.toString() + "." + type );
2545             }
2546             if ( file.exists() ) {
2547                 final int i = JOptionPane.showConfirmDialog( component,
2548                                                              file + " already exists. Overwrite?",
2549                                                              "Warning",
2550                                                              JOptionPane.OK_CANCEL_OPTION,
2551                                                              JOptionPane.WARNING_MESSAGE );
2552                 if ( i != JOptionPane.OK_OPTION ) {
2553                     return null;
2554                 }
2555                 else {
2556                     try {
2557                         file.delete();
2558                     }
2559                     catch ( final Exception e ) {
2560                         JOptionPane.showMessageDialog( component,
2561                                                        "Failed to delete: " + file,
2562                                                        "Error",
2563                                                        JOptionPane.WARNING_MESSAGE );
2564                     }
2565                 }
2566             }
2567             writePhylogenyToGraphicsFile( file.toString(), type, mp, component, contentpane );
2568         }
2569         return new_dir;
2570     }
2571
2572     static File writeToPdf( final Phylogeny t,
2573                             final MainPanel mp,
2574                             final JFileChooser writetopdf_filechooser,
2575                             final File curr_dir,
2576                             final Container contentpane,
2577                             final Component component ) {
2578         if ( ( t == null ) || t.isEmpty() ) {
2579             return null;
2580         }
2581         String initial_filename = "";
2582         if ( mp.getCurrentTreePanel().getTreeFile() != null ) {
2583             initial_filename = mp.getCurrentTreePanel().getTreeFile().toString();
2584         }
2585         if ( initial_filename.indexOf( '.' ) > 0 ) {
2586             initial_filename = initial_filename.substring( 0, initial_filename.lastIndexOf( '.' ) );
2587         }
2588         initial_filename = initial_filename + ".pdf";
2589         writetopdf_filechooser.setSelectedFile( new File( initial_filename ) );
2590         final File my_dir = curr_dir;
2591         if ( my_dir != null ) {
2592             writetopdf_filechooser.setCurrentDirectory( my_dir );
2593         }
2594         final int result = writetopdf_filechooser.showSaveDialog( contentpane );
2595         File file = writetopdf_filechooser.getSelectedFile();
2596         // setCurrentDir( writetopdf_filechooser.getCurrentDirectory() );
2597         final File new_current_dir = writetopdf_filechooser.getCurrentDirectory();
2598         if ( ( file != null ) && ( result == JFileChooser.APPROVE_OPTION ) ) {
2599             if ( !file.toString().toLowerCase().endsWith( ".pdf" ) ) {
2600                 file = new File( file.toString() + ".pdf" );
2601             }
2602             if ( file.exists() ) {
2603                 final int i = JOptionPane.showConfirmDialog( component,
2604                                                              file + " already exists. Overwrite?",
2605                                                              "WARNING",
2606                                                              JOptionPane.OK_CANCEL_OPTION,
2607                                                              JOptionPane.WARNING_MESSAGE );
2608                 if ( i != JOptionPane.OK_OPTION ) {
2609                     return null;
2610                 }
2611             }
2612             printPhylogenyToPdf( file.toString(), mp.getOptions(), mp.getCurrentTreePanel(), component );
2613         }
2614         return new_current_dir;
2615     }
2616 }
2617
2618 class DefaultFilter extends FileFilter {
2619
2620     @Override
2621     public boolean accept( final File f ) {
2622         final String file_name = f.getName().trim().toLowerCase();
2623         return file_name.endsWith( ".nh" ) || file_name.endsWith( ".newick" ) || file_name.endsWith( ".phy" )
2624                 || file_name.endsWith( ".nwk" ) || file_name.endsWith( ".phb" ) || file_name.endsWith( ".ph" )
2625                 || file_name.endsWith( ".tr" ) || file_name.endsWith( ".dnd" ) || file_name.endsWith( ".tree" )
2626                 || file_name.endsWith( ".nhx" ) || file_name.endsWith( ".xml" ) || file_name.endsWith( ".phyloxml" )
2627                 || file_name.endsWith( "phylo.xml" ) || file_name.endsWith( ".pxml" ) || file_name.endsWith( ".nexus" )
2628                 || file_name.endsWith( ".nx" ) || file_name.endsWith( ".nex" ) || file_name.endsWith( ".tre" )
2629                 || file_name.endsWith( ".zip" ) || file_name.endsWith( ".tol" ) || file_name.endsWith( ".tolxml" )
2630                 || file_name.endsWith( ".con" ) || f.isDirectory();
2631     }
2632
2633     @Override
2634     public String getDescription() {
2635         return "All supported files (*.xml, *.phyloxml, *phylo.xml, *.nhx, *.nh, *.newick, *.nex, *.nexus, *.phy, *.tre, *.tree, *.tol, ...)";
2636     }
2637 }
2638
2639 class GraphicsFileFilter extends FileFilter {
2640
2641     @Override
2642     public boolean accept( final File f ) {
2643         final String file_name = f.getName().trim().toLowerCase();
2644         return file_name.endsWith( ".jpg" ) || file_name.endsWith( ".jpeg" ) || file_name.endsWith( ".png" )
2645                 || file_name.endsWith( ".gif" ) || file_name.endsWith( ".bmp" ) || f.isDirectory();
2646     }
2647
2648     @Override
2649     public String getDescription() {
2650         return "Image files (*.jpg, *.jpeg, *.png, *.gif, *.bmp)";
2651     }
2652 }
2653
2654 class MsaFileFilter extends FileFilter {
2655
2656     @Override
2657     public boolean accept( final File f ) {
2658         final String file_name = f.getName().trim().toLowerCase();
2659         return file_name.endsWith( ".msa" ) || file_name.endsWith( ".aln" ) || file_name.endsWith( ".fasta" )
2660                 || file_name.endsWith( ".fas" ) || file_name.endsWith( ".fa" ) || f.isDirectory();
2661     }
2662
2663     @Override
2664     public String getDescription() {
2665         return "Multiple sequence alignment files (*.msa, *.aln, *.fasta, *.fa, *.fas)";
2666     }
2667 }
2668
2669 class NexusFilter extends FileFilter {
2670
2671     @Override
2672     public boolean accept( final File f ) {
2673         final String file_name = f.getName().trim().toLowerCase();
2674         return file_name.endsWith( ".nex" ) || file_name.endsWith( ".nexus" ) || file_name.endsWith( ".nx" )
2675                 || file_name.endsWith( ".tre" ) || f.isDirectory();
2676     }
2677
2678     @Override
2679     public String getDescription() {
2680         return "Nexus files (*.nex, *.nexus, *.nx, *.tre)";
2681     }
2682 } // NexusFilter
2683
2684 class NHFilter extends FileFilter {
2685
2686     @Override
2687     public boolean accept( final File f ) {
2688         final String file_name = f.getName().trim().toLowerCase();
2689         return file_name.endsWith( ".nh" ) || file_name.endsWith( ".newick" ) || file_name.endsWith( ".phy" )
2690                 || file_name.endsWith( ".tr" ) || file_name.endsWith( ".tree" ) || file_name.endsWith( ".dnd" )
2691                 || file_name.endsWith( ".ph" ) || file_name.endsWith( ".phb" ) || file_name.endsWith( ".nwk" )
2692                 || f.isDirectory();
2693     }
2694
2695     @Override
2696     public String getDescription() {
2697         return "New Hampshire - Newick files (*.nh, *.newick, *.phy, *.tree, *.dnd, *.tr, *.ph, *.phb, *.nwk)";
2698     }
2699 } // NHFilter
2700
2701 class NHXFilter extends FileFilter {
2702
2703     @Override
2704     public boolean accept( final File f ) {
2705         final String file_name = f.getName().trim().toLowerCase();
2706         return file_name.endsWith( ".nhx" ) || f.isDirectory();
2707     }
2708
2709     @Override
2710     public String getDescription() {
2711         return "NHX files (*.nhx) [deprecated]";
2712     }
2713 }
2714
2715 class PdfFilter extends FileFilter {
2716
2717     @Override
2718     public boolean accept( final File f ) {
2719         return f.getName().trim().toLowerCase().endsWith( ".pdf" ) || f.isDirectory();
2720     }
2721
2722     @Override
2723     public String getDescription() {
2724         return "PDF files (*.pdf)";
2725     }
2726 } // PdfFilter
2727
2728 class SequencesFileFilter extends FileFilter {
2729
2730     @Override
2731     public boolean accept( final File f ) {
2732         final String file_name = f.getName().trim().toLowerCase();
2733         return file_name.endsWith( ".fasta" ) || file_name.endsWith( ".fa" ) || file_name.endsWith( ".fas" )
2734                 || file_name.endsWith( ".seqs" ) || f.isDirectory();
2735     }
2736
2737     @Override
2738     public String getDescription() {
2739         return "Sequences files (*.fasta, *.fa, *.fas, *.seqs )";
2740     }
2741 }
2742
2743 class TolFilter extends FileFilter {
2744
2745     @Override
2746     public boolean accept( final File f ) {
2747         final String file_name = f.getName().trim().toLowerCase();
2748         return ( file_name.endsWith( ".tol" ) || file_name.endsWith( ".tolxml" ) || file_name.endsWith( ".zip" ) || f
2749                 .isDirectory() ) && ( !file_name.endsWith( ".xml.zip" ) );
2750     }
2751
2752     @Override
2753     public String getDescription() {
2754         return "Tree of Life files (*.tol, *.tolxml)";
2755     }
2756 } // TolFilter
2757
2758 class XMLFilter extends FileFilter {
2759
2760     @Override
2761     public boolean accept( final File f ) {
2762         final String file_name = f.getName().trim().toLowerCase();
2763         return file_name.endsWith( ".xml" ) || file_name.endsWith( ".phyloxml" ) || file_name.endsWith( "phylo.xml" )
2764                 || file_name.endsWith( ".pxml" ) || file_name.endsWith( ".zip" ) || f.isDirectory();
2765     }
2766
2767     @Override
2768     public String getDescription() {
2769         return "phyloXML files (*.xml, *.phyloxml, *phylo.xml, *.pxml, *.zip)";
2770     }
2771 } // XMLFilter