some additions being added
authorcmzmasek <cmzmasek@yahoo.com>
Sat, 6 Aug 2016 01:23:47 +0000 (18:23 -0700)
committercmzmasek <cmzmasek@yahoo.com>
Sat, 6 Aug 2016 01:23:47 +0000 (18:23 -0700)
forester/java/src/org/forester/archaeopteryx/AptxUtil.java
forester/java/src/org/forester/archaeopteryx/Configuration.java
forester/java/src/org/forester/archaeopteryx/ControlPanel.java
forester/java/src/org/forester/archaeopteryx/MainFrame.java
forester/java/src/org/forester/archaeopteryx/MainFrameApplication.java
forester/java/src/org/forester/archaeopteryx/TreePanel.java
forester/java/src/org/forester/archaeopteryx/TreePanelUtil.java
forester/java/src/org/forester/io/parsers/phyloxml/PhyloXmlMapping.java
forester/java/src/org/forester/io/parsers/phyloxml/data/TaxonomyParser.java
forester/java/src/org/forester/phylogeny/PhylogenyMethods.java
forester/java/src/org/forester/phylogeny/data/Taxonomy.java

index f0da94b..f946f23 100644 (file)
@@ -44,10 +44,12 @@ import java.security.KeyManagementException;
 import java.security.NoSuchAlgorithmException;
 import java.text.ParseException;
 import java.util.Arrays;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Locale;
+import java.util.Map;
 import java.util.Set;
 import java.util.SortedSet;
 import java.util.TreeSet;
@@ -751,6 +753,22 @@ public final class AptxUtil {
         }
         return str_array;
     }
+    
+    final static String[] getAllPossibleRanks(final Map<String, Integer> present_ranks) {
+        final String[] str_array = new String[ PhyloXmlUtil.TAXONOMY_RANKS_LIST.size() - 2 ];
+        int i = 0;
+        for( final String e : PhyloXmlUtil.TAXONOMY_RANKS_LIST ) {
+            if ( !e.equals( PhyloXmlUtil.UNKNOWN ) && !e.equals( PhyloXmlUtil.OTHER ) ) {
+                if ( present_ranks != null && present_ranks.containsKey( e ) ) {
+                    str_array[ i++ ] = e + " (" +  present_ranks.get(e) + ")";
+                }
+                else {
+                    str_array[ i++ ] = e;
+                }
+            }
+        }
+        return str_array;
+    }
 
     final static String[] getAllRanks( final Phylogeny tree ) {
         final SortedSet<String> ranks = new TreeSet<String>();
@@ -1079,4 +1097,25 @@ public final class AptxUtil {
         final IIOImage iio_image = new IIOImage( image, null, null );
         writer.write( null, iio_image, image_write_param );
     }
+
+    final static Map<String, Integer> getRankCounts(final Phylogeny tree) {
+        final Map<String, Integer> present_ranks = new HashMap<String, Integer>();
+    
+        if ( ( tree != null ) && !tree.isEmpty() ) {
+            for( final PhylogenyNodeIterator it = tree.iteratorPostorder(); it.hasNext(); ) {
+                final PhylogenyNode n = it.next();
+                if ( !n.isExternal() && n.getNodeData().isHasTaxonomy()
+                        && !ForesterUtil.isEmpty( n.getNodeData().getTaxonomy().getRank() ) && !n.isRoot() ) {
+                    final String rank = n.getNodeData().getTaxonomy().getRank().toLowerCase();
+                    if (present_ranks.containsKey( rank ) ) {
+                        present_ranks.put( rank, present_ranks.get( rank ) + 1 );
+                    }
+                    else {
+                        present_ranks.put( rank, 1 );
+                    }
+                }
+            }
+        }
+        return present_ranks;
+    }
 }
