inprogress
[jalview.git] / forester / java / src / org / forester / archaeopteryx / TreePanel.java
index 6b26c29..1eaadd3 100644 (file)
@@ -34,9 +34,9 @@ import java.awt.GradientPaint;
 import java.awt.Graphics;
 import java.awt.Graphics2D;
 import java.awt.Point;
-import java.awt.Polygon;
 import java.awt.Rectangle;
 import java.awt.RenderingHints;
+import java.awt.Stroke;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 import java.awt.event.FocusAdapter;
@@ -54,6 +54,7 @@ import java.awt.geom.Arc2D;
 import java.awt.geom.CubicCurve2D;
 import java.awt.geom.Ellipse2D;
 import java.awt.geom.Line2D;
+import java.awt.geom.Path2D;
 import java.awt.geom.QuadCurve2D;
 import java.awt.geom.Rectangle2D;
 import java.awt.image.BufferedImage;
@@ -75,8 +76,11 @@ import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Hashtable;
 import java.util.List;
+import java.util.Map.Entry;
 import java.util.Set;
+import java.util.SortedMap;
 import java.util.SortedSet;
+import java.util.TreeMap;
 
 import javax.swing.BorderFactory;
 import javax.swing.JApplet;
@@ -100,6 +104,7 @@ import org.forester.archaeopteryx.phylogeny.data.RenderableVector;
 import org.forester.archaeopteryx.tools.Blast;
 import org.forester.archaeopteryx.tools.ImageLoader;
 import org.forester.io.parsers.phyloxml.PhyloXmlUtil;
+import org.forester.io.writers.SequenceWriter;
 import org.forester.phylogeny.Phylogeny;
 import org.forester.phylogeny.PhylogenyMethods;
 import org.forester.phylogeny.PhylogenyMethods.DESCENDANT_SORT_PRIORITY;
