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