index bf28511..b4a4398 100644 (file)
@@ -68,13 +68,13 @@ public final class Configuration {
     }
     final static String                     clickto_options[][]                                    = {
         { "Display Node Data", "display" }, { "Collapse/Uncollapse", "display" }, { "Root/Reroot", "display" },
-        { "Go to Sub-/Super-Tree", "display" }, { "Swap Descendants", "display" },
+        { "Go to Sub/Supertree", "display" }, { "Swap Descendants", "display" },
         { "Colorize Node(s)", "display" }, { "Change Node Font(s)", "display" },
         { "Colorize Subtree(s)", "display" }, { "Open Sequence DB", "display" }, { "Open PDB", "display" },
         { "Open Taxonomy DB", "display" }, { "Launch BLAST", "display" }, { "Cut Subtree", "display" },
         { "Copy Subtree", "display" }, { "Paste Subtree", "display" }, { "Delete Subtree/Node", "display" },
         { "Add New Node", "display" }, { "Edit Node Data", "display" }, { "Sort Descendants", "display" },
-        { "List Node Data", "display" }, { "Select Node(s)", "display" }                      };
+        { "List Node Data", "display" }, { "Select Node(s)", "display" } , { "Uncollapse All", "display" },  { "Order Subtree", "display" },                     };
     private final static String             DEFAULT_SPECIES_COLORS[][]                             = {
         { "BRAFL", "0x00FFFF" }, { "SPHGR", "0x9620F0" }, { "STRPU", "0x9620F0" }, { "CIOIN", "0xFF1CAE" },
         { "CIOSA", "0xFF2CAE" }, { "BOVIN", "0x5C3317" }, { "CANFA", "0x8B2323" }, { "HUMAN", "0xFF2400" },
@@ -114,6 +114,9 @@ public final class Configuration {
     final static int                        sort_descendents                                       = 18;
     final static int                        get_ext_desc_data                                      = 19;
     final static int                        select_nodes                                           = 20;
+    final static int                        uncollapse_all                                         = 21;
+    final static int                        order_subtree                                         = 22;
+    
     // ------------------
     // Click-to options
     // ------------------
@@ -131,7 +134,8 @@ public final class Configuration {
         { "Rollover", "display", "yes" }, { "Relation Confidence", "nodisplay", "no" },
         { "Vector Data", "nodisplay", "no" }, { "Taxonomy Images", "display", "no" },
         { "Properties", "display", "no" }, { "Gene Name", "display", "yes" },
-        { "Multiple Seq Alignment", "display", "no" }, { "Branch Length Values", "display", "no" } };
+        { "Multiple Seq Alignment", "display", "no" }, { "Branch Length Values", "display", "no" }
+        , { "Taxonomy Rank", "display", "no" }};
     final static int                        display_as_phylogram                                   = 0;
     final static int                        show_node_names                                        = 1;
     final static int                        show_tax_code                                          = 2;
@@ -161,6 +165,8 @@ public final class Configuration {
     final static int                        show_gene_names                                        = 26;
     final static int                        show_mol_seqs                                          = 27;
     final static int                        write_branch_length_values                             = 28;
+    final static int                        show_tax_rank                                          = 29;
+    
     static final String                     VALIDATE_AGAINST_PHYLOXML_XSD_SCHEMA                   = "validate_against_phyloxml_xsd_schema";
     private static Hashtable<String, Color> _sequence_colors;
     private static Hashtable<String, Color> _annotation_colors;
@@ -548,6 +554,10 @@ public final class Configuration {
     public void setDisplayTaxonomyCode( final boolean b ) {
         display_options[ show_tax_code ][ 2 ] = b ? "yes" : "no";
     }
+    
+    public void setDisplayTaxonomyRank( final boolean b ) {
+        display_options[ show_tax_rank ][ 2 ] = b ? "yes" : "no";
+    }
 
     public void setDisplayTaxonomyCommonNames( final boolean b ) {
         display_options[ show_taxonomy_common_names ][ 2 ] = b ? "yes" : "no";
@@ -655,6 +665,9 @@ public final class Configuration {
         else if ( name.equals( "collapse_uncollapse" ) ) {
             index = Configuration.collapse_uncollapse;
         }
+        else if ( name.equals( "uncollapse_all" ) ) {
+            index = Configuration.uncollapse_all;
+        }
         else if ( name.equals( "reroot" ) ) {
             index = Configuration.reroot;
         }
@@ -664,6 +677,9 @@ public final class Configuration {
         else if ( name.equals( "swap" ) ) {
             index = Configuration.swap;
         }
+        else if ( name.equals( "order_subtree" ) ) {
+            index = Configuration.order_subtree;
+        }
         else if ( name.equals( "sort_descendants" ) ) {
             index = Configuration.sort_descendents;
         }
@@ -1386,6 +1402,9 @@ public final class Configuration {
             else if ( key.equals( "show_taxonomy_code" ) ) {
                 key_index = Configuration.show_tax_code;
             }
+            else if ( key.equals( "show_taxonomy_rank" ) ) {
+                key_index = Configuration.show_tax_rank;
+            }
             else if ( key.equals( "write_confidence_values" ) ) {
                 key_index = Configuration.write_confidence_values;
             }
index fb6f98c..f9b53b6 100644 (file)
@@ -93,7 +93,9 @@ final class ControlPanel extends JPanel implements ActionListener {
         SUBTREE,
         SWAP,
         CHANGE_NODE_FONT,
-        COLOR_NODE_FONT;
+        COLOR_NODE_FONT,
+        UNCOLLAPSE_ALL,
+        ORDER_SUBTREE;
     }
     final static Font                         jcb_bold_font             = new Font( Configuration.getDefaultFontFamilyName(),
                                                                                     Font.BOLD,
@@ -116,6 +118,10 @@ final class ControlPanel extends JPanel implements ActionListener {
     private JLabel                            _click_to_label;
     private List<String>                      _click_to_names;
     private int                               _collapse_cb_item;
+    private int                               _uncollapse_all_cb_item;
+    private int                               _order_subtree_cb_item;
+    
+    
     private JCheckBox                         _color_acc_species;
     private JCheckBox                         _color_acc_sequence;
     private JCheckBox                         _color_according_to_annotation;
@@ -146,7 +152,6 @@ final class ControlPanel extends JPanel implements ActionListener {
     private int                               _open_tax_web_item;
     private int                               _color_node_font_item;
     private JButton                           _order;
-    private boolean                           _order_of_appearance;
     private int                               _paste_subtree_item;
     private int                               _reroot_cb_item;
     private JButton                           _return_to_super_tree;
@@ -178,6 +183,7 @@ final class ControlPanel extends JPanel implements ActionListener {
     private JCheckBox                         _show_sequence_acc;
     private JComboBox<String>                 _show_sequence_relations;
     private JCheckBox                         _show_taxo_code;
+    private JCheckBox                         _show_taxo_rank;
     private JCheckBox                         _show_taxo_common_names;
     private JCheckBox                         _show_taxo_images_cb;
     private JCheckBox                         _show_taxo_scientific_names;
@@ -208,7 +214,6 @@ final class ControlPanel extends JPanel implements ActionListener {
             setBorder( BorderFactory.createRaisedBevelBorder() );
         }
         setLayout( new GridLayout( 0, 1, 2, 2 ) );
-        _order_of_appearance = true;
         setupControls();
     }
 
@@ -291,8 +296,8 @@ final class ControlPanel extends JPanel implements ActionListener {
                     else if ( isShowSeqNames() || isShowSeqSymbols() || isShowGeneNames() ) {
                         pri = DESCENDANT_SORT_PRIORITY.SEQUENCE;
                     }
-                    PhylogenyMethods.orderAppearance( tp.getPhylogeny().getRoot(), _order_of_appearance, true, pri );
-                    _order_of_appearance = !_order_of_appearance;
+                    PhylogenyMethods.orderAppearanceX( tp.getPhylogeny().getRoot(), true, pri );
+                  
                     tp.setNodeInPreorderToNull();
                     tp.getPhylogeny().externalNodesHaveChanged();
                     tp.getPhylogeny().clearHashIdToNodeMap();
@@ -740,6 +745,15 @@ final class ControlPanel extends JPanel implements ActionListener {
             }
             cb_index++;
         }
+if ( _configuration.doDisplayClickToOption( Configuration.uncollapse_all ) ) {
+            _uncollapse_all_cb_item = cb_index;
+            addClickToOption( Configuration.uncollapse_all,
+                              _configuration.getClickToTitle( Configuration.uncollapse_all ) );
+            if ( default_option == Configuration.uncollapse_all ) {
+                selected_index = cb_index;
+            }
+            cb_index++;
+}                
         if ( _configuration.doDisplayClickToOption( Configuration.reroot ) ) {
             _reroot_cb_item = cb_index;
             addClickToOption( Configuration.reroot, _configuration.getClickToTitle( Configuration.reroot ) );
@@ -764,6 +778,16 @@ final class ControlPanel extends JPanel implements ActionListener {
             }
             cb_index++;
         }
+if ( _configuration.doDisplayClickToOption( Configuration.order_subtree ) ) {
+            _order_subtree_cb_item = cb_index;
+            addClickToOption( Configuration.order_subtree,
+                              _configuration.getClickToTitle( Configuration.order_subtree ) );
+            if ( default_option == Configuration.order_subtree ) {
+                selected_index = cb_index;
+            }
+            cb_index++;
+}    
+        
         if ( _configuration.doDisplayClickToOption( Configuration.sort_descendents ) ) {
             _sort_descendents_item = cb_index;
             addClickToOption( Configuration.sort_descendents,
@@ -989,6 +1013,10 @@ final class ControlPanel extends JPanel implements ActionListener {
             setCheckbox( Configuration.show_taxonomy_common_names,
                          _configuration.doCheckOption( Configuration.show_taxonomy_common_names ) );
         }
+        if ( _configuration.doDisplayOption( Configuration.show_tax_rank ) ) {
+            addCheckbox( Configuration.show_tax_rank, _configuration.getDisplayTitle( Configuration.show_tax_rank ) );
+            setCheckbox( Configuration.show_tax_rank, _configuration.doCheckOption( Configuration.show_tax_rank ) );
+        }
         if ( _configuration.doDisplayOption( Configuration.show_seq_names ) ) {
             addCheckbox( Configuration.show_seq_names, _configuration.getDisplayTitle( Configuration.show_seq_names ) );
             setCheckbox( Configuration.show_seq_names, _configuration.doCheckOption( Configuration.show_seq_names ) );
@@ -1164,8 +1192,9 @@ final class ControlPanel extends JPanel implements ActionListener {
         _show_whole.setPreferredSize( new Dimension( 10, 10 ) );
         _return_to_super_tree = new JButton( RETURN_TO_SUPER_TREE_TEXT );
         _return_to_super_tree.setEnabled( false );
-        _order = new JButton( "Order Subtrees" );
+        _order = new JButton( "Order Tree" );
         _uncollapse_all = new JButton( "Uncollapse All" );
+       
         addJButton( _zoom_in_y, x_panel );
         addJButton( _zoom_out_x, y_panel );
         addJButton( _show_whole, y_panel );
@@ -1238,6 +1267,11 @@ final class ControlPanel extends JPanel implements ActionListener {
                 addJCheckBox( _show_taxo_code, ch_panel );
                 add( ch_panel );
                 break;
+            case Configuration.show_tax_rank:
+                _show_taxo_rank = new JCheckBox( title );
+                addJCheckBox( _show_taxo_rank, ch_panel );
+                add( ch_panel );
+                break;    
             case Configuration.show_taxonomy_images:
                 _show_taxo_images_cb = new JCheckBox( title );
                 addJCheckBox( _show_taxo_images_cb, ch_panel );
@@ -1569,6 +1603,10 @@ final class ControlPanel extends JPanel implements ActionListener {
     boolean isShowTaxonomyCode() {
         return ( ( _show_taxo_code != null ) && _show_taxo_code.isSelected() );
     }
+    
+    boolean isShowTaxonomyRank() {
+        return ( ( _show_taxo_rank != null ) && _show_taxo_rank.isSelected() );
+    }
 
     boolean isShowTaxonomyCommonNames() {
         return ( ( _show_taxo_common_names != null ) && _show_taxo_common_names.isSelected() );
@@ -1707,6 +1745,11 @@ final class ControlPanel extends JPanel implements ActionListener {
                     _show_taxo_code.setSelected( state );
                 }
                 break;
+            case Configuration.show_tax_rank:
+                if ( _show_taxo_rank != null ) {
+                    _show_taxo_rank.setSelected( state );
+                }
+                break;
             case Configuration.show_taxonomy_images:
                 if ( _show_taxo_images_cb != null ) {
                     _show_taxo_images_cb.setSelected( state );
@@ -1889,6 +1932,12 @@ final class ControlPanel extends JPanel implements ActionListener {
         else if ( action == _change_node_font_item ) {
             setActionWhenNodeClicked( NodeClickAction.CHANGE_NODE_FONT );
         }
+        else if ( action == _uncollapse_all_cb_item ) {
+            setActionWhenNodeClicked( NodeClickAction.UNCOLLAPSE_ALL );
+        }
+        else if ( action == _order_subtree_cb_item ) {
+            setActionWhenNodeClicked( NodeClickAction.ORDER_SUBTREE );
+        }
         else {
             throw new RuntimeException( "unknown action: " + action );
         }
index 0336c92..7411509 100644 (file)
@@ -36,6 +36,7 @@ import java.util.ArrayList;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Locale;
+import java.util.Map;
 import java.util.NoSuchElementException;
 
 import javax.swing.Box;
@@ -183,6 +184,7 @@ public abstract class MainFrame extends JFrame implements ActionListener {
     JMenuItem                        _confcolor_item;
     JMenuItem                        _color_rank_jmi;
     JMenuItem                        _collapse_species_specific_subtrees;
+    
     JMenuItem                        _obtain_detailed_taxonomic_information_jmi;
     JMenuItem                        _obtain_detailed_taxonomic_information_deleting_jmi;
     JMenuItem                        _obtain_seq_information_jmi;
@@ -1291,8 +1293,9 @@ public abstract class MainFrame extends JFrame implements ActionListener {
 
     void colorRank() {
         if ( _mainpanel.getCurrentTreePanel() != null ) {
-            final String[] ranks = AptxUtil.getAllPossibleRanks();
-            final String rank = ( String ) JOptionPane
+            final Map<String, Integer> present_ranks = AptxUtil.getRankCounts( _mainpanel.getCurrentTreePanel().getPhylogeny());
+            final String[] ranks = AptxUtil.getAllPossibleRanks(present_ranks);
+            String rank = ( String ) JOptionPane
                     .showInputDialog( this,
                                       "What rank should the colorization be based on",
                                       "Rank Selection",
@@ -1301,6 +1304,9 @@ public abstract class MainFrame extends JFrame implements ActionListener {
                                       ranks,
                                       null );
             if ( !ForesterUtil.isEmpty( rank ) ) {
+                if ( rank.indexOf( '(' ) > 0 ) {
+                    rank = rank.substring( 0, rank.indexOf( '(' ) ).trim();
+                }
                 _mainpanel.getCurrentTreePanel().colorRank( rank );
             }
         }
index fd79734..40fc4bc 100644 (file)
@@ -42,6 +42,7 @@ import java.net.URL;
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
 import javax.swing.ButtonGroup;
@@ -117,6 +118,7 @@ public final class MainFrameApplication extends MainFrame {
     // Application-only print menu items
     private JMenuItem                    _collapse_below_threshold;
     private JMenuItem                    _collapse_below_branch_length;
+    private JMenuItem                    _collapse_by_taxonomic_rank;
     private ButtonGroup                  _radio_group_1;
     private ButtonGroup                  _radio_group_2;
     // Others:
@@ -317,10 +319,8 @@ public final class MainFrameApplication extends MainFrame {
                     }
                 }
                 else {
-                    final int r = JOptionPane.showConfirmDialog( null,
-                                                                 "Exit Archaeopteryx?",
-                                                                 "Exit?",
-                                                                 JOptionPane.YES_NO_OPTION );
+                    final int r = JOptionPane
+                            .showConfirmDialog( null, "Exit Archaeopteryx?", "Exit?", JOptionPane.YES_NO_OPTION );
                     if ( r != JOptionPane.YES_OPTION ) {
                         return;
                     }
@@ -334,10 +334,9 @@ public final class MainFrameApplication extends MainFrame {
             @Override
             public void componentResized( final ComponentEvent e ) {
                 if ( _mainpanel.getCurrentTreePanel() != null ) {
-                    _mainpanel.getCurrentTreePanel().calcParametersForPainting( _mainpanel.getCurrentTreePanel()
-                                                                                .getWidth(),
-                                                                                _mainpanel.getCurrentTreePanel()
-                                                                                .getHeight() );
+                    _mainpanel.getCurrentTreePanel()
+                            .calcParametersForPainting( _mainpanel.getCurrentTreePanel().getWidth(),
+                                                        _mainpanel.getCurrentTreePanel().getHeight() );
                 }
             }
         } );
@@ -436,6 +435,12 @@ public final class MainFrameApplication extends MainFrame {
                 }
                 collapseBelowThreshold();
             }
+            else if ( o == _collapse_by_taxonomic_rank ) {
+                if ( isSubtreeDisplayed() ) {
+                    return;
+                }
+                collapseByTaxonomicRank();
+            }
             else if ( o == _collapse_below_branch_length ) {
                 if ( isSubtreeDisplayed() ) {
                     return;
@@ -719,8 +724,8 @@ public final class MainFrameApplication extends MainFrame {
                 JOptionPane.showMessageDialog( this,
                                                "Table contains " + t.getNumberOfRows() + " rows, but tree contains "
                                                        + phy.getNumberOfExternalNodes() + " external nodes",
-                                                       "Warning",
-                                                       JOptionPane.WARNING_MESSAGE );
+                                               "Warning",
+                                               JOptionPane.WARNING_MESSAGE );
             }
             final DescriptiveStatistics stats = new BasicDescriptiveStatistics();
             int not_found = 0;
@@ -733,11 +738,10 @@ public final class MainFrameApplication extends MainFrame {
                         row = t.findRow( node_name );
                     }
                     catch ( final IllegalArgumentException e ) {
-                        JOptionPane
-                        .showMessageDialog( this,
-                                            e.getMessage(),
-                                            "Error Mapping Node Identifiers to Expression Value Identifiers",
-                                            JOptionPane.ERROR_MESSAGE );
+                        JOptionPane.showMessageDialog( this,
+                                                       e.getMessage(),
+                                                       "Error Mapping Node Identifiers to Expression Value Identifiers",
+                                                       JOptionPane.ERROR_MESSAGE );
                         return;
                     }
                     if ( row < 0 ) {
@@ -755,7 +759,7 @@ public final class MainFrameApplication extends MainFrame {
                         catch ( final NumberFormatException e ) {
                             JOptionPane.showMessageDialog( this,
                                                            "Could not parse \"" + t.getValueAsString( col, row )
-                                                           + "\" into a decimal value",
+                                                                   + "\" into a decimal value",
                                                            "Issue with Expression Value Table",
                                                            JOptionPane.ERROR_MESSAGE );
                             return;
@@ -766,15 +770,18 @@ public final class MainFrameApplication extends MainFrame {
                     if ( !l.isEmpty() ) {
                         if ( node.getNodeData().getProperties() != null ) {
                             node.getNodeData().getProperties()
-                            .removePropertiesWithGivenReferencePrefix( PhyloXmlUtil.VECTOR_PROPERTY_REF );
+                                    .removePropertiesWithGivenReferencePrefix( PhyloXmlUtil.VECTOR_PROPERTY_REF );
                         }
                         node.getNodeData().setVector( l );
                     }
                 }
             }
             if ( not_found > 0 ) {
-                JOptionPane.showMessageDialog( this, "Could not fine expression values for " + not_found
-                                               + " external node(s)", "Warning", JOptionPane.WARNING_MESSAGE );
+                JOptionPane
+                        .showMessageDialog( this,
+                                            "Could not fine expression values for " + not_found + " external node(s)",
+                                            "Warning",
+                                            JOptionPane.WARNING_MESSAGE );
             }
             getCurrentTreePanel().setStatisticsForExpressionValues( stats );
         }
@@ -803,10 +810,10 @@ public final class MainFrameApplication extends MainFrame {
                     seqs = FastaParser.parse( fis2 );
                     try {
                         fis2.close();
-                     }
-                     catch ( final Exception e ) {
-                         // Ignore.
-                     }
+                    }
+                    catch ( final Exception e ) {
+                        // Ignore.
+                    }
                 }
                 else {
                     JOptionPane.showMessageDialog( this,
@@ -819,7 +826,7 @@ public final class MainFrameApplication extends MainFrame {
                     fis1.close();
                 }
                 catch ( final Exception e ) {
-                     // Ignore.
+                    // Ignore.
                 }
             }
             catch ( final MsaFormatException e ) {
@@ -896,8 +903,11 @@ public final class MainFrameApplication extends MainFrame {
                             nodes = phy.getNodes( seq_name_split );
                         }
                         if ( nodes.size() > 1 ) {
-                            JOptionPane.showMessageDialog( this, "Split sequence name \"" + seq_name_split
-                                                           + "\" is not unique", "Sequence name not unique", JOptionPane.ERROR_MESSAGE );
+                            JOptionPane.showMessageDialog( this,
+                                                           "Split sequence name \"" + seq_name_split
+                                                                   + "\" is not unique",
+                                                           "Sequence name not unique",
+                                                           JOptionPane.ERROR_MESSAGE );
                             setArrowCursor();
                             return;
                         }
@@ -941,14 +951,18 @@ public final class MainFrameApplication extends MainFrame {
                                                    JOptionPane.INFORMATION_MESSAGE );
                 }
                 else {
-                    JOptionPane.showMessageDialog( this, "Attached " + attached_counter
-                                                   + " sequences out of a total of " + total_counter + " sequences.\n" + s, attached_counter
-                                                   + " sequences attached", JOptionPane.WARNING_MESSAGE );
+                    JOptionPane.showMessageDialog( this,
+                                                   "Attached " + attached_counter + " sequences out of a total of "
+                                                           + total_counter + " sequences.\n" + s,
+                                                   attached_counter + " sequences attached",
+                                                   JOptionPane.WARNING_MESSAGE );
                 }
             }
             else {
-                JOptionPane.showMessageDialog( this, "No maching tree node for any of the " + total_counter
-                                               + " sequences", "Could not attach any sequences", JOptionPane.ERROR_MESSAGE );
+                JOptionPane.showMessageDialog( this,
+                                               "No maching tree node for any of the " + total_counter + " sequences",
+                                               "Could not attach any sequences",
+                                               JOptionPane.ERROR_MESSAGE );
             }
         }
     }
@@ -1014,13 +1028,19 @@ public final class MainFrameApplication extends MainFrame {
                 repaint();
             }
             if ( to_be_removed.size() > 0 ) {
-                JOptionPane.showMessageDialog( this, "Collapsed " + to_be_removed.size()
-                                               + " branches with\nconfidence values below " + getMinNotCollapseConfidenceValue(), "Collapsed "
-                                                       + to_be_removed.size() + " branches", JOptionPane.INFORMATION_MESSAGE );
+                JOptionPane.showMessageDialog( this,
+                                               "Collapsed " + to_be_removed.size()
+                                                       + " branches with\nconfidence values below "
+                                                       + getMinNotCollapseConfidenceValue(),
+                                               "Collapsed " + to_be_removed.size() + " branches",
+                                               JOptionPane.INFORMATION_MESSAGE );
             }
             else {
-                JOptionPane.showMessageDialog( this, "No branch collapsed,\nminimum confidence value per branch is "
-                        + min_support, "No branch collapsed", JOptionPane.INFORMATION_MESSAGE );
+                JOptionPane.showMessageDialog( this,
+                                               "No branch collapsed,\nminimum confidence value per branch is "
+                                                       + min_support,
+                                               "No branch collapsed",
+                                               JOptionPane.INFORMATION_MESSAGE );
             }
         }
         else {
@@ -1031,18 +1051,38 @@ public final class MainFrameApplication extends MainFrame {
         }
     }
 
+    private void collapseByTaxonomicRank() {
+        if ( _mainpanel.getCurrentTreePanel() != null ) {
+            final Map<String, Integer> present_ranks = AptxUtil.getRankCounts( _mainpanel.getCurrentTreePanel().getPhylogeny());
+            final String[] ranks = AptxUtil.getAllPossibleRanks(present_ranks);
+             String rank = ( String ) JOptionPane
+                    .showInputDialog( this,
+                                      "What rank should the collapsing be based on",
+                                      "Rank Selection",
+                                      JOptionPane.QUESTION_MESSAGE,
+                                      null,
+                                      ranks,
+                                      null );
+            if ( !ForesterUtil.isEmpty( rank ) ) {
+                if ( rank.indexOf( '(' ) > 0 ) {
+                    rank = rank.substring( 0, rank.indexOf( '(' ) ).trim();
+                }
+                _mainpanel.getCurrentTreePanel().collapseByTaxonomicRank( rank );
+            }
+        }
+    }
+
     private void collapseBelowBranchLengthThreshold() {
         if ( getCurrentTreePanel() != null ) {
             final Phylogeny phy = getCurrentTreePanel().getPhylogeny();
             if ( ( phy != null ) && !phy.isEmpty() ) {
-                final String s = ( String ) JOptionPane
-                        .showInputDialog( this,
-                                          "Please enter the minimum branch length value\n",
-                                          "Minimal Branch Length Value",
-                                          JOptionPane.QUESTION_MESSAGE,
-                                          null,
-                                          null,
-                                          getMinNotCollapseBlValue() );
+                final String s = ( String ) JOptionPane.showInputDialog( this,
+                                                                         "Please enter the minimum branch length value\n",
+                                                                         "Minimal Branch Length Value",
+                                                                         JOptionPane.QUESTION_MESSAGE,
+                                                                         null,
+                                                                         null,
+                                                                         getMinNotCollapseBlValue() );
                 if ( !ForesterUtil.isEmpty( s ) ) {
                     boolean success = true;
                     double m = 0.0;
@@ -1141,9 +1181,12 @@ public final class MainFrameApplication extends MainFrame {
                 repaint();
             }
             if ( to_be_removed.size() > 0 ) {
-                JOptionPane.showMessageDialog( this, "Collapsed " + to_be_removed.size()
-                                               + " branches with\nbranch length values below " + getMinNotCollapseBlValue(), "Collapsed "
-                                                       + to_be_removed.size() + " branches", JOptionPane.INFORMATION_MESSAGE );
+                JOptionPane.showMessageDialog( this,
+                                               "Collapsed " + to_be_removed.size()
+                                                       + " branches with\nbranch length values below "
+                                                       + getMinNotCollapseBlValue(),
+                                               "Collapsed " + to_be_removed.size() + " branches",
+                                               JOptionPane.INFORMATION_MESSAGE );
             }
             else {
                 JOptionPane.showMessageDialog( this,
@@ -1189,7 +1232,8 @@ public final class MainFrameApplication extends MainFrame {
                 if ( getMsa() != null ) {
                     final PhylogeneticInferrer inferrer = new PhylogeneticInferrer( getMsa(),
                                                                                     getPhylogeneticInferenceOptions()
-                                                                                    .copy(), this );
+                                                                                            .copy(),
+                                                                                    this );
                     new Thread( inferrer ).start();
                 }
                 else {
@@ -1203,7 +1247,8 @@ public final class MainFrameApplication extends MainFrame {
                 if ( getSeqs() != null ) {
                     final PhylogeneticInferrer inferrer = new PhylogeneticInferrer( getSeqs(),
                                                                                     getPhylogeneticInferenceOptions()
-                                                                                    .copy(), this );
+                                                                                            .copy(),
+                                                                                    this );
                     new Thread( inferrer ).start();
                 }
                 else {
@@ -1256,24 +1301,23 @@ public final class MainFrameApplication extends MainFrame {
                     String all = "all ";
                     if ( counter_failed > 0 ) {
                         all = "";
-                        failed = "\nCould not extract taxonomic data for " + counter_failed
-                                + " named external nodes:\n" + sb_failed;
+                        failed = "\nCould not extract taxonomic data for " + counter_failed + " named external nodes:\n"
+                                + sb_failed;
                     }
                     JOptionPane.showMessageDialog( this,
                                                    "Extracted taxonomic data from " + all + counter
-                                                   + " named external nodes:\n" + sb.toString() + failed,
+                                                           + " named external nodes:\n" + sb.toString() + failed,
                                                    "Taxonomic Data Extraction Completed",
                                                    counter_failed > 0 ? JOptionPane.WARNING_MESSAGE
                                                            : JOptionPane.INFORMATION_MESSAGE );
                 }
                 else {
-                    JOptionPane
-                    .showMessageDialog( this,
-                                        "Could not extract any taxonomic data.\nMaybe node names are empty\n"
-                                                + "or not in the forms \"XYZ_CAEEL\", \"XYZ_6239\", or \"XYZ_Caenorhabditis_elegans\"\n"
-                                                + "or nodes already have taxonomic data?\n",
-                                                "No Taxonomic Data Extracted",
-                                                JOptionPane.ERROR_MESSAGE );
+                    JOptionPane.showMessageDialog( this,
+                                                   "Could not extract any taxonomic data.\nMaybe node names are empty\n"
+                                                           + "or not in the forms \"XYZ_CAEEL\", \"XYZ_6239\", or \"XYZ_Caenorhabditis_elegans\"\n"
+                                                           + "or nodes already have taxonomic data?\n",
+                                                   "No Taxonomic Data Extracted",
+                                                   JOptionPane.ERROR_MESSAGE );
                 }
             }
         }
@@ -1308,8 +1352,9 @@ public final class MainFrameApplication extends MainFrame {
         if ( getCurrentTreePanel() != null ) {
             final Phylogeny phy = getCurrentTreePanel().getPhylogeny();
             if ( ( phy != null ) && !phy.isEmpty() ) {
-                PhylogenyMethods
-                .transferNodeNameToField( phy, PhylogenyMethods.PhylogenyNodeField.SEQUENCE_NAME, false );
+                PhylogenyMethods.transferNodeNameToField( phy,
+                                                          PhylogenyMethods.PhylogenyNodeField.SEQUENCE_NAME,
+                                                          false );
             }
         }
     }
@@ -1339,7 +1384,7 @@ public final class MainFrameApplication extends MainFrame {
         if ( getMainPanel().getMainFrame() == null ) {
             // Must be "E" applet version.
             ( ( ArchaeopteryxE ) ( ( MainPanelApplets ) getMainPanel() ).getApplet() )
-            .setSelectedTypeInTypeMenu( PHYLOGENY_GRAPHICS_TYPE.RECTANGULAR );
+                    .setSelectedTypeInTypeMenu( PHYLOGENY_GRAPHICS_TYPE.RECTANGULAR );
         }
         else {
             getMainPanel().getMainFrame().setSelectedTypeInTypeMenu( PHYLOGENY_GRAPHICS_TYPE.RECTANGULAR );
@@ -1484,8 +1529,9 @@ public final class MainFrameApplication extends MainFrame {
                     else {
                         try {
                             final PhylogenyParser parser = ParserUtils
-                                    .createParserDependingOnFileType( file, getConfiguration()
-                                                                      .isValidatePhyloXmlAgainstSchema() );
+                                    .createParserDependingOnFileType( file,
+                                                                      getConfiguration()
+                                                                              .isValidatePhyloXmlAgainstSchema() );
                             if ( parser instanceof NexusPhylogeniesParser ) {
                                 final NexusPhylogeniesParser nex = ( NexusPhylogeniesParser ) parser;
                                 setSpecialOptionsForNexParser( nex );
@@ -1535,13 +1581,12 @@ public final class MainFrameApplication extends MainFrame {
                                                        getMainPanel() );
                         _mainpanel.getControlPanel().showWhole();
                         if ( nhx_or_nexus && one_desc ) {
-                            JOptionPane
-                            .showMessageDialog( this,
-                                                "One or more trees contain (a) node(s) with one descendant, "
-                                                        + ForesterUtil.LINE_SEPARATOR
-                                                        + "possibly indicating illegal parentheses within node names.",
-                                                        "Warning: Possible Error in New Hampshire Formatted Data",
-                                                        JOptionPane.WARNING_MESSAGE );
+                            JOptionPane.showMessageDialog( this,
+                                                           "One or more trees contain (a) node(s) with one descendant, "
+                                                                   + ForesterUtil.LINE_SEPARATOR
+                                                                   + "possibly indicating illegal parentheses within node names.",
+                                                           "Warning: Possible Error in New Hampshire Formatted Data",
+                                                           JOptionPane.WARNING_MESSAGE );
                         }
                     }
                 }
@@ -1564,8 +1609,8 @@ public final class MainFrameApplication extends MainFrame {
         if ( ( file != null ) && ( result == JFileChooser.APPROVE_OPTION ) ) {
             if ( _open_filechooser_for_species_tree.getFileFilter() == MainFrame.xmlfilter ) {
                 try {
-                    final Phylogeny[] trees = PhylogenyMethods.readPhylogenies( PhyloXmlParser
-                                                                                .createPhyloXmlParserXsdValidating(), file );
+                    final Phylogeny[] trees = PhylogenyMethods
+                            .readPhylogenies( PhyloXmlParser.createPhyloXmlParserXsdValidating(), file );
                     t = trees[ 0 ];
                 }
                 catch ( final Exception e ) {
@@ -1586,8 +1631,8 @@ public final class MainFrameApplication extends MainFrame {
             // "*.*":
             else {
                 try {
-                    final Phylogeny[] trees = PhylogenyMethods.readPhylogenies( PhyloXmlParser
-                                                                                .createPhyloXmlParserXsdValidating(), file );
+                    final Phylogeny[] trees = PhylogenyMethods
+                            .readPhylogenies( PhyloXmlParser.createPhyloXmlParserXsdValidating(), file );
                     t = trees[ 0 ];
                 }
                 catch ( final Exception e ) {
@@ -1610,23 +1655,22 @@ public final class MainFrameApplication extends MainFrame {
                     if ( !node.getNodeData().isHasTaxonomy() ) {
                         exception = true;
                         t = null;
-                        JOptionPane
-                        .showMessageDialog( this,
-                                            "Species tree contains external node(s) without taxonomy information",
-                                            "Species tree not loaded",
-                                            JOptionPane.ERROR_MESSAGE );
+                        JOptionPane.showMessageDialog( this,
+                                                       "Species tree contains external node(s) without taxonomy information",
+                                                       "Species tree not loaded",
+                                                       JOptionPane.ERROR_MESSAGE );
                         break;
                     }
                     else {
                         if ( tax_set.contains( node.getNodeData().getTaxonomy() ) ) {
                             exception = true;
                             t = null;
-                            JOptionPane.showMessageDialog( this,
-                                                           "Taxonomy ["
-                                                                   + node.getNodeData().getTaxonomy().asSimpleText()
-                                                                   + "] is not unique in species tree",
-                                                                   "Species tree not loaded",
-                                                                   JOptionPane.ERROR_MESSAGE );
+                            JOptionPane
+                                    .showMessageDialog( this,
+                                                        "Taxonomy [" + node.getNodeData().getTaxonomy().asSimpleText()
+                                                                + "] is not unique in species tree",
+                                                        "Species tree not loaded",
+                                                        JOptionPane.ERROR_MESSAGE );
                             break;
                         }
                         else {
@@ -1705,7 +1749,7 @@ public final class MainFrameApplication extends MainFrame {
         _file_jmenu.addSeparator();
         final WebservicesManager webservices_manager = WebservicesManager.getInstance();
         _load_phylogeny_from_webservice_menu_items = new JMenuItem[ webservices_manager
-                                                                    .getAvailablePhylogeniesWebserviceClients().size() ];
+                .getAvailablePhylogeniesWebserviceClients().size() ];
         for( int i = 0; i < webservices_manager.getAvailablePhylogeniesWebserviceClients().size(); ++i ) {
             final PhylogeniesWebserviceClient client = webservices_manager.getAvailablePhylogeniesWebserviceClient( i );
             _load_phylogeny_from_webservice_menu_items[ i ] = new JMenuItem( client.getMenuName() );
@@ -1723,7 +1767,8 @@ public final class MainFrameApplication extends MainFrame {
         _save_all_item.setEnabled( false );
         _file_jmenu.addSeparator();
         _file_jmenu.add( _write_to_pdf_item = new JMenuItem( "Export to PDF file ..." ) );
-        if ( AptxUtil.canWriteFormat( "tif" ) || AptxUtil.canWriteFormat( "tiff" ) || AptxUtil.canWriteFormat( "TIF" ) ) {
+        if ( AptxUtil.canWriteFormat( "tif" ) || AptxUtil.canWriteFormat( "tiff" )
+                || AptxUtil.canWriteFormat( "TIF" ) ) {
             _file_jmenu.add( _write_to_tif_item = new JMenuItem( "Export to TIFF file..." ) );
         }
         _file_jmenu.add( _write_to_png_item = new JMenuItem( "Export to PNG file..." ) );
@@ -1743,8 +1788,9 @@ public final class MainFrameApplication extends MainFrame {
         _file_jmenu.addSeparator();
         _file_jmenu.add( _exit_item = new JMenuItem( "Exit" ) );
         customizeJMenuItem( _open_item );
-        _open_item
-        .setFont( new Font( _open_item.getFont().getFontName(), Font.BOLD, _open_item.getFont().getSize() + 4 ) );
+        _open_item.setFont( new Font( _open_item.getFont().getFontName(),
+                                      Font.BOLD,
+                                      _open_item.getFont().getSize() + 4 ) );
         customizeJMenuItem( _open_url_item );
         for( int i = 0; i < webservices_manager.getAvailablePhylogeniesWebserviceClients().size(); ++i ) {
             customizeJMenuItem( _load_phylogeny_from_webservice_menu_items[ i ] );
@@ -1774,11 +1820,13 @@ public final class MainFrameApplication extends MainFrame {
             public void stateChanged( final ChangeEvent e ) {
                 MainFrame.setOvPlacementColorChooseMenuItem( _overview_placment_mi, getOptions() );
                 MainFrame.setTextColorChooseMenuItem( _switch_colors_mi, getCurrentTreePanel() );
-                MainFrame
-                .setTextMinSupportMenuItem( _choose_minimal_confidence_mi, getOptions(), getCurrentTreePanel() );
-                MainFrame.setTextForFontChooserMenuItem( _choose_font_mi, MainFrame
-                                                         .createCurrentFontDesc( getMainPanel().getTreeFontSet() ) );
-              //  MainFrame.setTextForGraphicsSizeChooserMenuItem( _print_size_mi, getOptions() );
+                MainFrame.setTextMinSupportMenuItem( _choose_minimal_confidence_mi,
+                                                     getOptions(),
+                                                     getCurrentTreePanel() );
+                MainFrame.setTextForFontChooserMenuItem( _choose_font_mi,
+                                                         MainFrame.createCurrentFontDesc( getMainPanel()
+                                                                 .getTreeFontSet() ) );
+                //  MainFrame.setTextForGraphicsSizeChooserMenuItem( _print_size_mi, getOptions() );
                 MainFrame.setTextForPdfLineWidthChooserMenuItem( _choose_pdf_width_mi, getOptions() );
                 MainFrame.setCycleNodeFillMenuItem( _cycle_node_fill_mi, getOptions() );
                 MainFrame.setCycleNodeShapeMenuItem( _cycle_node_shape_mi, getOptions() );
@@ -1795,7 +1843,7 @@ public final class MainFrameApplication extends MainFrame {
         } );
         _options_jmenu.add( customizeMenuItemAsLabel( new JMenuItem( DISPLAY_SUBHEADER ), getConfiguration() ) );
         _options_jmenu
-        .add( _ext_node_dependent_cladogram_rbmi = new JRadioButtonMenuItem( MainFrame.NONUNIFORM_CLADOGRAMS_LABEL ) );
+                .add( _ext_node_dependent_cladogram_rbmi = new JRadioButtonMenuItem( MainFrame.NONUNIFORM_CLADOGRAMS_LABEL ) );
         _options_jmenu.add( _uniform_cladograms_rbmi = new JRadioButtonMenuItem( MainFrame.UNIFORM_CLADOGRAMS_LABEL ) );
         _options_jmenu.add( _non_lined_up_cladograms_rbmi = new JRadioButtonMenuItem( NON_LINED_UP_CLADOGRAMS_LABEL ) );
         _radio_group_1 = new ButtonGroup();
@@ -1805,14 +1853,16 @@ public final class MainFrameApplication extends MainFrame {
         _options_jmenu.add( _show_overview_cbmi = new JCheckBoxMenuItem( SHOW_OVERVIEW_LABEL ) );
         _options_jmenu.add( _show_scale_cbmi = new JCheckBoxMenuItem( DISPLAY_SCALE_LABEL ) );
         _options_jmenu
-        .add( _show_default_node_shapes_internal_cbmi = new JCheckBoxMenuItem( DISPLAY_NODE_BOXES_LABEL_INT ) );
+                .add( _show_default_node_shapes_internal_cbmi = new JCheckBoxMenuItem( DISPLAY_NODE_BOXES_LABEL_INT ) );
+        _options_jmenu
+                .add( _show_default_node_shapes_external_cbmi = new JCheckBoxMenuItem( DISPLAY_NODE_BOXES_LABEL_EXT ) );
         _options_jmenu
-        .add( _show_default_node_shapes_external_cbmi = new JCheckBoxMenuItem( DISPLAY_NODE_BOXES_LABEL_EXT ) );
+                .add( _show_default_node_shapes_for_marked_cbmi = new JCheckBoxMenuItem( MainFrame.DISPLAY_NODE_BOXES_LABEL_MARKED ) );
         _options_jmenu
-        .add( _show_default_node_shapes_for_marked_cbmi = new JCheckBoxMenuItem( MainFrame.DISPLAY_NODE_BOXES_LABEL_MARKED ) );
-        _options_jmenu.add( _line_up_renderable_data_cbmi = new JCheckBoxMenuItem( MainFrame.LINE_UP_RENDERABLE_DATA ) );
+                .add( _line_up_renderable_data_cbmi = new JCheckBoxMenuItem( MainFrame.LINE_UP_RENDERABLE_DATA ) );
         if ( getConfiguration().doDisplayOption( Configuration.show_domain_architectures ) ) {
-            _options_jmenu.add( _right_line_up_domains_cbmi = new JCheckBoxMenuItem( MainFrame.RIGHT_LINE_UP_DOMAINS ) );
+            _options_jmenu
+                    .add( _right_line_up_domains_cbmi = new JCheckBoxMenuItem( MainFrame.RIGHT_LINE_UP_DOMAINS ) );
             _options_jmenu.add( _show_domain_labels = new JCheckBoxMenuItem( MainFrame.SHOW_DOMAIN_LABELS_LABEL ) );
         }
         _options_jmenu.add( _show_annotation_ref_source = new JCheckBoxMenuItem( SHOW_ANN_REF_SOURCE_LABEL ) );
@@ -1841,40 +1891,40 @@ public final class MainFrameApplication extends MainFrame {
         _options_jmenu.add( _search_with_regex_cbmi = new JCheckBoxMenuItem( MainFrame.SEARCH_REGEX_LABEL ) );
         _search_with_regex_cbmi.setToolTipText( MainFrame.SEARCH_WITH_REGEX_TIP );
         _options_jmenu.add( _inverse_search_result_cbmi = new JCheckBoxMenuItem( INVERSE_SEARCH_RESULT_LABEL ) );
-        _options_jmenu.add( _color_all_found_nodes_when_coloring_subtree_cbmi = new JCheckBoxMenuItem( "Colorize All Found Nodes When Colorizing Subtree(s)" ) ); 
+        _options_jmenu
+                .add( _color_all_found_nodes_when_coloring_subtree_cbmi = new JCheckBoxMenuItem( "Colorize All Found Nodes When Colorizing Subtree(s)" ) );
         _options_jmenu.addSeparator();
-        _options_jmenu.add( customizeMenuItemAsLabel( new JMenuItem( "Graphics Export & Printing:" ),
-                                                      getConfiguration() ) );
+        _options_jmenu
+                .add( customizeMenuItemAsLabel( new JMenuItem( "Graphics Export & Printing:" ), getConfiguration() ) );
         _options_jmenu.add( _antialias_print_cbmi = new JCheckBoxMenuItem( "Antialias" ) );
         _options_jmenu.add( _print_black_and_white_cbmi = new JCheckBoxMenuItem( "Export in Black and White" ) );
-         _options_jmenu
-        .add( _graphics_export_visible_only_cbmi = new JCheckBoxMenuItem( "Limit to Visible ('Screenshot') for PNG, JPG, and GIF export" ) );
+        _options_jmenu
+                .add( _graphics_export_visible_only_cbmi = new JCheckBoxMenuItem( "Limit to Visible ('Screenshot') for PNG, JPG, and GIF export" ) );
         _options_jmenu.add( _choose_pdf_width_mi = new JMenuItem( "" ) );
         _options_jmenu.addSeparator();
         _options_jmenu.add( customizeMenuItemAsLabel( new JMenuItem( "Newick/NHX/Nexus Read:" ), getConfiguration() ) );
         _options_jmenu
-        .add( _internal_number_are_confidence_for_nh_parsing_cbmi = new JCheckBoxMenuItem( "Internal Node Names are Confidence Values" ) );
+                .add( _internal_number_are_confidence_for_nh_parsing_cbmi = new JCheckBoxMenuItem( "Internal Node Names are Confidence Values" ) );
         _options_jmenu.add( _replace_underscores_cbmi = new JCheckBoxMenuItem( "Replace Underscores with Spaces" ) );
-        _options_jmenu.add( _parse_beast_style_extended_nexus_tags_cbmi = new JCheckBoxMenuItem( "Parse BEAST-style extended Newick/Nexus tags" ) ); 
-        
-        _parse_beast_style_extended_nexus_tags_cbmi.setToolTipText( "to parse elements in the form of \"[&!color=#800080]\" in Newick/Nexus formatted trees" );
-        
-        
         _options_jmenu
-        .add( _allow_errors_in_distance_to_parent_cbmi = new JCheckBoxMenuItem( "Ignore Distance Values Format Errors" ) );
+                .add( _parse_beast_style_extended_nexus_tags_cbmi = new JCheckBoxMenuItem( "Parse BEAST-style extended Newick/Nexus tags" ) );
+        _parse_beast_style_extended_nexus_tags_cbmi
+                .setToolTipText( "to parse elements in the form of \"[&!color=#800080]\" in Newick/Nexus formatted trees" );
+        _options_jmenu
+                .add( _allow_errors_in_distance_to_parent_cbmi = new JCheckBoxMenuItem( "Ignore Distance Values Format Errors" ) );
         _options_jmenu.add( _extract_taxonomy_no_rbmi = new JRadioButtonMenuItem( "No Taxonomy Extraction" ) );
         _options_jmenu
-        .add( _extract_taxonomy_pfam_strict_rbmi = new JRadioButtonMenuItem( "Extract Taxonomy Codes/Ids from Pfam-style Node Names" ) );
+                .add( _extract_taxonomy_pfam_strict_rbmi = new JRadioButtonMenuItem( "Extract Taxonomy Codes/Ids from Pfam-style Node Names" ) );
         _options_jmenu
-        .add( _extract_taxonomy_pfam_relaxed_rbmi = new JRadioButtonMenuItem( "Extract Taxonomy Codes/Ids from Pfam-style like Node Names" ) );
+                .add( _extract_taxonomy_pfam_relaxed_rbmi = new JRadioButtonMenuItem( "Extract Taxonomy Codes/Ids from Pfam-style like Node Names" ) );
         _options_jmenu
-        .add( _extract_taxonomy_agressive_rbmi = new JRadioButtonMenuItem( "Extract Taxonomy Codes/Ids/Scientific Names from Node Names" ) );
+                .add( _extract_taxonomy_agressive_rbmi = new JRadioButtonMenuItem( "Extract Taxonomy Codes/Ids/Scientific Names from Node Names" ) );
         _extract_taxonomy_pfam_strict_rbmi
-        .setToolTipText( "To extract taxonomy codes/ids from node names in the form of e.g. \"BCL2_MOUSE/123-304\" or \"BCL2_10090/123-304\"" );
+                .setToolTipText( "To extract taxonomy codes/ids from node names in the form of e.g. \"BCL2_MOUSE/123-304\" or \"BCL2_10090/123-304\"" );
         _extract_taxonomy_pfam_relaxed_rbmi
-        .setToolTipText( "To extract taxonomy codes/ids from node names in the form of e.g. \"bax_MOUSE\" or \"bax_10090\"" );
+                .setToolTipText( "To extract taxonomy codes/ids from node names in the form of e.g. \"bax_MOUSE\" or \"bax_10090\"" );
         _extract_taxonomy_agressive_rbmi
-        .setToolTipText( "To extract taxonomy codes/ids or scientific names from node names in the form of e.g. \"MOUSE\" or \"10090\" or \"xyz_Nematostella_vectensis\"" );
+                .setToolTipText( "To extract taxonomy codes/ids or scientific names from node names in the form of e.g. \"MOUSE\" or \"10090\" or \"xyz_Nematostella_vectensis\"" );
         _radio_group_2 = new ButtonGroup();
         _radio_group_2.add( _extract_taxonomy_no_rbmi );
         _radio_group_2.add( _extract_taxonomy_pfam_strict_rbmi );
@@ -1882,27 +1932,28 @@ public final class MainFrameApplication extends MainFrame {
         _radio_group_2.add( _extract_taxonomy_agressive_rbmi );
         _options_jmenu.add( customizeMenuItemAsLabel( new JMenuItem( "Newick/Nexus Save:" ), getConfiguration() ) );
         _options_jmenu
-        .add( _use_brackets_for_conf_in_nh_export_cbmi = new JCheckBoxMenuItem( USE_BRACKETS_FOR_CONF_IN_NH_LABEL ) );
+                .add( _use_brackets_for_conf_in_nh_export_cbmi = new JCheckBoxMenuItem( USE_BRACKETS_FOR_CONF_IN_NH_LABEL ) );
         _use_brackets_for_conf_in_nh_export_cbmi
-        .setToolTipText( "e.g. \"0.1[90]\" for a branch with support 90 and a length of 0.1" );
+                .setToolTipText( "e.g. \"0.1[90]\" for a branch with support 90 and a length of 0.1" );
         _options_jmenu
-        .add( _use_internal_names_for_conf_in_nh_export_cbmi = new JCheckBoxMenuItem( USE_INTERNAL_NAMES_FOR_CONF_IN_NH_LABEL ) );
+                .add( _use_internal_names_for_conf_in_nh_export_cbmi = new JCheckBoxMenuItem( USE_INTERNAL_NAMES_FOR_CONF_IN_NH_LABEL ) );
         customizeJMenuItem( _choose_font_mi );
         customizeJMenuItem( _choose_minimal_confidence_mi );
         customizeJMenuItem( _switch_colors_mi );
         customizeJMenuItem( _choose_pdf_width_mi );
         customizeJMenuItem( _overview_placment_mi );
-        customizeCheckBoxMenuItem( _show_default_node_shapes_external_cbmi, getOptions()
-                                   .isShowDefaultNodeShapesExternal() );
-        customizeCheckBoxMenuItem( _show_default_node_shapes_internal_cbmi, getOptions()
-                                   .isShowDefaultNodeShapesInternal() );
-        customizeCheckBoxMenuItem( _show_default_node_shapes_for_marked_cbmi, getOptions()
-                                   .isShowDefaultNodeShapesForMarkedNodes() );
+        customizeCheckBoxMenuItem( _show_default_node_shapes_external_cbmi,
+                                   getOptions().isShowDefaultNodeShapesExternal() );
+        customizeCheckBoxMenuItem( _show_default_node_shapes_internal_cbmi,
+                                   getOptions().isShowDefaultNodeShapesInternal() );
+        customizeCheckBoxMenuItem( _show_default_node_shapes_for_marked_cbmi,
+                                   getOptions().isShowDefaultNodeShapesForMarkedNodes() );
         customizeJMenuItem( _cycle_node_shape_mi );
         customizeJMenuItem( _cycle_node_fill_mi );
         customizeJMenuItem( _choose_node_size_mi );
         customizeJMenuItem( _cycle_data_return );
-        customizeCheckBoxMenuItem( _color_labels_same_as_parent_branch, getOptions().isColorLabelsSameAsParentBranch() );
+        customizeCheckBoxMenuItem( _color_labels_same_as_parent_branch,
+                                   getOptions().isColorLabelsSameAsParentBranch() );
         customizeCheckBoxMenuItem( _color_by_taxonomic_group_cbmi, getOptions().isColorByTaxonomicGroup() );
         customizeCheckBoxMenuItem( _screen_antialias_cbmi, getOptions().isAntialiasScreen() );
         customizeCheckBoxMenuItem( _background_gradient_cbmi, getOptions().isBackgroundColorGradient() );
@@ -1922,8 +1973,8 @@ public final class MainFrameApplication extends MainFrame {
                                    getOptions().getNodeLabelDirection() == NODE_LABEL_DIRECTION.RADIAL );
         customizeCheckBoxMenuItem( _antialias_print_cbmi, getOptions().isAntialiasPrint() );
         customizeCheckBoxMenuItem( _print_black_and_white_cbmi, getOptions().isPrintBlackAndWhite() );
-        customizeCheckBoxMenuItem( _internal_number_are_confidence_for_nh_parsing_cbmi, getOptions()
-                                   .isInternalNumberAreConfidenceForNhParsing() );
+        customizeCheckBoxMenuItem( _internal_number_are_confidence_for_nh_parsing_cbmi,
+                                   getOptions().isInternalNumberAreConfidenceForNhParsing() );
         customizeRadioButtonMenuItem( _extract_taxonomy_no_rbmi,
                                       getOptions().getTaxonomyExtraction() == TAXONOMY_EXTRACTION.NO );
         customizeRadioButtonMenuItem( _extract_taxonomy_pfam_strict_rbmi,
@@ -1933,20 +1984,23 @@ public final class MainFrameApplication extends MainFrame {
         customizeRadioButtonMenuItem( _extract_taxonomy_agressive_rbmi,
                                       getOptions().getTaxonomyExtraction() == TAXONOMY_EXTRACTION.AGGRESSIVE );
         customizeCheckBoxMenuItem( _replace_underscores_cbmi, getOptions().isReplaceUnderscoresInNhParsing() );
-        customizeCheckBoxMenuItem( _allow_errors_in_distance_to_parent_cbmi, getOptions()
-                                   .isReplaceUnderscoresInNhParsing() );
+        customizeCheckBoxMenuItem( _allow_errors_in_distance_to_parent_cbmi,
+                                   getOptions().isReplaceUnderscoresInNhParsing() );
         customizeCheckBoxMenuItem( _search_with_regex_cbmi, getOptions().isSearchWithRegex() );
         customizeCheckBoxMenuItem( _search_whole_words_only_cbmi, getOptions().isMatchWholeTermsOnly() );
         customizeCheckBoxMenuItem( _inverse_search_result_cbmi, getOptions().isInverseSearchResult() );
-        customizeCheckBoxMenuItem( _color_all_found_nodes_when_coloring_subtree_cbmi, getOptions().isColorAllFoundNodesWhenColoringSubtree() ); 
-        customizeCheckBoxMenuItem( _parse_beast_style_extended_nexus_tags_cbmi, getOptions().isParseBeastStyleExtendedNexusTags() ); 
-        
+        customizeCheckBoxMenuItem( _color_all_found_nodes_when_coloring_subtree_cbmi,
+                                   getOptions().isColorAllFoundNodesWhenColoringSubtree() );
+        customizeCheckBoxMenuItem( _parse_beast_style_extended_nexus_tags_cbmi,
+                                   getOptions().isParseBeastStyleExtendedNexusTags() );
         customizeCheckBoxMenuItem( _graphics_export_visible_only_cbmi, getOptions().isGraphicsExportVisibleOnly() );
         customizeCheckBoxMenuItem( _show_confidence_stddev_cbmi, getOptions().isShowConfidenceStddev() );
-        customizeCheckBoxMenuItem( _use_brackets_for_conf_in_nh_export_cbmi, getOptions()
-                                   .getNhConversionSupportValueStyle() == NH_CONVERSION_SUPPORT_VALUE_STYLE.IN_SQUARE_BRACKETS );
-        customizeCheckBoxMenuItem( _use_internal_names_for_conf_in_nh_export_cbmi, getOptions()
-                                   .getNhConversionSupportValueStyle() == NH_CONVERSION_SUPPORT_VALUE_STYLE.AS_INTERNAL_NODE_NAMES );
+        customizeCheckBoxMenuItem( _use_brackets_for_conf_in_nh_export_cbmi,
+                                   getOptions()
+                                           .getNhConversionSupportValueStyle() == NH_CONVERSION_SUPPORT_VALUE_STYLE.IN_SQUARE_BRACKETS );
+        customizeCheckBoxMenuItem( _use_internal_names_for_conf_in_nh_export_cbmi,
+                                   getOptions()
+                                           .getNhConversionSupportValueStyle() == NH_CONVERSION_SUPPORT_VALUE_STYLE.AS_INTERNAL_NODE_NAMES );
         customizeCheckBoxMenuItem( _line_up_renderable_data_cbmi, getOptions().isLineUpRendarableNodeData() );
         customizeCheckBoxMenuItem( _right_line_up_domains_cbmi, getOptions().isRightLineUpDomains() );
         _jmenubar.add( _options_jmenu );
@@ -1962,11 +2016,11 @@ public final class MainFrameApplication extends MainFrame {
             _inference_menu.add( _inference_from_seqs_item = new JMenuItem( "From Unaligned Sequences..." ) );
             customizeJMenuItem( _inference_from_seqs_item );
             _inference_from_seqs_item
-            .setToolTipText( "Basic phylogenetic inference including multiple sequence alignment" );
+                    .setToolTipText( "Basic phylogenetic inference including multiple sequence alignment" );
         }
         else {
             _inference_menu
-            .add( _inference_from_seqs_item = new JMenuItem( "From Unaligned Sequences (no program found)" ) );
+                    .add( _inference_from_seqs_item = new JMenuItem( "From Unaligned Sequences (no program found)" ) );
             customizeJMenuItem( _inference_from_seqs_item );
             _inference_from_seqs_item.setEnabled( false );
         }
@@ -1985,7 +2039,7 @@ public final class MainFrameApplication extends MainFrame {
         _tools_menu.addSeparator();
         _tools_menu.add( _remove_visual_styles_item = new JMenuItem( "Delete All Visual Styles From Nodes" ) );
         _remove_visual_styles_item
-        .setToolTipText( "To remove all node visual styles (fonts, colors) from the current phylogeny" );
+                .setToolTipText( "To remove all node visual styles (fonts, colors) from the current phylogeny" );
         customizeJMenuItem( _remove_visual_styles_item );
         _tools_menu.add( _remove_branch_color_item = new JMenuItem( "Delete All Colors From Branches" ) );
         _remove_branch_color_item.setToolTipText( "To remove all branch color values from the current phylogeny" );
@@ -2007,26 +2061,29 @@ public final class MainFrameApplication extends MainFrame {
         _tools_menu.add( _collapse_species_specific_subtrees = new JMenuItem( "Collapse Species-Specific Subtrees" ) );
         customizeJMenuItem( _collapse_species_specific_subtrees );
         _collapse_species_specific_subtrees.setToolTipText( "To (reversibly) collapse species-specific subtrees" );
+        _tools_menu.add( _collapse_by_taxonomic_rank = new JMenuItem( "Collapse By Taxonomic Rank" ) );
+        customizeJMenuItem( _collapse_by_taxonomic_rank );
+        _collapse_by_taxonomic_rank.setToolTipText( "To (reversibly) collapse subtrees by taxonomic rank" );
         _tools_menu
-        .add( _collapse_below_threshold = new JMenuItem( "Collapse Branches with Confidence Below Threshold into Multifurcations" ) );
+                .add( _collapse_below_threshold = new JMenuItem( "Collapse Branches with Confidence Below Threshold into Multifurcations" ) );
         customizeJMenuItem( _collapse_below_threshold );
         _collapse_below_threshold
-        .setToolTipText( "To (permanently) collapse branches with confidence values below a threshold into multifurcations (in the case of multiple confidences per branch: without at least one confidence value above a threshold)" );
+                .setToolTipText( "To (permanently) collapse branches with confidence values below a threshold into multifurcations (in the case of multiple confidences per branch: without at least one confidence value above a threshold)" );
         //
         _tools_menu
-        .add( _collapse_below_branch_length = new JMenuItem( "Collapse Branches with Branch Lengths Below Threshold into Multifurcations" ) );
+                .add( _collapse_below_branch_length = new JMenuItem( "Collapse Branches with Branch Lengths Below Threshold into Multifurcations" ) );
         customizeJMenuItem( _collapse_below_branch_length );
         _collapse_below_branch_length
-        .setToolTipText( "To (permanently) collapse branches with branches with branch lengths below a threshold into multifurcations" );
+                .setToolTipText( "To (permanently) collapse branches with branches with branch lengths below a threshold into multifurcations" );
         //
         _tools_menu.addSeparator();
         _tools_menu
-        .add( _extract_tax_code_from_node_names_jmi = new JMenuItem( "Extract Taxonomic Data from Node Names" ) );
+                .add( _extract_tax_code_from_node_names_jmi = new JMenuItem( "Extract Taxonomic Data from Node Names" ) );
         customizeJMenuItem( _extract_tax_code_from_node_names_jmi );
         _extract_tax_code_from_node_names_jmi
-        .setToolTipText( "To extract SwissProt/Uniprot taxonomic codes (mnemonics) from nodes names in the form of 'xyz_CAEEL', Uniprot/NCBI identifiers form of 'xyz_6239', or scientific names form of 'xyz_Caenorhabditis_elegans'" );
+                .setToolTipText( "To extract SwissProt/Uniprot taxonomic codes (mnemonics) from nodes names in the form of 'xyz_CAEEL', Uniprot/NCBI identifiers form of 'xyz_6239', or scientific names form of 'xyz_Caenorhabditis_elegans'" );
         _tools_menu
-        .add( _move_node_names_to_tax_sn_jmi = new JMenuItem( "Transfer Node Names to Taxonomic Scientific Names" ) );
+                .add( _move_node_names_to_tax_sn_jmi = new JMenuItem( "Transfer Node Names to Taxonomic Scientific Names" ) );
         customizeJMenuItem( _move_node_names_to_tax_sn_jmi );
         _move_node_names_to_tax_sn_jmi.setToolTipText( "To interpret node names as taxonomic scientific names" );
         _tools_menu.add( _move_node_names_to_seq_names_jmi = new JMenuItem( "Transfer Node Names to Sequence Names" ) );
@@ -2037,15 +2094,15 @@ public final class MainFrameApplication extends MainFrame {
         customizeJMenuItem( _obtain_seq_information_jmi );
         _obtain_seq_information_jmi.setToolTipText( "To add additional sequence information" );
         _tools_menu
-        .add( _obtain_detailed_taxonomic_information_jmi = new JMenuItem( OBTAIN_DETAILED_TAXONOMIC_INFORMATION ) );
+                .add( _obtain_detailed_taxonomic_information_jmi = new JMenuItem( OBTAIN_DETAILED_TAXONOMIC_INFORMATION ) );
         customizeJMenuItem( _obtain_detailed_taxonomic_information_jmi );
         _obtain_detailed_taxonomic_information_jmi
-        .setToolTipText( "To add additional taxonomic information (from UniProt Taxonomy)" );
+                .setToolTipText( "To add additional taxonomic information (from UniProt Taxonomy)" );
         _tools_menu
-        .add( _obtain_detailed_taxonomic_information_deleting_jmi = new JMenuItem( "Obtain Detailed Taxonomic Information (deletes nodes!)" ) );
+                .add( _obtain_detailed_taxonomic_information_deleting_jmi = new JMenuItem( "Obtain Detailed Taxonomic Information (deletes nodes!)" ) );
         customizeJMenuItem( _obtain_detailed_taxonomic_information_deleting_jmi );
         _obtain_detailed_taxonomic_information_deleting_jmi
-        .setToolTipText( "To add additional taxonomic information, deletes nodes for which taxonomy cannot found (from UniProt Taxonomy)" );
+                .setToolTipText( "To add additional taxonomic information, deletes nodes for which taxonomy cannot found (from UniProt Taxonomy)" );
         _tools_menu.addSeparator();
         _tools_menu.add( _read_values_jmi = new JMenuItem( "Attach Vector/Expression Values" ) );
         customizeJMenuItem( _read_values_jmi );
@@ -2054,7 +2111,7 @@ public final class MainFrameApplication extends MainFrame {
         _tools_menu.add( _read_seqs_jmi = new JMenuItem( "Attach Molecular Sequences" ) );
         customizeJMenuItem( _read_seqs_jmi );
         _read_seqs_jmi
-        .setToolTipText( "To attach molecular sequences to tree nodes (from Fasta-formatted file) (beta)" );
+                .setToolTipText( "To attach molecular sequences to tree nodes (from Fasta-formatted file) (beta)" );
         _jmenubar.add( _tools_menu );
     }
 
@@ -2085,10 +2142,11 @@ public final class MainFrameApplication extends MainFrame {
         URL url = null;
         Phylogeny[] phys = null;
         final String message = "Please enter a complete URL, for example \"http://purl.org/phylo/treebase/phylows/study/TB2:S15480?format=nexus\"";
-        final String url_string = JOptionPane.showInputDialog( this,
-                                                               message,
-                                                               "Use URL/webservice to obtain a phylogeny",
-                                                               JOptionPane.QUESTION_MESSAGE );
+        final String url_string = JOptionPane
+                .showInputDialog( this,
+                                  message,
+                                  "Use URL/webservice to obtain a phylogeny",
+                                  JOptionPane.QUESTION_MESSAGE );
         boolean nhx_or_nexus = false;
         if ( ( url_string != null ) && ( url_string.length() > 0 ) ) {
             try {
@@ -2098,8 +2156,9 @@ public final class MainFrameApplication extends MainFrame {
                     parser = new TolParser();
                 }
                 else {
-                    parser = ParserUtils.createParserDependingOnUrlContents( url, getConfiguration()
-                                                                             .isValidatePhyloXmlAgainstSchema() );
+                    parser = ParserUtils
+                            .createParserDependingOnUrlContents( url,
+                                                                 getConfiguration().isValidatePhyloXmlAgainstSchema() );
                 }
                 if ( parser instanceof NexusPhylogeniesParser ) {
                     nhx_or_nexus = true;
@@ -2126,8 +2185,8 @@ public final class MainFrameApplication extends MainFrame {
                 JOptionPane.showMessageDialog( this,
                                                "Could not read from " + url + "\n"
                                                        + ForesterUtil.wordWrap( e.getLocalizedMessage(), 80 ),
-                                                       "Failed to read URL",
-                                                       JOptionPane.ERROR_MESSAGE );
+                                               "Failed to read URL",
+                                               JOptionPane.ERROR_MESSAGE );
             }
             catch ( final Exception e ) {
                 JOptionPane.showMessageDialog( this,
@@ -2198,11 +2257,10 @@ public final class MainFrameApplication extends MainFrame {
 
     static void warnIfNotPhyloXmlValidation( final Configuration c ) {
         if ( !c.isValidatePhyloXmlAgainstSchema() ) {
-            JOptionPane
-            .showMessageDialog( null,
-                                ForesterUtil
-                                .wordWrap( "phyloXML XSD-based validation is turned off [enable with line 'validate_against_phyloxml_xsd_schem: true' in configuration file]",
-                                           80 ),
+            JOptionPane.showMessageDialog( null,
+                                           ForesterUtil.wordWrap(
+                                                                  "phyloXML XSD-based validation is turned off [enable with line 'validate_against_phyloxml_xsd_schem: true' in configuration file]",
+                                                                  80 ),
                                            "Warning",
                                            JOptionPane.WARNING_MESSAGE );
         }
index a20689d..c60d06a 100644 (file)
@@ -49,6 +49,7 @@ import java.awt.event.MouseEvent;
 import java.awt.event.MouseWheelEvent;
 import java.awt.event.MouseWheelListener;
 import java.awt.font.FontRenderContext;
+import java.awt.font.TextAttribute;
 import java.awt.font.TextLayout;
 import java.awt.geom.AffineTransform;
 import java.awt.geom.Arc2D;
@@ -68,6 +69,7 @@ import java.io.UnsupportedEncodingException;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.net.URLEncoder;
+import java.text.AttributedString;
 import java.text.DecimalFormat;
 import java.text.DecimalFormatSymbols;
 import java.text.NumberFormat;
@@ -77,6 +79,7 @@ import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Hashtable;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 import java.util.SortedSet;
 
@@ -313,6 +316,7 @@ public final class TreePanel extends JPanel implements ActionListener, MouseWhee
     private float                        _y_distance                                        = 0.0f;
     private int                          _length_of_longest_text;
     private int                          _longest_domain;
+    private Map<String, AttributedString> _attributed_string_map = null;
     static {
         final DecimalFormatSymbols dfs = new DecimalFormatSymbols();
         dfs.setDecimalSeparator( '.' );
@@ -1396,6 +1400,12 @@ public final class TreePanel extends JPanel implements ActionListener, MouseWhee
             case GET_EXT_DESC_DATA:
                 showExtDescNodeData( node );
                 break;
+            case UNCOLLAPSE_ALL:
+                uncollapseAll( node );
+                break;
+            case ORDER_SUBTREE:
+                orderSubtree( node );
+                break;
             default:
                 throw new IllegalArgumentException( "unknown action: " + action );
         }
@@ -1801,6 +1811,9 @@ public final class TreePanel extends JPanel implements ActionListener, MouseWhee
             else if ( title.equals( Configuration.clickto_options[ Configuration.sort_descendents ][ 0 ] ) ) {
                 _node_popup_menu_items[ i ].setEnabled( node.getNumberOfDescendants() > 1 );
             }
+            else if ( title.equals( Configuration.clickto_options[ Configuration.uncollapse_all ][ 0 ] ) ) {
+                _node_popup_menu_items[ i ].setEnabled( isCanUncollapseAll( node ) );
+            }
             _node_popup_menu_items[ i ].addActionListener( this );
             _node_popup_menu.add( _node_popup_menu_items[ i ] );
         }
@@ -1857,6 +1870,11 @@ public final class TreePanel extends JPanel implements ActionListener, MouseWhee
     }
 
     private final void nodeTaxonomyDataAsSB( final Taxonomy taxonomy, final StringBuilder sb ) {
+        if ( _control_panel.isShowTaxonomyRank() && !ForesterUtil.isEmpty( taxonomy.getRank() ) ) {
+            sb.append( "[" );
+            sb.append( taxonomy.getRank() );
+            sb.append( "] " );
+        }
         if ( _control_panel.isShowTaxonomyCode() && !ForesterUtil.isEmpty( taxonomy.getTaxonomyCode() ) ) {
             sb.append( taxonomy.getTaxonomyCode() );
             sb.append( " " );
@@ -2713,7 +2731,7 @@ public final class TreePanel extends JPanel implements ActionListener, MouseWhee
             x += drawTaxonomyImage( node.getXcoord() + 2 + half_box_size, node.getYcoord(), node, g );
         }
         if ( ( getControlPanel().isShowTaxonomyCode() || getControlPanel().isShowTaxonomyScientificNames() || getControlPanel()
-                .isShowTaxonomyCommonNames() ) && node.getNodeData().isHasTaxonomy() ) {
+                .isShowTaxonomyCommonNames() || getControlPanel().isShowTaxonomyRank() ) && node.getNodeData().isHasTaxonomy() ) {
             x += paintTaxonomy( g, node, is_in_found_nodes, to_pdf, to_graphics_file, x );
         }
         setColor( g, node, to_graphics_file, to_pdf, is_in_found_nodes, getTreeColorSet().getSequenceColor() );
@@ -2799,7 +2817,12 @@ public final class TreePanel extends JPanel implements ActionListener, MouseWhee
             }
         }
         if ( sb_str.length() > 0 ) {
-            TreePanel.drawString( sb_str, pos_x, pos_y, g );
+            if ( !isAllowAttributedStrings() ) {
+                TreePanel.drawString( sb_str, pos_x, pos_y, g );
+            }
+            else {
+                drawStringX( sb_str, pos_x, pos_y, g );
+            }
         }
         // GUILHEM_END _____________
         if ( _sb.length() > 0 ) {
@@ -2869,6 +2892,10 @@ public final class TreePanel extends JPanel implements ActionListener, MouseWhee
         return x;
     }
 
+    private final boolean isAllowAttributedStrings() {
+        return false;
+    }
+
     final private void paintNodeDataUnrootedCirc( final Graphics2D g,
                                                   final PhylogenyNode node,
                                                   final boolean to_pdf,
@@ -4693,6 +4720,29 @@ public final class TreePanel extends JPanel implements ActionListener, MouseWhee
             repaint();
         }
     }
+    
+    final void uncollapseAll( final PhylogenyNode node ) {
+        if ( getPhylogenyGraphicsType() == PHYLOGENY_GRAPHICS_TYPE.UNROOTED ) {
+            JOptionPane.showMessageDialog( this,
+                                           "Cannot uncollapse in unrooted display type",
+                                           "Attempt to uncollapse in unrooted display",
+                                           JOptionPane.WARNING_MESSAGE );
+            return;
+        }
+        if ( !node.isExternal() ) {
+            TreePanelUtil.uncollapseSubtree( node);
+            updateSetOfCollapsedExternalNodes();
+            _phylogeny.recalculateNumberOfExternalDescendants( true );
+            resetNodeIdToDistToLeafMap();
+            calculateLongestExtNodeInfo();
+            setNodeInPreorderToNull();
+            _control_panel.displayedPhylogenyMightHaveChanged( true );
+            resetPreferredSize();
+            updateOvSizes();
+            _main_panel.adjustJScrollPane();
+            repaint();
+        }
+    }
 
     final void collapseSpeciesSpecificSubtrees() {
         if ( ( _phylogeny == null ) || ( _phylogeny.getNumberOfExternalNodes() < 2 ) ) {
@@ -4711,6 +4761,44 @@ public final class TreePanel extends JPanel implements ActionListener, MouseWhee
         repaint();
     }
 
+    final void collapseByTaxonomicRank( final String rank ) {
+        if ( ( _phylogeny == null ) || ( _phylogeny.getNumberOfExternalNodes() < 2 ) ) {
+            return;
+        }
+        setWaitCursor();
+        
+        final int collapsed = TreePanelUtil.collapseByTaxonomicRank( _phylogeny, rank, this );
+       
+        setArrowCursor();
+        repaint();
+        if ( collapsed > 0 ) {
+            String msg = "Collapsing via " + rank + " completed:\n";
+            if ( collapsed > 1 ) {
+                msg += "collapsed " + collapsed + " subtrees";
+            }
+            else {
+                msg += "collapsed one subtree";
+            }
+            setEdited( true );
+            JOptionPane.showMessageDialog( this,
+                                           msg,
+                                           "Taxonomy Rank-Collapsing Completed (" + rank + ")",
+                                           JOptionPane.INFORMATION_MESSAGE );
+        }
+        else {
+            String msg = "Could not taxonomy rank-collapse any subtree via " + rank + ".\n";
+            msg += "Possible solutions (given that suitable taxonomic information is present):\n";
+            msg += "select a different rank (e.g. phylum, genus, ...)\n";
+            msg += "  and/or\n";
+            msg += "execute:\n";
+            msg += "1. \"" + MainFrameApplication.OBTAIN_DETAILED_TAXONOMIC_INFORMATION + "\" (Tools)\n";
+            msg += "2. \"" + MainFrameApplication.INFER_ANCESTOR_TAXONOMIES + "\" (Analysis)";
+            JOptionPane.showMessageDialog( this, msg, "Taxonomy Rank-Collapsing Failed", JOptionPane.WARNING_MESSAGE );
+        }
+    }
+    
+    
+    
     final void colorRank( final String rank ) {
         if ( ( _phylogeny == null ) || ( _phylogeny.getNumberOfExternalNodes() < 2 ) ) {
             return;
@@ -4745,18 +4833,18 @@ public final class TreePanel extends JPanel implements ActionListener, MouseWhee
             setEdited( true );
             JOptionPane.showMessageDialog( this,
                                            msg,
-                                           "Taxonomy Colorization Completed (" + rank + ")",
+                                           "Taxonomy Rank-Colorization Completed (" + rank + ")",
                                            JOptionPane.INFORMATION_MESSAGE );
         }
         else {
-            String msg = "Could not taxonomy colorize any subtree via " + rank + ".\n";
+            String msg = "Could not taxonomy rank-colorize any subtree via " + rank + ".\n";
             msg += "Possible solutions (given that suitable taxonomic information is present):\n";
             msg += "select a different rank (e.g. phylum, genus, ...)\n";
             msg += "  and/or\n";
             msg += "execute:\n";
             msg += "1. \"" + MainFrameApplication.OBTAIN_DETAILED_TAXONOMIC_INFORMATION + "\" (Tools)\n";
             msg += "2. \"" + MainFrameApplication.INFER_ANCESTOR_TAXONOMIES + "\" (Analysis)";
-            JOptionPane.showMessageDialog( this, msg, "Taxonomy Colorization Failed", JOptionPane.WARNING_MESSAGE );
+            JOptionPane.showMessageDialog( this, msg, "Taxonomy Rank-Colorization Failed", JOptionPane.WARNING_MESSAGE );
         }
     }
 
@@ -5001,7 +5089,23 @@ public final class TreePanel extends JPanel implements ActionListener, MouseWhee
     final boolean isCanCollapse() {
         return ( getPhylogenyGraphicsType() != PHYLOGENY_GRAPHICS_TYPE.UNROOTED );
     }
-
+    
+    final boolean isCanUncollapseAll( final PhylogenyNode node ) {
+        if ( node.isExternal() || getPhylogenyGraphicsType() == PHYLOGENY_GRAPHICS_TYPE.UNROOTED ) {
+            return false;
+        }
+        if ( node.isCollapse() ) {
+            return true;
+        }
+        final PhylogenyNodeIterator it = new PreorderTreeIterator( node );
+        while ( it.hasNext() ) {
+            if ( it.next().isCollapse() ) {
+                return true;
+            }
+        }
+        return false;
+    }
+    
     final boolean isCanColorSubtree() {
         return ( getPhylogenyGraphicsType() != PHYLOGENY_GRAPHICS_TYPE.UNROOTED );
     }
@@ -5911,6 +6015,29 @@ public final class TreePanel extends JPanel implements ActionListener, MouseWhee
         updateSubSuperTreeButton();
     }
 
+    final void orderSubtree( final PhylogenyNode node ) {
+        if ( node.isExternal() ) {
+            return;
+        }
+        DESCENDANT_SORT_PRIORITY pri = DESCENDANT_SORT_PRIORITY.NODE_NAME;
+        if ( getControlPanel().isShowTaxonomyScientificNames() || getControlPanel().isShowTaxonomyCode() ) {
+            pri = DESCENDANT_SORT_PRIORITY.TAXONOMY;
+        }
+        else if ( getControlPanel().isShowSeqNames() || getControlPanel().isShowSeqSymbols() || getControlPanel().isShowGeneNames() ) {
+            pri = DESCENDANT_SORT_PRIORITY.SEQUENCE;
+        }
+        PhylogenyMethods.orderAppearanceX( node, true, pri );
+      
+        setNodeInPreorderToNull();
+        getPhylogeny().externalNodesHaveChanged();
+        getPhylogeny().clearHashIdToNodeMap();
+        getPhylogeny().recalculateNumberOfExternalDescendants( true );
+        resetNodeIdToDistToLeafMap();
+        setEdited( true );
+        getControlPanel().displayedPhylogenyMightHaveChanged( true );
+        repaint();
+    }
+    
     final void swap( final PhylogenyNode node ) {
         if ( node.isExternal() || ( node.getNumberOfDescendants() < 2 ) ) {
             return;
@@ -6061,6 +6188,38 @@ public final class TreePanel extends JPanel implements ActionListener, MouseWhee
     final private static void drawString( final String str, final float x, final float y, final Graphics2D g ) {
         g.drawString( str, x, y );
     }
+    
+    
+    final private void drawStringX( final String str, final float x, final float y, final Graphics2D g ) {
+        //TODO
+        //FIXME
+        if ( getAttributedStringMap() == null /*&& getAttributedStringMap().containsKey(str) */ ) {
+            final AttributedString as = new AttributedString(str);
+            //Font plainFont = new Font("Times New Roman", Font.PLAIN, 24);
+            
+            as.addAttribute(TextAttribute.FONT, g.getFont());
+            as.addAttribute(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON, 1, 3);
+            as.addAttribute(TextAttribute.SUPERSCRIPT, TextAttribute.SUPERSCRIPT_SUPER, 3, 4);
+            
+            as.addAttribute(TextAttribute.FOREGROUND, Color.BLUE,  1, 2);
+            as.addAttribute(TextAttribute.FOREGROUND, Color.PINK,  3, 5);
+            as.addAttribute(TextAttribute.STRIKETHROUGH,
+                TextAttribute.STRIKETHROUGH_ON, 2, 4);
+            g.drawString(as.getIterator(), x, y);
+        }
+        else {
+            g.drawString( str, x, y );
+        }
+    }
+
+
+    private final Map<String, AttributedString> getAttributedStringMap() {
+        return _attributed_string_map ;
+    }
+    
+    private final void setAttributedStringMap( final Map<String, AttributedString> attributed_string_map ) {
+        _attributed_string_map = attributed_string_map;
+    }
 
     final private static boolean plusPressed( final int key_code ) {
         return ( ( key_code == KeyEvent.VK_ADD ) || ( key_code == KeyEvent.VK_PLUS )
index ac47498..a7d8d87 100644 (file)
@@ -149,8 +149,8 @@ public class TreePanelUtil {
         }
         if ( cp.isShowSeqSymbols() && node.getNodeData().isHasSequence()
                 && !ForesterUtil.isEmpty( node.getNodeData().getSequence().getSymbol() ) ) {
-            TreePanelUtil
-                    .showExtDescNodeDataUserSelectedHelperHelper( node.getNodeData().getSequence().getSymbol(), sb );
+            TreePanelUtil.showExtDescNodeDataUserSelectedHelperHelper( node.getNodeData().getSequence().getSymbol(),
+                                                                       sb );
         }
         if ( cp.isShowGeneNames() && node.getNodeData().isHasSequence()
                 && !ForesterUtil.isEmpty( node.getNodeData().getSequence().getGeneName() ) ) {
@@ -165,18 +165,20 @@ public class TreePanelUtil {
         }
         if ( cp.isShowTaxonomyCode() && node.getNodeData().isHasTaxonomy()
                 && !ForesterUtil.isEmpty( node.getNodeData().getTaxonomy().getTaxonomyCode() ) ) {
-            TreePanelUtil.showExtDescNodeDataUserSelectedHelperHelper( node.getNodeData().getTaxonomy()
-                    .getTaxonomyCode(), sb );
+            TreePanelUtil
+                    .showExtDescNodeDataUserSelectedHelperHelper( node.getNodeData().getTaxonomy().getTaxonomyCode(),
+                                                                  sb );
         }
         if ( cp.isShowTaxonomyScientificNames() && node.getNodeData().isHasTaxonomy()
                 && !ForesterUtil.isEmpty( node.getNodeData().getTaxonomy().getScientificName() ) ) {
-            TreePanelUtil.showExtDescNodeDataUserSelectedHelperHelper( node.getNodeData().getTaxonomy()
-                    .getScientificName(), sb );
+            TreePanelUtil
+                    .showExtDescNodeDataUserSelectedHelperHelper( node.getNodeData().getTaxonomy().getScientificName(),
+                                                                  sb );
         }
         if ( cp.isShowTaxonomyCommonNames() && node.getNodeData().isHasTaxonomy()
                 && !ForesterUtil.isEmpty( node.getNodeData().getTaxonomy().getCommonName() ) ) {
-            TreePanelUtil
-                    .showExtDescNodeDataUserSelectedHelperHelper( node.getNodeData().getTaxonomy().getCommonName(), sb );
+            TreePanelUtil.showExtDescNodeDataUserSelectedHelperHelper( node.getNodeData().getTaxonomy().getCommonName(),
+                                                                       sb );
         }
         //        if ( ( cp.isShowSeqNames() || cp.isShowSeqSymbols() || cp.isShowSequenceAcc() )
         //                && node.getNodeData().isHasSequence()
@@ -236,6 +238,17 @@ public class TreePanelUtil {
         }
     }
 
+    final static void uncollapseSubtree( final PhylogenyNode node ) {
+        node.setCollapse( false );
+        if ( node.isExternal() ) {
+            return;
+        }
+        final PhylogenyNodeIterator it = new PreorderTreeIterator( node );
+        while ( it.hasNext() ) {
+            it.next().setCollapse( false );
+        }
+    }
+
     static void colorizeSubtree( final PhylogenyNode node, final BranchColor c ) {
         node.getBranchData().setBranchColor( c );
         final List<PhylogenyNode> descs = PhylogenyMethods.getAllDescendants( node );
@@ -279,7 +292,8 @@ public class TreePanelUtil {
             if ( !n.getBranchData().isHasBranchColor() ) {
                 final Taxonomy tax = PhylogenyMethods.getExternalDescendantsTaxonomy( n );
                 if ( tax != null ) {
-                    n.getBranchData().setBranchColor( new BranchColor( tree_panel.calculateTaxonomyBasedColor( tax ) ) );
+                    n.getBranchData()
+                            .setBranchColor( new BranchColor( tree_panel.calculateTaxonomyBasedColor( tax ) ) );
                     final List<PhylogenyNode> descs = PhylogenyMethods.getAllDescendants( n );
                     for( final PhylogenyNode desc : descs ) {
                         desc.getBranchData()
@@ -290,23 +304,106 @@ public class TreePanelUtil {
         }
     }
 
-    final static int colorPhylogenyAccordingToRanks( final Phylogeny tree, final String rank, final TreePanel tree_panel ) {
+    final static int collapseByTaxonomicRank( final Phylogeny tree, final String rank, final TreePanel tree_panel ) {
+        final Set<String> true_lineage_set = new HashSet<String>();
+        for( final PhylogenyNodeIterator iter = tree.iteratorPreorder(); iter.hasNext(); ) {
+            iter.next().setCollapse( false );
+        }
+        int collapsed = 0;
+        for( final PhylogenyNodeIterator it = tree.iteratorPostorder(); it.hasNext(); ) {
+            final PhylogenyNode n = it.next();
+            if ( !n.isExternal() && n.getNodeData().isHasTaxonomy() && !ForesterUtil.isEmpty( n.getNodeData().getTaxonomy().getRank() )
+                    && n.getNodeData().getTaxonomy().getRank().equalsIgnoreCase( rank ) /*&& !n.isRoot()*/ ) {
+                TreePanelUtil.collapseSubtree( n, true );
+                ++collapsed;
+                if ( !ForesterUtil.isEmpty( n.getNodeData().getTaxonomy().getScientificName() ) ) {
+                    true_lineage_set.add( n.getNodeData().getTaxonomy().getScientificName() );
+                    System.out.println( "1 true_lineage_set added " +  n.getNodeData().getTaxonomy().getScientificName()  );
+                }
+            }
+        }
+        for( final PhylogenyNodeIterator it = tree.iteratorPostorder(); it.hasNext(); ) {
+            final PhylogenyNode node = it.next();
+            if ( ( !node.isExternal() && !node.isCollapse() ) && node.getNodeData().isHasTaxonomy()
+                    && !ForesterUtil.isEmpty( node.getNodeData().getTaxonomy().getLineage() ) /* && !node.isRoot()*/ ) {
+                boolean success = false;
+                if ( !true_lineage_set.isEmpty() ) {
+                    for( final String lin : node.getNodeData().getTaxonomy().getLineage() ) {
+                        if ( true_lineage_set.contains( lin ) ) {
+                            //TreePanelUtil
+                            //     .colorizeSubtree( node, new BranchColor( true_lineage_to_color_map.get( lin ) ) );
+                            TreePanelUtil.collapseSubtree( node, true );
+                            ++collapsed;
+                            success = true;
+                            break;
+                        }
+                    }
+                }
+                if ( !success ) {
+                    final Map<String, String> lineage_to_rank_map = MainPanel.getLineageToRankMap();
+                    for( final String lin : node.getNodeData().getTaxonomy().getLineage() ) {
+                        final Taxonomy temp_tax = new Taxonomy();
+                        temp_tax.setScientificName( lin );
+                        if ( lineage_to_rank_map.containsKey( lin )
+                                && !ForesterUtil.isEmpty( lineage_to_rank_map.get( lin ) )
+                                && lineage_to_rank_map.get( lin ).equalsIgnoreCase( rank ) ) {
+                            //final BranchColor c = new BranchColor( tree_panel.calculateTaxonomyBasedColor( temp_tax ) );
+                            //TreePanelUtil.colorizeSubtree( node, c );
+                            TreePanelUtil.collapseSubtree( node, true );
+                            ++collapsed;
+                            true_lineage_set.add( lin );
+                            System.out.println( "2 true_lineage_set added " +  lin  );
+                            break;
+                        }
+                        else {
+                            UniProtTaxonomy up = null;
+                            try {
+                                up = TaxonomyDataManager.obtainUniProtTaxonomy( temp_tax, null, null );
+                            }
+                            catch ( final Exception e ) {
+                                e.printStackTrace();
+                            }
+                            if ( ( up != null ) && !ForesterUtil.isEmpty( up.getRank() ) ) {
+                                lineage_to_rank_map.put( lin, up.getRank() );
+                                System.out.println( lin + "->" + up.getRank() );
+                                if ( up.getRank().equalsIgnoreCase( rank ) ) {
+                                    // final BranchColor c = new BranchColor( tree_panel.calculateTaxonomyBasedColor( temp_tax ) );
+                                    // TreePanelUtil.colorizeSubtree( node, c );
+                                    TreePanelUtil.collapseSubtree( node, true );
+                                    ++collapsed;
+                                    true_lineage_set.add( lin );
+                                    System.out.println( "3 true_lineage_set added " +  lin  );
+                                    break;
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        return collapsed;
+    }
+
+    final static int colorPhylogenyAccordingToRanks( final Phylogeny tree,
+                                                     final String rank,
+                                                     final TreePanel tree_panel ) {
         final Map<String, Color> true_lineage_to_color_map = new HashMap<String, Color>();
         int colorizations = 0;
         for( final PhylogenyNodeIterator it = tree.iteratorPostorder(); it.hasNext(); ) {
             final PhylogenyNode n = it.next();
             if ( n.getNodeData().isHasTaxonomy()
                     && ( !ForesterUtil.isEmpty( n.getNodeData().getTaxonomy().getScientificName() )
-                            || !ForesterUtil.isEmpty( n.getNodeData().getTaxonomy().getCommonName() ) || !ForesterUtil
-                                .isEmpty( n.getNodeData().getTaxonomy().getTaxonomyCode() ) ) ) {
+                            || !ForesterUtil.isEmpty( n.getNodeData().getTaxonomy().getCommonName() )
+                            || !ForesterUtil.isEmpty( n.getNodeData().getTaxonomy().getTaxonomyCode() ) ) ) {
                 if ( !ForesterUtil.isEmpty( n.getNodeData().getTaxonomy().getRank() )
                         && n.getNodeData().getTaxonomy().getRank().equalsIgnoreCase( rank ) ) {
-                    final BranchColor c = new BranchColor( tree_panel.calculateTaxonomyBasedColor( n.getNodeData()
-                            .getTaxonomy() ) );
+                    final BranchColor c = new BranchColor( tree_panel
+                            .calculateTaxonomyBasedColor( n.getNodeData().getTaxonomy() ) );
                     TreePanelUtil.colorizeSubtree( n, c );
                     ++colorizations;
                     if ( !ForesterUtil.isEmpty( n.getNodeData().getTaxonomy().getScientificName() ) ) {
-                        true_lineage_to_color_map.put( n.getNodeData().getTaxonomy().getScientificName(), c.getValue() );
+                        true_lineage_to_color_map.put( n.getNodeData().getTaxonomy().getScientificName(),
+                                                       c.getValue() );
                     }
                 }
             }
@@ -319,8 +416,8 @@ public class TreePanelUtil {
                 if ( !true_lineage_to_color_map.isEmpty() ) {
                     for( final String lin : node.getNodeData().getTaxonomy().getLineage() ) {
                         if ( true_lineage_to_color_map.containsKey( lin ) ) {
-                            TreePanelUtil
-                                    .colorizeSubtree( node, new BranchColor( true_lineage_to_color_map.get( lin ) ) );
+                            TreePanelUtil.colorizeSubtree( node,
+                                                           new BranchColor( true_lineage_to_color_map.get( lin ) ) );
                             ++colorizations;
                             success = true;
                             break;
@@ -351,8 +448,10 @@ public class TreePanelUtil {
                             }
                             if ( ( up != null ) && !ForesterUtil.isEmpty( up.getRank() ) ) {
                                 lineage_to_rank_map.put( lin, up.getRank() );
+                                System.out.println( lin + "->" + up.getRank() );
                                 if ( up.getRank().equalsIgnoreCase( rank ) ) {
-                                    final BranchColor c = new BranchColor( tree_panel.calculateTaxonomyBasedColor( temp_tax ) );
+                                    final BranchColor c = new BranchColor( tree_panel
+                                            .calculateTaxonomyBasedColor( temp_tax ) );
                                     TreePanelUtil.colorizeSubtree( node, c );
                                     ++colorizations;
                                     true_lineage_to_color_map.put( lin, c.getValue() );
@@ -367,7 +466,8 @@ public class TreePanelUtil {
         return colorizations;
     }
 
-    final static String createAnnotationString( final SortedSet<Annotation> annotations, final boolean show_ref_sources ) {
+    final static String createAnnotationString( final SortedSet<Annotation> annotations,
+                                                final boolean show_ref_sources ) {
         final SortedMap<String, List<Annotation>> m = new TreeMap<String, List<Annotation>>();
         for( final Annotation an : annotations ) {
             final String ref_source = ForesterUtil.isEmpty( an.getRefSource() ) ? "?" : an.getRefSource();
@@ -435,8 +535,8 @@ public class TreePanelUtil {
 
     final static boolean isTaxonomyEmpty( final Taxonomy tax ) {
         return ( ( tax.getIdentifier() == null ) && ForesterUtil.isEmpty( tax.getTaxonomyCode() )
-                && ForesterUtil.isEmpty( tax.getCommonName() ) && ForesterUtil.isEmpty( tax.getScientificName() ) && tax
-                .getSynonyms().isEmpty() );
+                && ForesterUtil.isEmpty( tax.getCommonName() ) && ForesterUtil.isEmpty( tax.getScientificName() )
+                && tax.getSynonyms().isEmpty() );
     }
 
     static final int nodeDataIntoStringBuffer( final List<String> data, final Options optz, final StringBuilder sb ) {
index 1db3384..d9db39d 100644 (file)
@@ -125,6 +125,7 @@ public final class PhyloXmlMapping {
     public static final String TAXONOMY_RANK                                       = "rank";
     public static final String TAXONOMY_SCIENTIFIC_NAME                            = "scientific_name";
     public static final String TAXONOMY_SYNONYM                                    = "synonym";
+    public static final String TAXONOMY_LINEAGE                                    = "lineage";
     public static final String TYPE_ATTR                                           = "type";
     public static final String URI                                                 = "uri";
     public static final String URI_DESC_ATTR                                       = "desc";
index f55028f..74d11df 100644 (file)
@@ -25,6 +25,8 @@
 
 package org.forester.io.parsers.phyloxml.data;
 
+import java.util.Arrays;
+
 import org.forester.io.parsers.phyloxml.PhyloXmlDataFormatException;
 import org.forester.io.parsers.phyloxml.PhyloXmlMapping;
 import org.forester.io.parsers.phyloxml.XmlElement;
@@ -77,6 +79,12 @@ public class TaxonomyParser implements PhylogenyDataPhyloXmlParser {
                 else if ( child_element.getQualifiedName().equals( PhyloXmlMapping.URI ) ) {
                     taxonomy.addUri( ( Uri ) UriParser.getInstance().parse( child_element ) );
                 }
+                else if ( child_element.getQualifiedName().equals( PhyloXmlMapping.TAXONOMY_LINEAGE ) ) {
+                    final String[] lineage = child_element.getValueAsString().split( "," );
+                    if ( lineage != null && lineage.length > 0 ) {
+                       taxonomy.setLineage( Arrays.asList(lineage) );
+                    }
+                }
             }
         }
         return taxonomy;
index a5cf36a..09f9955 100644 (file)
@@ -68,6 +68,8 @@ import org.forester.util.ForesterUtil;
 
 public class PhylogenyMethods {
 
+    private static boolean _order_changed;
+
     private PhylogenyMethods() {
         // Hidden constructor.
     }
@@ -814,13 +816,13 @@ public class PhylogenyMethods {
             return;
         }
         else {
-            PhylogenyNode temp = null;
             if ( ( n.getNumberOfDescendants() == 2 )
                     && ( n.getChildNode1().getNumberOfExternalNodes() != n.getChildNode2().getNumberOfExternalNodes() )
                     && ( ( n.getChildNode1().getNumberOfExternalNodes() < n.getChildNode2().getNumberOfExternalNodes() ) == order ) ) {
-                temp = n.getChildNode1();
+                final PhylogenyNode temp = n.getChildNode1();
                 n.setChild1( n.getChildNode2() );
                 n.setChild2( temp );
+                _order_changed = true;
             }
             else if ( order_ext_alphabetically ) {
                 boolean all_ext = true;
@@ -839,6 +841,27 @@ public class PhylogenyMethods {
             }
         }
     }
+    
+    public synchronized static void orderAppearanceX( final PhylogenyNode n,
+                                                      final boolean order_ext_alphabetically,
+                                                      final DESCENDANT_SORT_PRIORITY pri ) {
+        if ( n.isExternal() ) {
+            return;
+        }
+        else {
+           _order_changed = false;
+           orderAppearance( n,
+                            true,
+                            order_ext_alphabetically,
+                            pri );
+           if (!_order_changed ) {
+               orderAppearance( n,
+                                false,
+                                order_ext_alphabetically,
+                                pri );
+           }
+        }
+    }
 
     public static void postorderBranchColorAveragingExternalNodeBased( final Phylogeny p ) {
         for( final PhylogenyNodeIterator iter = p.iteratorPostorder(); iter.hasNext(); ) {
index 4a333a2..8a2dc33 100644 (file)
@@ -248,8 +248,8 @@ public class Taxonomy implements PhylogenyData, MultipleUris, Comparable<Taxonom
 
     public boolean isEmpty() {
         return ( ( getIdentifier() == null ) && ForesterUtil.isEmpty( getTaxonomyCode() )
-                && ForesterUtil.isEmpty( getCommonName() ) && ForesterUtil.isEmpty( getScientificName() ) && ForesterUtil
-                .isEmpty( _lineage ) );
+                && ForesterUtil.isEmpty( getCommonName() ) && ForesterUtil.isEmpty( getScientificName() )
+                && ForesterUtil.isEmpty( _lineage ) );
     }
 
     /**
@@ -391,8 +391,10 @@ public class Taxonomy implements PhylogenyData, MultipleUris, Comparable<Taxonom
             PhylogenyDataUtil.appendElement( writer, PhyloXmlMapping.TAXONOMY_AUTHORITY, getAuthority(), indentation );
         }
         if ( !ForesterUtil.isEmpty( getCommonName() ) ) {
-            PhylogenyDataUtil
-            .appendElement( writer, PhyloXmlMapping.TAXONOMY_COMMON_NAME, getCommonName(), indentation );
+            PhylogenyDataUtil.appendElement( writer,
+                                             PhyloXmlMapping.TAXONOMY_COMMON_NAME,
+                                             getCommonName(),
+                                             indentation );
         }
         if ( _synonyms != null ) {
             for( final String syn : getSynonyms() ) {
@@ -411,6 +413,24 @@ public class Taxonomy implements PhylogenyData, MultipleUris, Comparable<Taxonom
                 }
             }
         }
+        if ( getLineage() != null ) {
+            final StringBuilder sb = new StringBuilder();
+            boolean first = true;
+            for( final String lin : getLineage() ) {
+                if ( !ForesterUtil.isEmpty( lin ) ) {
+                    if ( first ) {
+                        first = false;
+                    }
+                    else {
+                        sb.append( "," );
+                    }
+                    sb.append( lin );
+                }
+            }
+            if ( sb.length() > 0 ) {
+                PhylogenyDataUtil.appendElement( writer, PhyloXmlMapping.TAXONOMY_LINEAGE, sb.toString(), indentation );
+            }
+        }
         writer.write( ForesterUtil.LINE_SEPARATOR );
         writer.write( indentation );
         PhylogenyDataUtil.appendClose( writer, PhyloXmlMapping.TAXONOMY );