@@ -129,113 +134,119 @@ import org.forester.util.SequenceIdParser;
 
 public final class TreePanel extends JPanel implements ActionListener, MouseWheelListener, Printable {
 
-    private static final float              PI                                                 = ( float ) ( Math.PI );
-    private static final double             TWO_PI                                             = 2 * Math.PI;
-    private static final float              ONEHALF_PI                                         = ( float ) ( 1.5 * Math.PI );
-    private static final float              HALF_PI                                            = ( float ) ( Math.PI / 2.0 );
-    private static final float              ANGLE_ROTATION_UNIT                                = ( float ) ( Math.PI / 32 );
-    private static final short              OV_BORDER                                          = 10;
-    final static Cursor                     CUT_CURSOR                                         = Cursor.getPredefinedCursor( Cursor.CROSSHAIR_CURSOR );
-    final static Cursor                     MOVE_CURSOR                                        = Cursor.getPredefinedCursor( Cursor.MOVE_CURSOR );
-    final static Cursor                     ARROW_CURSOR                                       = Cursor.getPredefinedCursor( Cursor.DEFAULT_CURSOR );
-    final static Cursor                     HAND_CURSOR                                        = Cursor.getPredefinedCursor( Cursor.HAND_CURSOR );
-    final static Cursor                     WAIT_CURSOR                                        = Cursor.getPredefinedCursor( Cursor.WAIT_CURSOR );
-    private final static long               serialVersionUID                                   = -978349745916505029L;
-    private final static int                EURO_D                                             = 10;
-    private final static String             NODE_POPMENU_NODE_CLIENT_PROPERTY                  = "node";
-    private final static int                MIN_ROOT_LENGTH                                    = 3;
-    private final static int                MAX_SUBTREES                                       = 100;
-    private final static int                MAX_NODE_FRAMES                                    = 10;
-    private final static int                MOVE                                               = 20;
-    private final static NumberFormat       FORMATTER_CONFIDENCE;
-    private final static NumberFormat       FORMATTER_BRANCH_LENGTH;
-    private final static int                WIGGLE                                             = 2;
-    private final static int                LIMIT_FOR_HQ_RENDERING                             = 1000;
-    private final static int                CONFIDENCE_LEFT_MARGIN                             = 4;
-    private final RenderingHints            _rendering_hints                                   = new RenderingHints( RenderingHints.KEY_RENDERING,
-                                                                                                                     RenderingHints.VALUE_RENDER_DEFAULT );
-    private File                            _treefile                                          = null;
-    private Configuration                   _configuration                                     = null;
-    private final NodeFrame[]               _node_frames                                       = new NodeFrame[ TreePanel.MAX_NODE_FRAMES ];
-    private int                             _node_frame_index                                  = 0;
-    private Phylogeny                       _phylogeny                                         = null;
-    private final Phylogeny[]               _sub_phylogenies                                   = new Phylogeny[ TreePanel.MAX_SUBTREES ];
-    private final PhylogenyNode[]           _sub_phylogenies_temp_roots                        = new PhylogenyNode[ TreePanel.MAX_SUBTREES ];
-    private int                             _subtree_index                                     = 0;
-    private MainPanel                       _main_panel                                        = null;
-    private Set<Integer>                    _found_nodes                                       = null;
-    private PhylogenyNode                   _highlight_node                                    = null;
-    private JPopupMenu                      _node_popup_menu                                   = null;
-    private JMenuItem                       _node_popup_menu_items[]                           = null;
-    private int                             _longest_ext_node_info                             = 0;
-    private float                           _x_correction_factor                               = 0.0f;
-    private float                           _ov_x_correction_factor                            = 0.0f;
-    private float                           _x_distance                                        = 0.0f;
-    private float                           _y_distance                                        = 0.0f;
-    private PHYLOGENY_GRAPHICS_TYPE         _graphics_type                                     = PHYLOGENY_GRAPHICS_TYPE.RECTANGULAR;
-    private double                          _domain_structure_width                            = Constants.DOMAIN_STRUCTURE_DEFAULT_WIDTH;
-    private int                             _domain_structure_e_value_thr_exp                  = Constants.DOMAIN_STRUCTURE_E_VALUE_THR_DEFAULT_EXP;
-    private float                           _last_drag_point_x                                 = 0;
-    private float                           _last_drag_point_y                                 = 0;
-    private ControlPanel                    _control_panel                                     = null;
-    private int                             _external_node_index                               = 0;
-    private final Polygon                   _polygon                                           = new Polygon();
-    private final StringBuilder             _sb                                                = new StringBuilder();
-    private JColorChooser                   _color_chooser                                     = null;
-    private double                          _scale_distance                                    = 0.0;
-    private String                          _scale_label                                       = null;
-    private final CubicCurve2D              _cubic_curve                                       = new CubicCurve2D.Float();
-    private final QuadCurve2D               _quad_curve                                        = new QuadCurve2D.Float();
-    private final Line2D                    _line                                              = new Line2D.Float();
-    private final Ellipse2D                 _ellipse                                           = new Ellipse2D.Float();
-    private final Rectangle2D               _rectangle                                         = new Rectangle2D.Float();
-    private Options                         _options                                           = null;
-    private float                           _ov_max_width                                      = 0;
-    private float                           _ov_max_height                                     = 0;
-    private int                             _ov_x_position                                     = 0;
-    private int                             _ov_y_position                                     = 0;
-    private int                             _ov_y_start                                        = 0;
-    private float                           _ov_y_distance                                     = 0;
-    private float                           _ov_x_distance                                     = 0;
-    private boolean                         _ov_on                                             = false;
-    private double                          _urt_starting_angle                                = ( float ) ( Math.PI / 2 );
-    private float                           _urt_factor                                        = 1;
-    private float                           _urt_factor_ov                                     = 1;
-    private final boolean                   _phy_has_branch_lengths;
-    private final Rectangle2D               _ov_rectangle                                      = new Rectangle2D.Float();
-    private boolean                         _in_ov_rect                                        = false;
-    private boolean                         _in_ov                                             = false;
-    private final Rectangle                 _ov_virtual_rectangle                              = new Rectangle();
-    final private static double             _180_OVER_PI                                       = 180.0 / Math.PI;
-    private static final float              ROUNDED_D                                          = 8;
-    private int                             _circ_max_depth;
-    private PhylogenyNode                   _root;
-    final private Arc2D                     _arc                                               = new Arc2D.Double();
-    final private HashMap<Integer, Double>  _urt_nodeid_angle_map                              = new HashMap<Integer, Double>();
-    final private HashMap<Integer, Integer> _urt_nodeid_index_map                              = new HashMap<Integer, Integer>();
-    final private Set<Integer>              _collapsed_external_nodeid_set                     = new HashSet<Integer>();
-    HashMap<Integer, Short>                 _nodeid_dist_to_leaf                               = new HashMap<Integer, Short>();
-    private AffineTransform                 _at;
-    private double                          _max_distance_to_root                              = -1;
-    private int                             _dynamic_hiding_factor                             = 0;
-    private boolean                         _edited                                            = false;
-    private Popup                           _node_desc_popup;
-    private JTextArea                       _rollover_popup;
-    private final StringBuffer              _popup_buffer                                      = new StringBuffer();
-    final private static Font               POPUP_FONT                                         = new Font( Configuration
-                                                                                                                   .getDefaultFontFamilyName(),
-                                                                                                           Font.PLAIN,
-                                                                                                           12 );
-    private Sequence                        _query_sequence                                    = null;
-    private final FontRenderContext         _frc                                               = new FontRenderContext( null,
-                                                                                                                        false,
-                                                                                                                        false );
+    private static final BasicStroke     STROKE_2                                           = new BasicStroke( 2f );
+    private static final BasicStroke     STROKE_1                                           = new BasicStroke( 1f );
+    private static final BasicStroke     STROKE_075                                         = new BasicStroke( 0.75f );
+    private static final BasicStroke     STROKE_05                                          = new BasicStroke( 0.5f );
+    private static final BasicStroke     STROKE_025                                         = new BasicStroke( 0.25f );
+    private static final BasicStroke     STROKE_01                                          = new BasicStroke( 0.1f );
+    private static final BasicStroke     STROKE_005                                         = new BasicStroke( 0.05f );
+    private static final float           PI                                                 = ( float ) ( Math.PI );
+    private static final double          TWO_PI                                             = 2 * Math.PI;
+    private static final float           ONEHALF_PI                                         = ( float ) ( 1.5 * Math.PI );
+    private static final float           HALF_PI                                            = ( float ) ( Math.PI / 2.0 );
+    private static final float           ANGLE_ROTATION_UNIT                                = ( float ) ( Math.PI / 32 );
+    private static final short           OV_BORDER                                          = 10;
+    final static Cursor                  CUT_CURSOR                                         = Cursor.getPredefinedCursor( Cursor.CROSSHAIR_CURSOR );
+    final static Cursor                  MOVE_CURSOR                                        = Cursor.getPredefinedCursor( Cursor.MOVE_CURSOR );
+    final static Cursor                  ARROW_CURSOR                                       = Cursor.getPredefinedCursor( Cursor.DEFAULT_CURSOR );
+    final static Cursor                  HAND_CURSOR                                        = Cursor.getPredefinedCursor( Cursor.HAND_CURSOR );
+    final static Cursor                  WAIT_CURSOR                                        = Cursor.getPredefinedCursor( Cursor.WAIT_CURSOR );
+    private final static long            serialVersionUID                                   = -978349745916505029L;
+    private final static int             EURO_D                                             = 10;
+    private final static String          NODE_POPMENU_NODE_CLIENT_PROPERTY                  = "node";
+    private final static int             MIN_ROOT_LENGTH                                    = 3;
+    private final static int             MAX_SUBTREES                                       = 100;
+    private final static int             MAX_NODE_FRAMES                                    = 10;
+    private final static int             MOVE                                               = 20;
+    private final static NumberFormat    FORMATTER_CONFIDENCE;
+    private final static NumberFormat    FORMATTER_BRANCH_LENGTH;
+    private final static int             WIGGLE                                             = 2;
+    private final static int             LIMIT_FOR_HQ_RENDERING                             = 2000;
+    private final static int             CONFIDENCE_LEFT_MARGIN                             = 4;
+    private final RenderingHints         _rendering_hints                                   = new RenderingHints( RenderingHints.KEY_RENDERING,
+                                                                                                                  RenderingHints.VALUE_RENDER_DEFAULT );
+    private File                         _treefile                                          = null;
+    private Configuration                _configuration                                     = null;
+    private final NodeFrame[]            _node_frames                                       = new NodeFrame[ TreePanel.MAX_NODE_FRAMES ];
+    private int                          _node_frame_index                                  = 0;
+    private Phylogeny                    _phylogeny                                         = null;
+    private final Phylogeny[]            _sub_phylogenies                                   = new Phylogeny[ TreePanel.MAX_SUBTREES ];
+    private final PhylogenyNode[]        _sub_phylogenies_temp_roots                        = new PhylogenyNode[ TreePanel.MAX_SUBTREES ];
+    private int                          _subtree_index                                     = 0;
+    private MainPanel                    _main_panel                                        = null;
+    private Set<Long>                    _found_nodes                                       = null;
+    private PhylogenyNode                _highlight_node                                    = null;
+    private JPopupMenu                   _node_popup_menu                                   = null;
+    private JMenuItem                    _node_popup_menu_items[]                           = null;
+    private int                          _longest_ext_node_info                             = 0;
+    private float                        _x_correction_factor                               = 0.0f;
+    private float                        _ov_x_correction_factor                            = 0.0f;
+    private float                        _x_distance                                        = 0.0f;
+    private float                        _y_distance                                        = 0.0f;
+    private PHYLOGENY_GRAPHICS_TYPE      _graphics_type                                     = PHYLOGENY_GRAPHICS_TYPE.RECTANGULAR;
+    private double                       _domain_structure_width                            = Constants.DOMAIN_STRUCTURE_DEFAULT_WIDTH;
+    private int                          _domain_structure_e_value_thr_exp                  = Constants.DOMAIN_STRUCTURE_E_VALUE_THR_DEFAULT_EXP;
+    private float                        _last_drag_point_x                                 = 0;
+    private float                        _last_drag_point_y                                 = 0;
+    private ControlPanel                 _control_panel                                     = null;
+    private int                          _external_node_index                               = 0;
+    private final Path2D.Float           _polygon                                           = new Path2D.Float();
+    private final StringBuilder          _sb                                                = new StringBuilder();
+    private JColorChooser                _color_chooser                                     = null;
+    private double                       _scale_distance                                    = 0.0;
+    private String                       _scale_label                                       = null;
+    private final CubicCurve2D           _cubic_curve                                       = new CubicCurve2D.Float();
+    private final QuadCurve2D            _quad_curve                                        = new QuadCurve2D.Float();
+    private final Line2D                 _line                                              = new Line2D.Float();
+    private final Ellipse2D              _ellipse                                           = new Ellipse2D.Float();
+    private final Rectangle2D            _rectangle                                         = new Rectangle2D.Float();
+    private Options                      _options                                           = null;
+    private float                        _ov_max_width                                      = 0;
+    private float                        _ov_max_height                                     = 0;
+    private int                          _ov_x_position                                     = 0;
+    private int                          _ov_y_position                                     = 0;
+    private int                          _ov_y_start                                        = 0;
+    private float                        _ov_y_distance                                     = 0;
+    private float                        _ov_x_distance                                     = 0;
+    private boolean                      _ov_on                                             = false;
+    private double                       _urt_starting_angle                                = ( float ) ( Math.PI / 2 );
+    private float                        _urt_factor                                        = 1;
+    private float                        _urt_factor_ov                                     = 1;
+    private final boolean                _phy_has_branch_lengths;
+    private final Rectangle2D            _ov_rectangle                                      = new Rectangle2D.Float();
+    private boolean                      _in_ov_rect                                        = false;
+    private boolean                      _in_ov                                             = false;
+    private final Rectangle              _ov_virtual_rectangle                              = new Rectangle();
+    final private static double          _180_OVER_PI                                       = 180.0 / Math.PI;
+    private static final float           ROUNDED_D                                          = 8;
+    private int                          _circ_max_depth;
+    private PhylogenyNode                _root;
+    final private Arc2D                  _arc                                               = new Arc2D.Double();
+    final private HashMap<Long, Double>  _urt_nodeid_angle_map                              = new HashMap<Long, Double>();
+    final private HashMap<Long, Integer> _urt_nodeid_index_map                              = new HashMap<Long, Integer>();
+    final private Set<Long>              _collapsed_external_nodeid_set                     = new HashSet<Long>();
+    HashMap<Long, Short>                 _nodeid_dist_to_leaf                               = new HashMap<Long, Short>();
+    private AffineTransform              _at;
+    private double                       _max_distance_to_root                              = -1;
+    private int                          _dynamic_hiding_factor                             = 0;
+    private boolean                      _edited                                            = false;
+    private Popup                        _node_desc_popup;
+    private JTextArea                    _rollover_popup;
+    private final StringBuffer           _popup_buffer                                      = new StringBuffer();
+    final private static Font            POPUP_FONT                                         = new Font( Configuration.getDefaultFontFamilyName(),
+                                                                                                        Font.PLAIN,
+                                                                                                        12 );
+    private Sequence                     _query_sequence                                    = null;
+    private final FontRenderContext      _frc                                               = new FontRenderContext( null,
+                                                                                                                     false,
+                                                                                                                     false );
     // expression values menu:
-    private DescriptiveStatistics           _statistics_for_vector_data;
-    private PhylogenyNode[]                 _nodes_in_preorder                                 = null;
-    private StringBuilder                   _current_external_nodes_data_buffer                = new StringBuilder();
-    private int                             _current_external_nodes_data_buffer_change_counter = 0;
-    private Set<Integer>                    _current_external_nodes                            = null;
+    private DescriptiveStatistics        _statistics_for_vector_data;
+    private PhylogenyNode[]              _nodes_in_preorder                                 = null;
+    private StringBuilder                _current_external_nodes_data_buffer                = new StringBuilder();
+    private int                          _current_external_nodes_data_buffer_change_counter = 0;
+    private Set<Long>                    _current_external_nodes                            = null;
     //  private Image                           offscreenImage;
     //  private Graphics                        offscreenGraphics;
     //  private Dimension                       offscreenDimension;
@@ -307,65 +318,6 @@ public final class TreePanel extends JPanel implements ActionListener, MouseWhee
         requestFocusInWindow();
     }
 
-    public void checkForVectorProperties( final Phylogeny phy ) {
-        final DescriptiveStatistics stats = new BasicDescriptiveStatistics();
-        for( final PhylogenyNodeIterator iter = phy.iteratorPreorder(); iter.hasNext(); ) {
-            final PhylogenyNode node = iter.next();
-            if ( node.getNodeData().getProperties() != null ) {
-                final PropertiesMap pm = node.getNodeData().getProperties();
-                final double[] vector = new double[ pm.getProperties().size() ];
-                int counter = 0;
-                for( final String ref : pm.getProperties().keySet() ) {
-                    if ( ref.startsWith( PhyloXmlUtil.VECTOR_PROPERTY_REF ) ) {
-                        final Property p = pm.getProperty( ref );
-                        final String value_str = p.getValue();
-                        final String index_str = ref
-                                .substring( PhyloXmlUtil.VECTOR_PROPERTY_REF.length(), ref.length() );
-                        double d = -100;
-                        try {
-                            d = Double.parseDouble( value_str );
-                        }
-                        catch ( final NumberFormatException e ) {
-                            JOptionPane.showMessageDialog( this, "Could not parse \"" + value_str
-                                    + "\" into a decimal value", "Problem with Vector Data", JOptionPane.ERROR_MESSAGE );
-                            return;
-                        }
-                        int i = -1;
-                        try {
-                            i = Integer.parseInt( index_str );
-                        }
-                        catch ( final NumberFormatException e ) {
-                            JOptionPane.showMessageDialog( this,
-                                                           "Could not parse \"" + index_str
-                                                                   + "\" into index for vector data",
-                                                           "Problem with Vector Data",
-                                                           JOptionPane.ERROR_MESSAGE );
-                            return;
-                        }
-                        if ( i < 0 ) {
-                            JOptionPane.showMessageDialog( this,
-                                                           "Attempt to use negative index for vector data",
-                                                           "Problem with Vector Data",
-                                                           JOptionPane.ERROR_MESSAGE );
-                            return;
-                        }
-                        vector[ i ] = d;
-                        ++counter;
-                        stats.addValue( d );
-                    }
-                }
-                final List<Double> vector_l = new ArrayList<Double>( counter );
-                for( int i = 0; i < counter; ++i ) {
-                    vector_l.add( vector[ i ] );
-                }
-                node.getNodeData().setVector( vector_l );
-            }
-        }
-        if ( stats.getN() > 0 ) {
-            _statistics_for_vector_data = stats;
-        }
-    }
-
     public synchronized Hashtable<String, BufferedImage> getImageMap() {
         return getMainPanel().getImageMap();
     }
@@ -404,7 +356,7 @@ public final class TreePanel extends JPanel implements ActionListener, MouseWhee
                 getControlPanel().displayedPhylogenyMightHaveChanged( true );
             }
             else {
-                getTreeFontSet().decreaseFontSize();
+                getTreeFontSet().decreaseFontSize( 1, false );
                 getControlPanel().displayedPhylogenyMightHaveChanged( true );
             }
         }
@@ -499,11 +451,6 @@ public final class TreePanel extends JPanel implements ActionListener, MouseWhee
         }
     }
 
-    public final void setArrowCursor() {
-        setCursor( ARROW_CURSOR );
-        repaint();
-    }
-
     public final void setEdited( final boolean edited ) {
         _edited = edited;
     }
@@ -513,20 +460,60 @@ public final class TreePanel extends JPanel implements ActionListener, MouseWhee
     }
 
     /**
+     * Set a phylogeny tree.
+     * 
+     * @param t
+     *            an instance of a Phylogeny
+     */
+    public final void setTree( final Phylogeny t ) {
+        setNodeInPreorderToNull();
+        _phylogeny = t;
+    }
+
+    public final void setWaitCursor() {
+        setCursor( WAIT_CURSOR );
+        repaint();
+    }
+
+    @Override
+    public void update( final Graphics g ) {
+        paint( g );
+    }
+
+    final void calcMaxDepth() {
+        if ( _phylogeny != null ) {
+            _circ_max_depth = PhylogenyMethods.calculateMaxDepth( _phylogeny );
+        }
+    }
+
+    /**
      * Set parameters for printing the displayed tree
      * 
-     * @param x
-     * @param y
      */
-    public final void setParametersForPainting( final int x, final int y, final boolean recalc_longest_ext_node_info ) {
+    final void calcParametersForPainting( final int x, final int y, final boolean recalc_longest_ext_node_info ) {
         // updateStyle(); not needed?
         if ( ( _phylogeny != null ) && !_phylogeny.isEmpty() ) {
             initNodeData();
             if ( recalc_longest_ext_node_info ) {
                 calculateLongestExtNodeInfo();
-                while ( ( getLongestExtNodeInfo() > y / 2 ) && ( getTreeFontSet().getLargeFont().getSize() > 2 ) ) {
-                    getMainPanel().getTreeFontSet().decreaseFontSize();
-                    calculateLongestExtNodeInfo();
+                if ( getOptions().isAllowFontSizeChange() ) {
+                    if ( ( getLongestExtNodeInfo() > ( x * 0.6 ) )
+                            && ( getTreeFontSet().getLargeFont().getSize() > 2 + TreeFontSet.FONT_SIZE_CHANGE_STEP ) ) {
+                        while ( ( getLongestExtNodeInfo() > ( x * 0.7 ) )
+                                && ( getTreeFontSet().getLargeFont().getSize() > 2 ) ) {
+                            getMainPanel().getTreeFontSet().decreaseFontSize( getConfiguration().getMinBaseFontSize(),
+                                                                              true );
+                            calculateLongestExtNodeInfo();
+                        }
+                    }
+                    else {
+                        while ( ( getLongestExtNodeInfo() < ( x * 0.6 ) )
+                                && ( getTreeFontSet().getLargeFont().getSize() <= getTreeFontSet().getLargeFontMemory()
+                                        .getSize() - TreeFontSet.FONT_SIZE_CHANGE_STEP ) ) {
+                            getMainPanel().getTreeFontSet().increaseFontSize();
+                            calculateLongestExtNodeInfo();
+                        }
+                    }
                 }
             }
             int ext_nodes = _phylogeny.getRoot().getNumberOfExternalNodes();
@@ -574,33 +561,27 @@ public final class TreePanel extends JPanel implements ActionListener, MouseWhee
             }
             _circ_max_depth = max_depth;
             setUpUrtFactor();
-        }
-    }
-
-    /**
-     * Set a phylogeny tree.
-     * 
-     * @param t
-     *            an instance of a Phylogeny
-     */
-    public final void setTree( final Phylogeny t ) {
-        setNodeInPreorderToNull();
-        _phylogeny = t;
-    }
-
-    public final void setWaitCursor() {
-        setCursor( WAIT_CURSOR );
-        repaint();
-    }
-
-    @Override
-    public void update( final Graphics g ) {
-        paint( g );
-    }
-
-    final void calcMaxDepth() {
-        if ( _phylogeny != null ) {
-            _circ_max_depth = PhylogenyMethods.calculateMaxDepth( _phylogeny );
+            //
+            if ( getOptions().isAllowFontSizeChange() ) {
+                if ( ( getPhylogenyGraphicsType() != PHYLOGENY_GRAPHICS_TYPE.UNROOTED )
+                        && ( getPhylogenyGraphicsType() != PHYLOGENY_GRAPHICS_TYPE.CIRCULAR ) ) {
+                    //                int dynamic_hiding_factor = calcDynamicHidingFactor();
+                    //                if ( dynamic_hiding_factor > 1 ) {
+                    //                    while ( dynamic_hiding_factor > 1
+                    //                            && getTreeFontSet()._fm_large.getHeight() > TreeFontSet.SMALL_FONTS_BASE ) {
+                    //                        getTreeFontSet().decreaseFontSize( 1, true );
+                    //                        dynamic_hiding_factor = calcDynamicHidingFactor();
+                    //                    }
+                    //                }
+                    //                else if ( getTreeFontSet().isDecreasedSizeBySystem() ) {
+                    //                    while ( dynamic_hiding_factor < 1 && getTreeFontSet()._fm_large.getHeight() < 12 ) {
+                    //                        getTreeFontSet().increaseFontSize();
+                    //                        dynamic_hiding_factor = calcDynamicHidingFactor();
+                    //                    }
+                    //                }
+                }
+            }
+            //
         }
     }
 
@@ -639,8 +620,8 @@ public final class TreePanel extends JPanel implements ActionListener, MouseWhee
                 if ( getControlPanel().isShowAnnotation()
                         && ( node.getNodeData().getSequence().getAnnotations() != null )
                         && !node.getNodeData().getSequence().getAnnotations().isEmpty() ) {
-                    sum += getTreeFontSet()._fm_large.stringWidth( node.getNodeData().getSequence().getAnnotation( 0 )
-                            .asSimpleText()
+                    sum += getTreeFontSet()._fm_large.stringWidth( AptxUtil.createAnnotationString( node.getNodeData()
+                            .getSequence().getAnnotations() )
                             + " " );
                 }
                 if ( getControlPanel().isShowDomainArchitectures()
@@ -718,25 +699,88 @@ public final class TreePanel extends JPanel implements ActionListener, MouseWhee
     }
 
     final Color calculateTaxonomyBasedColor( final Taxonomy tax ) {
-        String species = tax.getTaxonomyCode();
-        if ( ForesterUtil.isEmpty( species ) ) {
-            species = tax.getScientificName();
-            if ( ForesterUtil.isEmpty( species ) ) {
-                species = tax.getCommonName();
-            }
-        }
-        if ( ForesterUtil.isEmpty( species ) ) {
+        if ( ForesterUtil.isEmpty( tax.getTaxonomyCode() ) && ForesterUtil.isEmpty( tax.getScientificName() ) ) {
             return getTreeColorSet().getTaxonomyColor();
         }
-        // Look in species hash
-        Color c = getControlPanel().getSpeciesColors().get( species );
+        Color c = null;
+        if ( !ForesterUtil.isEmpty( tax.getTaxonomyCode() ) ) {
+            c = getControlPanel().getSpeciesColors().get( tax.getTaxonomyCode() );
+        }
+        if ( ( c == null ) && !ForesterUtil.isEmpty( tax.getScientificName() ) ) {
+            c = getControlPanel().getSpeciesColors().get( tax.getScientificName() );
+        }
         if ( c == null ) {
-            c = AptxUtil.calculateColorFromString( species );
-            getControlPanel().getSpeciesColors().put( species, c );
+            if ( !ForesterUtil.isEmpty( tax.getTaxonomyCode() ) ) {
+                c = AptxUtil.calculateColorFromString( tax.getTaxonomyCode(), true );
+                getControlPanel().getSpeciesColors().put( tax.getTaxonomyCode(), c );
+            }
+            else {
+                c = AptxUtil.calculateColorFromString( tax.getScientificName(), true );
+                getControlPanel().getSpeciesColors().put( tax.getScientificName(), c );
+            }
         }
         return c;
     }
 
+    void checkForVectorProperties( final Phylogeny phy ) {
+        final DescriptiveStatistics stats = new BasicDescriptiveStatistics();
+        for( final PhylogenyNodeIterator iter = phy.iteratorPreorder(); iter.hasNext(); ) {
+            final PhylogenyNode node = iter.next();
+            if ( node.getNodeData().getProperties() != null ) {
+                final PropertiesMap pm = node.getNodeData().getProperties();
+                final double[] vector = new double[ pm.getProperties().size() ];
+                int counter = 0;
+                for( final String ref : pm.getProperties().keySet() ) {
+                    if ( ref.startsWith( PhyloXmlUtil.VECTOR_PROPERTY_REF ) ) {
+                        final Property p = pm.getProperty( ref );
+                        final String value_str = p.getValue();
+                        final String index_str = ref
+                                .substring( PhyloXmlUtil.VECTOR_PROPERTY_REF.length(), ref.length() );
+                        double d = -100;
+                        try {
+                            d = Double.parseDouble( value_str );
+                        }
+                        catch ( final NumberFormatException e ) {
+                            JOptionPane.showMessageDialog( this, "Could not parse \"" + value_str
+                                    + "\" into a decimal value", "Problem with Vector Data", JOptionPane.ERROR_MESSAGE );
+                            return;
+                        }
+                        int i = -1;
+                        try {
+                            i = Integer.parseInt( index_str );
+                        }
+                        catch ( final NumberFormatException e ) {
+                            JOptionPane.showMessageDialog( this,
+                                                           "Could not parse \"" + index_str
+                                                                   + "\" into index for vector data",
+                                                           "Problem with Vector Data",
+                                                           JOptionPane.ERROR_MESSAGE );
+                            return;
+                        }
+                        if ( i < 0 ) {
+                            JOptionPane.showMessageDialog( this,
+                                                           "Attempt to use negative index for vector data",
+                                                           "Problem with Vector Data",
+                                                           JOptionPane.ERROR_MESSAGE );
+                            return;
+                        }
+                        vector[ i ] = d;
+                        ++counter;
+                        stats.addValue( d );
+                    }
+                }
+                final List<Double> vector_l = new ArrayList<Double>( counter );
+                for( int i = 0; i < counter; ++i ) {
+                    vector_l.add( vector[ i ] );
+                }
+                node.getNodeData().setVector( vector_l );
+            }
+        }
+        if ( stats.getN() > 0 ) {
+            _statistics_for_vector_data = stats;
+        }
+    }
+
     void clearCurrentExternalNodesDataBuffer() {
         setCurrentExternalNodesDataBuffer( new StringBuilder() );
     }
@@ -816,6 +860,7 @@ public final class TreePanel extends JPanel implements ActionListener, MouseWhee
             else {
                 msg += "colorized one subtree";
             }
+            setEdited( true );
             JOptionPane.showMessageDialog( this,
                                            msg,
                                            "Taxonomy Colorization Completed (" + rank + ")",
@@ -899,7 +944,7 @@ public final class TreePanel extends JPanel implements ActionListener, MouseWhee
         return _domain_structure_e_value_thr_exp;
     }
 
-    final Set<Integer> getFoundNodes() {
+    final Set<Long> getFoundNodes() {
         return _found_nodes;
     }
 
@@ -1114,6 +1159,7 @@ public final class TreePanel extends JPanel implements ActionListener, MouseWhee
         PhylogenyMethods.midpointRoot( _phylogeny );
         resetNodeIdToDistToLeafMap();
         setArrowCursor();
+        setEdited( true );
         repaint();
     }
 
@@ -1155,7 +1201,7 @@ public final class TreePanel extends JPanel implements ActionListener, MouseWhee
                 if ( ( e.getModifiers() & InputEvent.SHIFT_MASK ) != 0 ) {
                     // Yes, so add to _found_nodes
                     if ( getFoundNodes() == null ) {
-                        setFoundNodes( new HashSet<Integer>() );
+                        setFoundNodes( new HashSet<Long>() );
                     }
                     getFoundNodes().add( node.getId() );
                     // Check if control key is down
@@ -1490,7 +1536,7 @@ public final class TreePanel extends JPanel implements ActionListener, MouseWhee
                     g.fillRect( graphics_file_x, graphics_file_y, graphics_file_width, graphics_file_height );
                 }
             }
-            g.setStroke( new BasicStroke( 1 ) );
+            setupStroke( g );
         }
         else {
             g.setStroke( new BasicStroke( getOptions().getPrintLineWidth() ) );
@@ -1512,7 +1558,7 @@ public final class TreePanel extends JPanel implements ActionListener, MouseWhee
             // Position starting Y of tree
             _phylogeny.getRoot().setYcoord( ( getYdistance() * _phylogeny.getRoot().getNumberOfExternalNodes() )
                     + ( TreePanel.MOVE / 2.0f ) );
-            final int dynamic_hiding_factor = ( int ) ( getTreeFontSet()._fm_large.getHeight() / ( 1.5 * getYdistance() ) );
+            final int dynamic_hiding_factor = calcDynamicHidingFactor();
             if ( getControlPanel().isDynamicallyHideData() ) {
                 if ( dynamic_hiding_factor > 1 ) {
                     getControlPanel().setDynamicHidingIsOn( true );
@@ -1700,6 +1746,7 @@ public final class TreePanel extends JPanel implements ActionListener, MouseWhee
         setNodeInPreorderToNull();
         resetPreferredSize();
         getMainPanel().adjustJScrollPane();
+        setEdited( true );
         repaint();
         if ( getPhylogenyGraphicsType() == PHYLOGENY_GRAPHICS_TYPE.CIRCULAR ) {
             getControlPanel().showWhole();
@@ -1707,7 +1754,7 @@ public final class TreePanel extends JPanel implements ActionListener, MouseWhee
     }
 
     final void resetNodeIdToDistToLeafMap() {
-        _nodeid_dist_to_leaf = new HashMap<Integer, Short>();
+        _nodeid_dist_to_leaf = new HashMap<Long, Short>();
     }
 
     final void resetPreferredSize() {
@@ -1754,13 +1801,18 @@ public final class TreePanel extends JPanel implements ActionListener, MouseWhee
             getControlPanel().getSearchResetButton().setEnabled( true );
             getControlPanel().getSearchResetButton().setVisible( true );
             if ( getFoundNodes() == null ) {
-                setFoundNodes( new HashSet<Integer>() );
+                setFoundNodes( new HashSet<Long>() );
             }
             getFoundNodes().add( node.getId() );
             getControlPanel().setSearchFoundCountsOnLabel( getFoundNodes().size() );
         }
     }
 
+    final void setArrowCursor() {
+        setCursor( ARROW_CURSOR );
+        repaint();
+    }
+
     final void setControlPanel( final ControlPanel atv_control ) {
         _control_panel = atv_control;
     }
@@ -1770,7 +1822,7 @@ public final class TreePanel extends JPanel implements ActionListener, MouseWhee
         _current_external_nodes_data_buffer = sb;
     }
 
-    final void setFoundNodes( final Set<Integer> found_nodes ) {
+    final void setFoundNodes( final Set<Long> found_nodes ) {
         _found_nodes = found_nodes;
     }
 
@@ -1837,21 +1889,13 @@ public final class TreePanel extends JPanel implements ActionListener, MouseWhee
             }
         }
         if ( getMainPanel().getOptions().isAntialiasScreen() ) {
-            if ( ( getPhylogenyGraphicsType() == PHYLOGENY_GRAPHICS_TYPE.RECTANGULAR )
-                    && !getMainPanel().getOptions().isShowDefaultNodeShapes()
-                    && ( ( getControlPanel() != null ) && !getControlPanel().isShowDomainArchitectures() ) ) {
-                _rendering_hints.put( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF );
-            }
-            else {
-                _rendering_hints.put( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON );
-            }
-            try {
-                _rendering_hints.put( RenderingHints.KEY_TEXT_ANTIALIASING,
-                                      RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB );
-            }
-            catch ( final Throwable e ) {
-                _rendering_hints.put( RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON );
-            }
+            _rendering_hints.put( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON );
+            // try {
+            _rendering_hints.put( RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB );
+            // }
+            // catch ( final Throwable e ) {
+            //    _rendering_hints.put( RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON );
+            //}
         }
         else {
             _rendering_hints.put( RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF );
@@ -1985,6 +2029,7 @@ public final class TreePanel extends JPanel implements ActionListener, MouseWhee
         if ( _control_panel.getColorBranchesCb() != null ) {
             _control_panel.getColorBranchesCb().setSelected( true );
         }
+        setEdited( true );
         setArrowCursor();
         repaint();
     }
@@ -2157,9 +2202,9 @@ public final class TreePanel extends JPanel implements ActionListener, MouseWhee
         repaint();
     }
 
-    final private void addToCurrentExternalNodes( final int i ) {
+    final private void addToCurrentExternalNodes( final long i ) {
         if ( _current_external_nodes == null ) {
-            _current_external_nodes = new HashSet<Integer>();
+            _current_external_nodes = new HashSet<Long>();
         }
         _current_external_nodes.add( i );
     }
@@ -2256,6 +2301,10 @@ public final class TreePanel extends JPanel implements ActionListener, MouseWhee
         }
     }
 
+    private final int calcDynamicHidingFactor() {
+        return ( int ) ( 0.5 + ( getTreeFontSet()._fm_large.getHeight() / ( 1.5 * getYdistance() ) ) );
+    }
+
     /**
      * Calculate the length of the distance between the given node and its
      * parent.
@@ -2285,13 +2334,13 @@ public final class TreePanel extends JPanel implements ActionListener, MouseWhee
         if ( getControlPanel().isColorAccordingToAnnotation() && ( getControlPanel().getAnnotationColors() != null ) ) {
             final StringBuilder sb = new StringBuilder();
             for( final Annotation a : ann ) {
-                sb.append( !ForesterUtil.isEmpty( a.getRef() ) ? a.getRef() : a.getDesc() );
+                sb.append( !ForesterUtil.isEmpty( a.getRefValue() ) ? a.getRefValue() : a.getDesc() );
             }
             final String ann_str = sb.toString();
             if ( !ForesterUtil.isEmpty( ann_str ) ) {
                 c = getControlPanel().getAnnotationColors().get( ann_str );
                 if ( c == null ) {
-                    c = AptxUtil.calculateColorFromString( ann_str );
+                    c = AptxUtil.calculateColorFromString( ann_str, false );
                     getControlPanel().getAnnotationColors().put( ann_str, c );
                 }
                 if ( c == null ) {
@@ -2371,7 +2420,7 @@ public final class TreePanel extends JPanel implements ActionListener, MouseWhee
         setNodeInPreorderToNull();
         setCutOrCopiedTree( _phylogeny.copy( node ) );
         final List<PhylogenyNode> nodes = PhylogenyMethods.getAllDescendants( node );
-        final Set<Integer> node_ids = new HashSet<Integer>( nodes.size() );
+        final Set<Long> node_ids = new HashSet<Long>( nodes.size() );
         for( final PhylogenyNode n : nodes ) {
             node_ids.add( n.getId() );
         }
@@ -2380,22 +2429,6 @@ public final class TreePanel extends JPanel implements ActionListener, MouseWhee
         repaint();
     }
 
-    private String createAnnotationString( final SortedSet<Annotation> ann ) {
-        final StringBuilder sb = new StringBuilder();
-        boolean first = true;
-        for( final Annotation a : ann ) {
-            if ( !first ) {
-                sb.append( "|" );
-            }
-            else {
-                first = false;
-            }
-            sb.append( a.asSimpleText() );
-        }
-        final String ann_str = sb.toString();
-        return ann_str;
-    }
-
     final private String createASimpleTextRepresentationOfANode( final PhylogenyNode node ) {
         final String tax = PhylogenyMethods.getSpecies( node );
         String label = node.getName();
@@ -2664,11 +2697,11 @@ public final class TreePanel extends JPanel implements ActionListener, MouseWhee
                                        JOptionPane.ERROR_MESSAGE );
     }
 
-    final private Set<Integer> getCopiedAndPastedNodes() {
+    final private Set<Long> getCopiedAndPastedNodes() {
         return getMainPanel().getCopiedAndPastedNodes();
     }
 
-    final private Set<Integer> getCurrentExternalNodes() {
+    final private Set<Long> getCurrentExternalNodes() {
         return _current_external_nodes;
     }
 
@@ -2867,30 +2900,27 @@ public final class TreePanel extends JPanel implements ActionListener, MouseWhee
         return Blast.isContainsQueryForBlast( node );
     }
 
-    final private boolean isCanOpenSeqWeb( final PhylogenyNode node ) {
-        if ( node.getNodeData().isHasSequence()
-                && ( node.getNodeData().getSequence().getAccession() != null )
-                && !ForesterUtil.isEmpty( node.getNodeData().getSequence().getAccession().getSource() )
-                && !ForesterUtil.isEmpty( node.getNodeData().getSequence().getAccession().getValue() )
-                && getConfiguration().isHasWebLink( node.getNodeData().getSequence().getAccession().getSource()
-                        .toLowerCase() ) ) {
-            return true;
+    final private String isCanOpenSeqWeb( final PhylogenyNode node ) {
+        String v = ForesterUtil.extractUniProtKbProteinSeqIdentifier( node );
+        if ( ForesterUtil.isEmpty( v ) ) {
+            v = ForesterUtil.extractGenbankAccessor( node );
+        }
+        if ( ForesterUtil.isEmpty( v ) ) {
+            v = ForesterUtil.extractRefSeqAccessorAccessor( node );
         }
-        return false;
+        if ( ForesterUtil.isEmpty( v ) ) {
+            v = ForesterUtil.extractGInumber( node );
+        }
+        return v;
     }
 
     final private boolean isCanOpenTaxWeb( final PhylogenyNode node ) {
         if ( node.getNodeData().isHasTaxonomy()
-                && ( ( ( node.getNodeData().getTaxonomy().getIdentifier() != null )
-                        && !ForesterUtil.isEmpty( node.getNodeData().getTaxonomy().getIdentifier().getProvider() )
-                        && !ForesterUtil.isEmpty( node.getNodeData().getTaxonomy().getIdentifier().getValue() ) && getConfiguration()
-                        .isHasWebLink( node.getNodeData().getTaxonomy().getIdentifier().getProvider().toLowerCase() ) )
-                        || ( !ForesterUtil.isEmpty( node.getNodeData().getTaxonomy().getScientificName() ) )
+                && ( ( !ForesterUtil.isEmpty( node.getNodeData().getTaxonomy().getScientificName() ) )
                         || ( !ForesterUtil.isEmpty( node.getNodeData().getTaxonomy().getTaxonomyCode() ) )
                         || ( !ForesterUtil.isEmpty( node.getNodeData().getTaxonomy().getCommonName() ) ) || ( ( node
-                        .getNodeData().getTaxonomy().getIdentifier() != null )
-                        && !ForesterUtil.isEmpty( node.getNodeData().getTaxonomy().getIdentifier().getValue() ) && node
-                        .getNodeData().getTaxonomy().getIdentifier().getValue().startsWith( "http://" ) ) ) ) {
+                        .getNodeData().getTaxonomy().getIdentifier() != null ) && !ForesterUtil.isEmpty( node
+                        .getNodeData().getTaxonomy().getIdentifier().getValue() ) ) ) ) {
             return true;
         }
         else {
@@ -2953,7 +2983,7 @@ public final class TreePanel extends JPanel implements ActionListener, MouseWhee
                 getMainPanel().getControlPanel().displayedPhylogenyMightHaveChanged( true );
             }
             else if ( ( e.getKeyCode() == KeyEvent.VK_SUBTRACT ) || ( e.getKeyCode() == KeyEvent.VK_MINUS ) ) {
-                getMainPanel().getTreeFontSet().decreaseFontSize();
+                getMainPanel().getTreeFontSet().decreaseFontSize( 1, false );
                 getMainPanel().getControlPanel().displayedPhylogenyMightHaveChanged( true );
             }
             else if ( plusPressed( e.getKeyCode() ) ) {
@@ -3110,7 +3140,14 @@ public final class TreePanel extends JPanel implements ActionListener, MouseWhee
             final String title = clickto_names.get( i );
             _node_popup_menu_items[ i ] = new JMenuItem( title );
             if ( title.equals( Configuration.clickto_options[ Configuration.open_seq_web ][ 0 ] ) ) {
-                _node_popup_menu_items[ i ].setEnabled( isCanOpenSeqWeb( node ) );
+                final String id = isCanOpenSeqWeb( node );
+                if ( !ForesterUtil.isEmpty( id ) ) {
+                    _node_popup_menu_items[ i ].setText( _node_popup_menu_items[ i ].getText() + " [" + id + "]" );
+                    _node_popup_menu_items[ i ].setEnabled( true );
+                }
+                else {
+                    _node_popup_menu_items[ i ].setEnabled( false );
+                }
             }
             else if ( title.equals( Configuration.clickto_options[ Configuration.open_tax_web ][ 0 ] ) ) {
                 _node_popup_menu_items[ i ].setEnabled( isCanOpenTaxWeb( node ) );
@@ -3185,12 +3222,16 @@ public final class TreePanel extends JPanel implements ActionListener, MouseWhee
                 return "Sequence Symbols";
             case SEQUENCE_MOL_SEQ:
                 return "Molecular Sequences";
+            case SEQUENCE_MOL_SEQ_FASTA:
+                return "Molecular Sequences (Fasta)";
             case SEQUENCE_ACC:
                 return "Sequence Accessors";
             case TAXONOMY_SCIENTIFIC_NAME:
                 return "Scientific Names";
             case TAXONOMY_CODE:
                 return "Taxonomy Codes";
+            case TAXONOMY_COMM0N_NAME:
+                return "Taxonomy Common Names";
             case UNKNOWN:
                 return "User Selected Data";
             default:
@@ -3200,35 +3241,17 @@ public final class TreePanel extends JPanel implements ActionListener, MouseWhee
     }
 
     final private void openSeqWeb( final PhylogenyNode node ) {
-        if ( !isCanOpenSeqWeb( node ) ) {
+        if ( ForesterUtil.isEmpty( isCanOpenSeqWeb( node ) ) ) {
             cannotOpenBrowserWarningMessage( "sequence" );
             return;
         }
-        String uri_str = null;
-        final Sequence seq = node.getNodeData().getSequence();
-        final String source = seq.getAccession().getSource().toLowerCase();
-        String url;
-        if ( source.toLowerCase().equals( "ncbi" ) ) {
-            url = Constants.NCBI_ALL_DATABASE_SEARCH;
-        }
-        else {
-            final WebLink weblink = getConfiguration().getWebLink( source );
-            url = weblink.getUrl().toString();
-        }
-        try {
-            uri_str = url + URLEncoder.encode( seq.getAccession().getValue(), ForesterConstants.UTF8 );
-        }
-        catch ( final UnsupportedEncodingException e ) {
-            AptxUtil.showErrorMessage( this, e.toString() );
-            e.printStackTrace();
-        }
+        final String uri_str = AptxUtil.createUriForSeqWeb( node, getConfiguration(), this );
         if ( !ForesterUtil.isEmpty( uri_str ) ) {
             try {
-                JApplet applet = null;
-                if ( isApplet() ) {
-                    applet = obtainApplet();
-                }
-                AptxUtil.launchWebBrowser( new URI( uri_str ), isApplet(), applet, "_aptx_seq" );
+                AptxUtil.launchWebBrowser( new URI( uri_str ),
+                                           isApplet(),
+                                           isApplet() ? obtainApplet() : null,
+                                           "_aptx_seq" );
             }
             catch ( final IOException e ) {
                 AptxUtil.showErrorMessage( this, e.toString() );
@@ -3251,32 +3274,34 @@ public final class TreePanel extends JPanel implements ActionListener, MouseWhee
         }
         String uri_str = null;
         final Taxonomy tax = node.getNodeData().getTaxonomy();
-        if ( ( tax.getIdentifier() != null ) && !ForesterUtil.isEmpty( tax.getIdentifier().getProvider() )
-                && getConfiguration().isHasWebLink( tax.getIdentifier().getProvider().toLowerCase() ) ) {
-            final String type = tax.getIdentifier().getProvider().toLowerCase();
-            final WebLink weblink = getConfiguration().getWebLink( type );
+        if ( ( tax.getIdentifier() != null ) && !ForesterUtil.isEmpty( tax.getIdentifier().getValue() )
+                && tax.getIdentifier().getValue().startsWith( "http://" ) ) {
             try {
-                uri_str = weblink.getUrl() + URLEncoder.encode( tax.getIdentifier().getValue(), ForesterConstants.UTF8 );
+                uri_str = new URI( tax.getIdentifier().getValue() ).toString();
             }
-            catch ( final UnsupportedEncodingException e ) {
+            catch ( final URISyntaxException e ) {
                 AptxUtil.showErrorMessage( this, e.toString() );
+                uri_str = null;
                 e.printStackTrace();
             }
         }
-        else if ( ( tax.getIdentifier() != null ) && !ForesterUtil.isEmpty( tax.getIdentifier().getValue() )
-                && tax.getIdentifier().getValue().startsWith( "http://" ) ) {
+        else if ( ( tax.getIdentifier() != null )
+                && !ForesterUtil.isEmpty( tax.getIdentifier().getValue() )
+                && !ForesterUtil.isEmpty( tax.getIdentifier().getProvider() )
+                && ( tax.getIdentifier().getProvider().equalsIgnoreCase( "ncbi" ) || tax.getIdentifier().getProvider()
+                        .equalsIgnoreCase( "uniprot" ) ) ) {
             try {
-                uri_str = new URI( tax.getIdentifier().getValue() ).toString();
+                uri_str = "http://www.uniprot.org/taxonomy/"
+                        + URLEncoder.encode( tax.getIdentifier().getValue(), ForesterConstants.UTF8 );
             }
-            catch ( final URISyntaxException e ) {
+            catch ( final UnsupportedEncodingException e ) {
                 AptxUtil.showErrorMessage( this, e.toString() );
-                uri_str = null;
                 e.printStackTrace();
             }
         }
         else if ( !ForesterUtil.isEmpty( tax.getScientificName() ) ) {
             try {
-                uri_str = "http://www.eol.org/search?q="
+                uri_str = "http://www.uniprot.org/taxonomy/?query="
                         + URLEncoder.encode( tax.getScientificName(), ForesterConstants.UTF8 );
             }
             catch ( final UnsupportedEncodingException e ) {
@@ -3296,7 +3321,7 @@ public final class TreePanel extends JPanel implements ActionListener, MouseWhee
         }
         else if ( !ForesterUtil.isEmpty( tax.getCommonName() ) ) {
             try {
-                uri_str = "http://www.eol.org/search?q="
+                uri_str = "http://www.uniprot.org/taxonomy/?query="
                         + URLEncoder.encode( tax.getCommonName(), ForesterConstants.UTF8 );
             }
             catch ( final UnsupportedEncodingException e ) {
@@ -3306,11 +3331,10 @@ public final class TreePanel extends JPanel implements ActionListener, MouseWhee
         }
         if ( !ForesterUtil.isEmpty( uri_str ) ) {
             try {
-                JApplet applet = null;
-                if ( isApplet() ) {
-                    applet = obtainApplet();
-                }
-                AptxUtil.launchWebBrowser( new URI( uri_str ), isApplet(), applet, "_aptx_tax" );
+                AptxUtil.launchWebBrowser( new URI( uri_str ),
+                                           isApplet(),
+                                           isApplet() ? obtainApplet() : null,
+                                           "_aptx_tax" );
             }
             catch ( final IOException e ) {
                 AptxUtil.showErrorMessage( this, e.toString() );
@@ -3620,30 +3644,30 @@ public final class TreePanel extends JPanel implements ActionListener, MouseWhee
         else {
             d = ( Math.log10( d ) * _y_distance ) / 2.5;
         }
-        final int box_size = getOptions().getDefaultNodeShapeSize();
+        final int box_size = getOptions().getDefaultNodeShapeSize() + 1;
         if ( d < box_size ) {
             d = box_size;
         }
+        final float xx = node.getXcoord() - ( 2 * box_size );
+        final float xxx = xx > node.getParent().getXcoord() + 1 ? xx : node.getParent().getXcoord() + 1;
         _polygon.reset();
-        _polygon.addPoint( ForesterUtil.roundToInt( node.getXcoord() - box_size ),
-                           ForesterUtil.roundToInt( node.getYcoord() ) );
-        _polygon.addPoint( ForesterUtil.roundToInt( node.getXcoord() + box_size ),
-                           ForesterUtil.roundToInt( node.getYcoord() - d ) );
-        _polygon.addPoint( ForesterUtil.roundToInt( node.getXcoord() + box_size ),
-                           ForesterUtil.roundToInt( node.getYcoord() + d ) );
+        _polygon.moveTo( xxx, node.getYcoord() );
+        _polygon.lineTo( node.getXcoord() + 1, node.getYcoord() - d );
+        _polygon.lineTo( node.getXcoord() + 1, node.getYcoord() + d );
+        _polygon.closePath();
         if ( getOptions().getDefaultNodeFill() == NodeVisualization.NodeFill.SOLID ) {
             g.setColor( c );
-            g.fillPolygon( _polygon );
+            g.fill( _polygon );
         }
         else if ( getOptions().getDefaultNodeFill() == NodeVisualization.NodeFill.NONE ) {
             g.setColor( getBackground() );
-            g.fillPolygon( _polygon );
+            g.fill( _polygon );
             g.setColor( c );
-            g.drawPolygon( _polygon );
+            g.draw( _polygon );
         }
         else if ( getOptions().getDefaultNodeFill() == NodeFill.GRADIENT ) {
-            g.setPaint( new GradientPaint( node.getXcoord() - box_size, node.getYcoord(), getBackground(), ( node
-                    .getXcoord() + box_size ), ( float ) ( node.getYcoord() - d ), c, false ) );
+            g.setPaint( new GradientPaint( xxx, node.getYcoord(), getBackground(), node.getXcoord(), ( float ) ( node
+                    .getYcoord() - d ), c, false ) );
             g.fill( _polygon );
             g.setPaint( c );
             g.draw( _polygon );
@@ -3811,7 +3835,9 @@ public final class TreePanel extends JPanel implements ActionListener, MouseWhee
             }
             final int box_size = getOptions().getDefaultNodeShapeSize();
             final int half_box_size = box_size / 2;
-            if ( getOptions().isShowDefaultNodeShapes() || ( getControlPanel().isEvents() && node.isHasAssignedEvent() ) ) {
+            if ( ( getOptions().isShowDefaultNodeShapesExternal() && node.isExternal() )
+                    || ( getOptions().isShowDefaultNodeShapesInternal() && node.isInternal() )
+                    || ( getControlPanel().isEvents() && node.isHasAssignedEvent() ) ) {
                 if ( getOptions().getDefaultNodeShape() == NodeShape.CIRCLE ) {
                     if ( getOptions().getDefaultNodeFill() == NodeFill.GRADIENT ) {
                         drawOvalGradient( x - half_box_size,
@@ -3893,6 +3919,7 @@ public final class TreePanel extends JPanel implements ActionListener, MouseWhee
         if ( !getControlPanel().isShowInternalData() && !node.isExternal() && !node.isCollapse() ) {
             return;
         }
+        _sb.setLength( 0 );
         int x = 0;
         final int half_box_size = getOptions().getDefaultNodeShapeSize() / 2;
         if ( getControlPanel().isShowTaxonomyImages()
@@ -3931,11 +3958,16 @@ public final class TreePanel extends JPanel implements ActionListener, MouseWhee
         else {
             g.setColor( getTreeColorSet().getSequenceColor() );
         }
-        _sb.setLength( 0 );
         if ( node.isCollapse() && ( ( !node.isRoot() && !node.getParent().isCollapse() ) || node.isRoot() ) ) {
-            _sb.append( " [" );
-            _sb.append( node.getAllExternalDescendants().size() );
-            _sb.append( "]" );
+            if ( _sb.length() > 0 ) {
+                _sb.setLength( 0 );
+                _sb.append( "(" );
+                _sb.append( node.getAllExternalDescendants().size() );
+                _sb.append( ")" );
+            }
+        }
+        else {
+            _sb.setLength( 0 );
         }
         if ( getControlPanel().isShowNodeNames() && ( node.getName().length() > 0 ) ) {
             if ( _sb.length() > 0 ) {
@@ -4063,7 +4095,7 @@ public final class TreePanel extends JPanel implements ActionListener, MouseWhee
             else if ( getControlPanel().isColorAccordingToAnnotation() ) {
                 g.setColor( calculateColorForAnnotation( ann ) );
             }
-            final String ann_str = createAnnotationString( ann );
+            final String ann_str = AptxUtil.createAnnotationString( ann );
             TreePanel.drawString( ann_str, node.getXcoord() + x + 3 + half_box_size, node.getYcoord()
                     + ( getTreeFontSet()._fm_large.getAscent() / down_shift_factor ), g );
             _sb.setLength( 0 );
@@ -4245,7 +4277,7 @@ public final class TreePanel extends JPanel implements ActionListener, MouseWhee
 
     final private void paintNodeLite( final Graphics2D g, final PhylogenyNode node ) {
         if ( node.isCollapse() ) {
-            if ( ( !node.isRoot() && !node.getParent().isCollapse() ) || node.isRoot() ) {
+            if ( !node.isRoot() && !node.getParent().isCollapse() ) {
                 paintCollapsedNode( g, node, false, false, false );
             }
             return;
@@ -4299,7 +4331,7 @@ public final class TreePanel extends JPanel implements ActionListener, MouseWhee
                                              final boolean to_graphics_file ) {
         final boolean is_in_found_nodes = isInFoundNodes( node ) || isInCurrentExternalNodes( node );
         if ( node.isCollapse() ) {
-            if ( ( !node.isRoot() && !node.getParent().isCollapse() ) || node.isRoot() ) {
+            if ( ( !node.isRoot() && !node.getParent().isCollapse() ) ) {
                 paintCollapsedNode( g, node, to_graphics_file, to_pdf, is_in_found_nodes );
             }
             return;
@@ -4486,16 +4518,18 @@ public final class TreePanel extends JPanel implements ActionListener, MouseWhee
     }
 
     final private void paintOvRectangle( final Graphics2D g ) {
-        final float w_ratio = ( float ) getWidth() / getVisibleRect().width;
-        final float h_ratio = ( float ) getHeight() / getVisibleRect().height;
-        final float x_ratio = ( float ) getWidth() / getVisibleRect().x;
-        final float y_ratio = ( float ) getHeight() / getVisibleRect().y;
+        final float w_ratio = ( ( float ) getWidth() ) / getVisibleRect().width;
+        final float h_ratio = ( ( float ) getHeight() ) / getVisibleRect().height;
+        final float x_ratio = ( ( float ) getWidth() ) / getVisibleRect().x;
+        final float y_ratio = ( ( float ) getHeight() ) / getVisibleRect().y;
         final float width = getOvMaxWidth() / w_ratio;
         final float height = getOvMaxHeight() / h_ratio;
         final float x = getVisibleRect().x + getOvXPosition() + ( getOvMaxWidth() / x_ratio );
         final float y = getVisibleRect().y + getOvYPosition() + ( getOvMaxHeight() / y_ratio );
         g.setColor( getTreeColorSet().getFoundColor() );
         getOvRectangle().setRect( x, y, width, height );
+        final Stroke s = g.getStroke();
+        g.setStroke( STROKE_1 );
         if ( ( width < 6 ) && ( height < 6 ) ) {
             drawRectFilled( x, y, 6, 6, g );
             getOvVirtualRectangle().setRect( x, y, 6, 6 );
@@ -4515,6 +4549,7 @@ public final class TreePanel extends JPanel implements ActionListener, MouseWhee
             }
             getOvVirtualRectangle().setRect( x, y, width, height );
         }
+        g.setStroke( s );
     }
 
     final private void paintPhylogenyLite( final Graphics2D g ) {
@@ -4523,9 +4558,12 @@ public final class TreePanel extends JPanel implements ActionListener, MouseWhee
                 .setXSecondary( ( float ) ( getVisibleRect().x + getOvXPosition() + ( MOVE / ( getVisibleRect().width / getOvRectangle()
                         .getWidth() ) ) ) );
         _phylogeny.getRoot().setYSecondary( ( getVisibleRect().y + getOvYStart() ) );
+        final Stroke s = g.getStroke();
+        g.setStroke( STROKE_05 );
         for( final PhylogenyNode element : _nodes_in_preorder ) {
             paintNodeLite( g, element );
         }
+        g.setStroke( s );
         paintOvRectangle( g );
     }
 
@@ -4577,12 +4615,15 @@ public final class TreePanel extends JPanel implements ActionListener, MouseWhee
         else {
             g.setColor( getTreeColorSet().getBranchLengthColor() );
         }
+        final Stroke s = g.getStroke();
+        g.setStroke( STROKE_1 );
         drawLine( x1, y1, x1, y2, g );
         drawLine( x2, y1, x2, y2, g );
         drawLine( x1, y3, x2, y3, g );
         if ( getScaleLabel() != null ) {
             g.drawString( getScaleLabel(), ( x1 + 2 ), y3 - 2 );
         }
+        g.setStroke( s );
     }
 
     final private int paintTaxonomy( final Graphics2D g,
@@ -4868,10 +4909,10 @@ public final class TreePanel extends JPanel implements ActionListener, MouseWhee
             }
         }
         if ( getCopiedAndPastedNodes() == null ) {
-            setCopiedAndPastedNodes( new HashSet<Integer>() );
+            setCopiedAndPastedNodes( new HashSet<Long>() );
         }
         final List<PhylogenyNode> nodes = PhylogenyMethods.obtainAllNodesAsList( buffer_phy );
-        final Set<Integer> node_ids = new HashSet<Integer>( nodes.size() );
+        final Set<Long> node_ids = new HashSet<Long>( nodes.size() );
         for( final PhylogenyNode n : nodes ) {
             node_ids.add( n.getId() );
         }
@@ -4911,7 +4952,7 @@ public final class TreePanel extends JPanel implements ActionListener, MouseWhee
         return sb;
     }
 
-    final private void setCopiedAndPastedNodes( final Set<Integer> nodeIds ) {
+    final private void setCopiedAndPastedNodes( final Set<Long> nodeIds ) {
         getMainPanel().setCopiedAndPastedNodes( nodeIds );
     }
 
@@ -4963,6 +5004,30 @@ public final class TreePanel extends JPanel implements ActionListener, MouseWhee
         _scale_label = scale_label;
     }
 
+    private final void setupStroke( final Graphics2D g ) {
+        if ( getYdistance() < 0.001 ) {
+            g.setStroke( STROKE_005 );
+        }
+        else if ( getYdistance() < 0.01 ) {
+            g.setStroke( STROKE_01 );
+        }
+        else if ( getYdistance() < 0.5 ) {
+            g.setStroke( STROKE_025 );
+        }
+        else if ( getYdistance() < 1 ) {
+            g.setStroke( STROKE_05 );
+        }
+        else if ( getYdistance() < 2 ) {
+            g.setStroke( STROKE_075 );
+        }
+        else if ( getYdistance() < 20 ) {
+            g.setStroke( STROKE_1 );
+        }
+        else {
+            g.setStroke( STROKE_2 );
+        }
+    }
+
     final private void setUpUrtFactor() {
         final int d = getVisibleRect().width < getVisibleRect().height ? getVisibleRect().width
                 : getVisibleRect().height;
@@ -5016,6 +5081,51 @@ public final class TreePanel extends JPanel implements ActionListener, MouseWhee
                         data.add( n.getNodeData().getSequence().getMolecularSequence() );
                     }
                     break;
+                case SEQUENCE_MOL_SEQ_FASTA:
+                    final StringBuilder sb = new StringBuilder();
+                    if ( n.getNodeData().isHasSequence()
+                            && !ForesterUtil.isEmpty( n.getNodeData().getSequence().getMolecularSequence() ) ) {
+                        final StringBuilder ann = new StringBuilder();
+                        if ( !ForesterUtil.isEmpty( n.getName() ) ) {
+                            ann.append( n.getName() );
+                            ann.append( "|" );
+                        }
+                        if ( !ForesterUtil.isEmpty( n.getNodeData().getSequence().getSymbol() ) ) {
+                            ann.append( "SYM=" );
+                            ann.append( n.getNodeData().getSequence().getSymbol() );
+                            ann.append( "|" );
+                        }
+                        if ( !ForesterUtil.isEmpty( n.getNodeData().getSequence().getName() ) ) {
+                            ann.append( "NAME=" );
+                            ann.append( n.getNodeData().getSequence().getName() );
+                            ann.append( "|" );
+                        }
+                        if ( n.getNodeData().getSequence().getAccession() != null ) {
+                            ann.append( "ACC=" );
+                            ann.append( n.getNodeData().getSequence().getAccession().asText() );
+                            ann.append( "|" );
+                        }
+                        if ( n.getNodeData().isHasTaxonomy() ) {
+                            if ( !ForesterUtil.isEmpty( n.getNodeData().getTaxonomy().getTaxonomyCode() ) ) {
+                                ann.append( "TAXID=" );
+                                ann.append( n.getNodeData().getTaxonomy().getTaxonomyCode() );
+                                ann.append( "|" );
+                            }
+                            if ( !ForesterUtil.isEmpty( n.getNodeData().getTaxonomy().getScientificName() ) ) {
+                                ann.append( "SN=" );
+                                ann.append( n.getNodeData().getTaxonomy().getScientificName() );
+                                ann.append( "|" );
+                            }
+                        }
+                        String ann_str = ann.toString().trim();
+                        if ( ann_str.endsWith( "|" ) ) {
+                            ann_str = ann_str.substring( 0, ann_str.length() - 1 );
+                        }
+                        sb.append( SequenceWriter.toFasta( ann_str, n.getNodeData().getSequence()
+                                .getMolecularSequence(), 60 ) );
+                        data.add( sb.toString() );
+                    }
+                    break;
                 case SEQUENCE_ACC:
                     if ( n.getNodeData().isHasSequence() && ( n.getNodeData().getSequence().getAccession() != null )
                             && !ForesterUtil.isEmpty( n.getNodeData().getSequence().getAccession().toString() ) ) {
@@ -5028,6 +5138,12 @@ public final class TreePanel extends JPanel implements ActionListener, MouseWhee
                         data.add( n.getNodeData().getTaxonomy().getScientificName() );
                     }
                     break;
+                case TAXONOMY_COMM0N_NAME:
+                    if ( n.getNodeData().isHasTaxonomy()
+                            && !ForesterUtil.isEmpty( n.getNodeData().getTaxonomy().getCommonName() ) ) {
+                        data.add( n.getNodeData().getTaxonomy().getCommonName() );
+                    }
+                    break;
                 case TAXONOMY_CODE:
                     if ( n.getNodeData().isHasTaxonomy()
                             && !ForesterUtil.isEmpty( n.getNodeData().getTaxonomy().getTaxonomyCode() ) ) {
@@ -5042,17 +5158,12 @@ public final class TreePanel extends JPanel implements ActionListener, MouseWhee
                             + getOptions().getExtDescNodeDataToReturn() );
             }
         } // for loop
+        final StringBuilder sb = new StringBuilder();
+        final int size = makeSB( data, getOptions(), sb );
         if ( ( getConfiguration().getExtNodeDataReturnOn() == EXT_NODE_DATA_RETURN_ON.CONSOLE )
                 || ( getConfiguration().getExtNodeDataReturnOn() == EXT_NODE_DATA_RETURN_ON.BUFFER_ONLY ) ) {
-            final StringBuilder sb = new StringBuilder();
-            for( final String d : data ) {
-                if ( !ForesterUtil.isEmpty( d ) ) {
-                    if ( getConfiguration().getExtNodeDataReturnOn() == EXT_NODE_DATA_RETURN_ON.CONSOLE ) {
-                        System.out.println( d );
-                    }
-                    sb.append( d );
-                    sb.append( ForesterUtil.LINE_SEPARATOR );
-                }
+            if ( getConfiguration().getExtNodeDataReturnOn() == EXT_NODE_DATA_RETURN_ON.CONSOLE ) {
+                System.out.println( sb );
             }
             if ( sb.length() < 1 ) {
                 clearCurrentExternalNodesDataBuffer();
@@ -5062,13 +5173,6 @@ public final class TreePanel extends JPanel implements ActionListener, MouseWhee
             }
         }
         else if ( getConfiguration().getExtNodeDataReturnOn() == EXT_NODE_DATA_RETURN_ON.WINODW ) {
-            final StringBuilder sb = new StringBuilder();
-            for( final String d : data ) {
-                if ( !ForesterUtil.isEmpty( d ) ) {
-                    sb.append( d );
-                    sb.append( ForesterUtil.LINE_SEPARATOR );
-                }
-            }
             if ( sb.length() < 1 ) {
                 AptxUtil.showInformationMessage( this,
                                                  "No Appropriate Data (" + obtainTitleForExtDescNodeData() + ")",
@@ -5077,10 +5181,15 @@ public final class TreePanel extends JPanel implements ActionListener, MouseWhee
             }
             else {
                 setCurrentExternalNodesDataBuffer( sb );
-                final String title = "External Descendants "
-                        + ( getOptions().getExtDescNodeDataToReturn() == NODE_DATA.UNKNOWN ? "Data"
-                                : obtainTitleForExtDescNodeData() ) + " (" + data.size() + "/"
-                        + node.getNumberOfExternalNodes() + ") For Node " + node;
+                final String title = ( getOptions().getExtDescNodeDataToReturn() == NODE_DATA.UNKNOWN ? "Data"
+                        : obtainTitleForExtDescNodeData() )
+                        + " for "
+                        + data.size()
+                        + "/"
+                        + node.getNumberOfExternalNodes()
+                        + " external descendats of node "
+                        + node
+                        + ", unique entries: " + size;
                 final String s = sb.toString().trim();
                 if ( getMainPanel().getMainFrame() == null ) {
                     // Must be "E" applet version.
@@ -5094,6 +5203,46 @@ public final class TreePanel extends JPanel implements ActionListener, MouseWhee
         }
     }
 
+    private int makeSB( final List<String> data, final Options optz, final StringBuilder sb ) {
+        final SortedMap<String, Integer> map = new TreeMap<String, Integer>();
+        if ( ( optz.getExtDescNodeDataToReturn() != NODE_DATA.SEQUENCE_MOL_SEQ )
+                && ( optz.getExtDescNodeDataToReturn() != NODE_DATA.SEQUENCE_MOL_SEQ_FASTA ) ) {
+            for( final String d : data ) {
+                if ( !ForesterUtil.isEmpty( d ) ) {
+                    if ( map.containsKey( d ) ) {
+                        map.put( d, map.get( d ) + 1 );
+                    }
+                    else {
+                        map.put( d, 1 );
+                    }
+                }
+            }
+        }
+        int size = 0;
+        if ( ( optz.getExtDescNodeDataToReturn() != NODE_DATA.SEQUENCE_MOL_SEQ )
+                && ( optz.getExtDescNodeDataToReturn() != NODE_DATA.SEQUENCE_MOL_SEQ_FASTA ) ) {
+            for( final Entry<String, Integer> e : map.entrySet() ) {
+                final String v = e.getKey();
+                final Object c = e.getValue();
+                sb.append( v );
+                sb.append( "\t" );
+                sb.append( c );
+                sb.append( ForesterUtil.LINE_SEPARATOR );
+            }
+            size = map.size();
+        }
+        else {
+            for( final String d : data ) {
+                if ( !ForesterUtil.isEmpty( d ) ) {
+                    sb.append( d );
+                    sb.append( ForesterUtil.LINE_SEPARATOR );
+                }
+            }
+            size = data.size();
+        }
+        return size;
+    }
+
     final private void showNodeDataPopup( final MouseEvent e, final PhylogenyNode node ) {
         try {
             if ( ( node.getName().length() > 0 )