mev-4.0.01/source/org/tigr/microarray/mev/cluster/gui/impl/tease/HCLTree.java

Code
Comments
Other
Rev Date Author Line
2 26 Feb 07 jari 1 /*
2 26 Feb 07 jari 2 Copyright @ 1999-2004, The Institute for Genomic Research (TIGR).
2 26 Feb 07 jari 3 All rights reserved.
2 26 Feb 07 jari 4  */
2 26 Feb 07 jari 5 /*
2 26 Feb 07 jari 6  * $RCSfile: HCLTree.java,v $
2 26 Feb 07 jari 7  * $Revision: 1.4 $
2 26 Feb 07 jari 8  * $Date: 2006/07/06 17:15:05 $
2 26 Feb 07 jari 9  * $Author: eleanorahowe $
2 26 Feb 07 jari 10  * $State: Exp $
2 26 Feb 07 jari 11  */
2 26 Feb 07 jari 12 package org.tigr.microarray.mev.cluster.gui.impl.tease;
2 26 Feb 07 jari 13
2 26 Feb 07 jari 14 import java.awt.AlphaComposite;
2 26 Feb 07 jari 15 import java.awt.Color;
2 26 Feb 07 jari 16 import java.awt.Composite;
2 26 Feb 07 jari 17 import java.awt.Dimension;
2 26 Feb 07 jari 18 import java.awt.Graphics;
2 26 Feb 07 jari 19 import java.awt.Graphics2D;
2 26 Feb 07 jari 20 import java.awt.Polygon;
2 26 Feb 07 jari 21 import java.awt.event.MouseAdapter;
2 26 Feb 07 jari 22 import java.awt.event.MouseEvent;
2 26 Feb 07 jari 23 import java.beans.Expression;
2 26 Feb 07 jari 24 import java.beans.PersistenceDelegate;
2 26 Feb 07 jari 25 import java.io.BufferedWriter;
2 26 Feb 07 jari 26 import java.io.File;
2 26 Feb 07 jari 27 import java.io.FileOutputStream;
2 26 Feb 07 jari 28 import java.io.FileWriter;
2 26 Feb 07 jari 29 import java.io.IOException;
2 26 Feb 07 jari 30 import java.io.PrintWriter;
2 26 Feb 07 jari 31 import java.util.ArrayList;
2 26 Feb 07 jari 32 import java.util.Arrays;
2 26 Feb 07 jari 33 import java.util.Hashtable;
2 26 Feb 07 jari 34 import java.util.Vector;
2 26 Feb 07 jari 35
2 26 Feb 07 jari 36 import javax.swing.JFileChooser;
2 26 Feb 07 jari 37 import javax.swing.JOptionPane;
2 26 Feb 07 jari 38 import javax.swing.JPanel;
2 26 Feb 07 jari 39 import javax.swing.SwingUtilities;
2 26 Feb 07 jari 40
2 26 Feb 07 jari 41 import org.tigr.microarray.mev.TMEV;
2 26 Feb 07 jari 42 import org.tigr.microarray.mev.cluster.gui.IData;
2 26 Feb 07 jari 43 import org.tigr.microarray.mev.cluster.gui.IDisplayMenu;
2 26 Feb 07 jari 44 import org.tigr.microarray.mev.cluster.gui.IFramework;
2 26 Feb 07 jari 45
2 26 Feb 07 jari 46
2 26 Feb 07 jari 47 public class HCLTree extends JPanel implements java.io.Serializable {
2 26 Feb 07 jari 48     
2 26 Feb 07 jari 49     public static final long serialVersionUID = 202006060001L;
2 26 Feb 07 jari 50     
2 26 Feb 07 jari 51     // These constants specify a horizontal or
2 26 Feb 07 jari 52     // vertical orientation.
2 26 Feb 07 jari 53     
2 26 Feb 07 jari 54     /** HORIZONTAL orientation */
2 26 Feb 07 jari 55     public static final int HORIZONTAL = 0;  //gene tree
2 26 Feb 07 jari 56     /** VERTICAL orientation */
2 26 Feb 07 jari 57     public static final int VERTICAL   = 1;  //sample tree
2 26 Feb 07 jari 58     
2 26 Feb 07 jari 59     public static final int xOrigin = 20;
2 26 Feb 07 jari 60     
2 26 Feb 07 jari 61     protected HCLTreeListener treeListener;
2 26 Feb 07 jari 62     
2 26 Feb 07 jari 63     protected int orientation = HORIZONTAL;
2 26 Feb 07 jari 64     protected int min_pixels = 10;
2 26 Feb 07 jari 65     protected int max_pixels = 50;
2 26 Feb 07 jari 66     protected float zero_threshold = 0.05f;
2 26 Feb 07 jari 67     protected Color lineColor = new Color(0, 0, 128);
2 26 Feb 07 jari 68     protected Color belowThrColor = Color.lightGray;
2 26 Feb 07 jari 69     protected Color selectedLineColor = Color.magenta;
2 26 Feb 07 jari 70     
2 26 Feb 07 jari 71     // initial data
2 26 Feb 07 jari 72     protected IData data;
2 26 Feb 07 jari 73     // a result data
2 26 Feb 07 jari 74     protected HCLTreeData treeData;
2 26 Feb 07 jari 75     // helpers
2 26 Feb 07 jari 76     protected float minHeight;
2 26 Feb 07 jari 77     protected int stepSize;
2 26 Feb 07 jari 78     public int[] pHeights;
2 26 Feb 07 jari 79     public float[] positions;
2 26 Feb 07 jari 80     protected boolean[] selected;
2 26 Feb 07 jari 81     protected Color[] nodesColors;
2 26 Feb 07 jari 82     
2 26 Feb 07 jari 83     public ArrayList dots;
2 26 Feb 07 jari 84     
2 26 Feb 07 jari 85     protected int [] parentNodes;
2 26 Feb 07 jari 86     protected boolean [] terminalNodes;
2 26 Feb 07 jari 87     protected float maxHeight;
2 26 Feb 07 jari 88     protected boolean flatTree = false;
2 26 Feb 07 jari 89     protected int horizontalOffset = 0;
2 26 Feb 07 jari 90     
2 26 Feb 07 jari 91     protected IFramework framework;
2 26 Feb 07 jari 92     
2 26 Feb 07 jari 93     /**
2 26 Feb 07 jari 94      * Creates a new HCLTree.  Used to restore state from a saved file.  
2 26 Feb 07 jari 95      * This constructor must remain in place with the same signature to ensure 
2 26 Feb 07 jari 96      * backwards-compatibility with future revisions of the class.  
2 26 Feb 07 jari 97      * Add another constructor that calls this one, rather than change this one. 
2 26 Feb 07 jari 98      * @author eleanorahowe
2 26 Feb 07 jari 99      * 
2 26 Feb 07 jari 100      * @param treeData
2 26 Feb 07 jari 101      * @param orientation
2 26 Feb 07 jari 102      */
2 26 Feb 07 jari 103     public HCLTree(HCLTreeData treeData, int orientation){
2 26 Feb 07 jari 104       this(treeData, new Integer(orientation), null);
2 26 Feb 07 jari 105     }
2 26 Feb 07 jari 106     
2 26 Feb 07 jari 107     /**
2 26 Feb 07 jari 108      * Constructs a <code>HCLTree</code> for passed result and
2 26 Feb 07 jari 109      * with specified orientation.
2 26 Feb 07 jari 110      *
2 26 Feb 07 jari 111      * @param result the result of a hcl calculation.
2 26 Feb 07 jari 112      * @param orientation the tree orientation.
2 26 Feb 07 jari 113      */
2 26 Feb 07 jari 114   public HCLTree(HCLTreeData treeData, Integer orientation, ArrayList dotsp){
2 26 Feb 07 jari 115     setBackground(Color.white);
2 26 Feb 07 jari 116       if(dotsp == null) {
2 26 Feb 07 jari 117         this.dots = new ArrayList();
2 26 Feb 07 jari 118       } else
2 26 Feb 07 jari 119         this.dots = dotsp;
2 26 Feb 07 jari 120       
2 26 Feb 07 jari 121         this.treeData = treeData;
2 26 Feb 07 jari 122         this.orientation = orientation.intValue();   //horizontal or vertical
2 26 Feb 07 jari 123         // helpers
2 26 Feb 07 jari 124         this.flatTree = flatTreeCheck(treeData.height);
2 26 Feb 07 jari 125         this.minHeight = getMinHeight(treeData.node_order, treeData.height);
2 26 Feb 07 jari 126         
2 26 Feb 07 jari 127         this.maxHeight = getMaxHeight(this.treeData.node_order, treeData.height);
2 26 Feb 07 jari 128         
2 26 Feb 07 jari 129         this.zero_threshold = minHeight;
2 26 Feb 07 jari 130         this.terminalNodes = new boolean[this.treeData.height.length];  //terminalNodes is a boolean array that has
2 26 Feb 07 jari 131                                           //the size of the number of genes
2 26 Feb 07 jari 132         this.pHeights  = getPixelHeights(treeData.node_order, treeData.height);
2 26 Feb 07 jari 133
2 26 Feb 07 jari 134         this.positions = getPositions(treeData.node_order, treeData.child_1_array, treeData.child_2_array);
2 26 Feb 07 jari 135         this.selected = new boolean[treeData.node_order.length*2];
2 26 Feb 07 jari 136         this.nodesColors = new Color[treeData.node_order.length*2];
2 26 Feb 07 jari 137         
2 26 Feb 07 jari 138         deselect(this.selected);
2 26 Feb 07 jari 139         if (treeData.node_order.length >= 1 && !flatTree) {
2 26 Feb 07 jari 140             switch (this.orientation) {
2 26 Feb 07 jari 141                 case HORIZONTAL:
2 26 Feb 07 jari 142                   this.stepSize = 5;
2 26 Feb 07 jari 143                     setSizes(this.pHeights[treeData.node_order[treeData.node_order.length-2]] + xOrigin, 0);
2 26 Feb 07 jari 144                     break;
2 26 Feb 07 jari 145                 case VERTICAL:
2 26 Feb 07 jari 146                   this.stepSize = 20;
2 26 Feb 07 jari 147                     setSizes(0, this.pHeights[treeData.node_order[treeData.node_order.length-2]]);
2 26 Feb 07 jari 148                     break;
2 26 Feb 07 jari 149             }
2 26 Feb 07 jari 150         } else {
2 26 Feb 07 jari 151             setSizes(0, 0);
2 26 Feb 07 jari 152         }
2 26 Feb 07 jari 153         
2 26 Feb 07 jari 154         initializeParentNodeArray();
2 26 Feb 07 jari 155
2 26 Feb 07 jari 156         addMouseListener(new Listener());
2 26 Feb 07 jari 157     }
2 26 Feb 07 jari 158     
2 26 Feb 07 jari 159     private HCLTree() { }
2 26 Feb 07 jari 160     
2 26 Feb 07 jari 161
2 26 Feb 07 jari 162
2 26 Feb 07 jari 163     public static PersistenceDelegate getPersistenceDelegate(){
2 26 Feb 07 jari 164       return new HCLTreePersistenceDelegate();
2 26 Feb 07 jari 165     }
2 26 Feb 07 jari 166     
2 26 Feb 07 jari 167     
2 26 Feb 07 jari 168     /**
2 26 Feb 07 jari 169      * Sets specified listener to be notified by tree events.
2 26 Feb 07 jari 170      */
2 26 Feb 07 jari 171     public void setListener(HCLTreeListener treeListener) {
2 26 Feb 07 jari 172         this.treeListener = treeListener;
2 26 Feb 07 jari 173     }
2 26 Feb 07 jari 174   public HCLTreeData getTreeData(){return this.treeData;}    
2 26 Feb 07 jari 175     public void setTreeData(HCLTreeData htd){
2 26 Feb 07 jari 176       this.treeData = htd;
2 26 Feb 07 jari 177     }
2 26 Feb 07 jari 178     public void addInfoBox(TEASEInfoBox infoBox) {
2 26 Feb 07 jari 179       this.dots.add(infoBox);
2 26 Feb 07 jari 180       add(infoBox);
2 26 Feb 07 jari 181     } 
2 26 Feb 07 jari 182     
2 26 Feb 07 jari 183     private void initializeParentNodeArray(){
2 26 Feb 07 jari 184         parentNodes = new int[this.treeData.height.length];
2 26 Feb 07 jari 185         for(int i = 0 ; i < this.treeData.node_order.length; i++){
2 26 Feb 07 jari 186             if(this.treeData.node_order[i] != -1) {
2 26 Feb 07 jari 187                 parentNodes[this.treeData.node_order[i]] =  findParent(i);
2 26 Feb 07 jari 188             }
2 26 Feb 07 jari 189         }
2 26 Feb 07 jari 190     }
2 26 Feb 07 jari 191     
2 26 Feb 07 jari 192     private int findParent(int index){
2 26 Feb 07 jari 193         int node = this.treeData.node_order[index];
2 26 Feb 07 jari 194         for(int i = 0; i < this.treeData.child_1_array.length; i++){
2 26 Feb 07 jari 195             if(this.treeData.child_1_array[i] == node)
2 26 Feb 07 jari 196                 return i;
2 26 Feb 07 jari 197         }
2 26 Feb 07 jari 198         for(int i = 0; i < this.treeData.child_2_array.length; i++){
2 26 Feb 07 jari 199             if(this.treeData.child_2_array[i] == node)
2 26 Feb 07 jari 200                 return i;
2 26 Feb 07 jari 201         }
2 26 Feb 07 jari 202         return 0;
2 26 Feb 07 jari 203     }
2 26 Feb 07 jari 204     
2 26 Feb 07 jari 205     /**
2 26 Feb 07 jari 206      * Sets specified tree attributies.
2 26 Feb 07 jari 207      */
2 26 Feb 07 jari 208     public void setProperties(float zeroThreshold, int minDistance, int maxDistance) {
2 26 Feb 07 jari 209         this.zero_threshold = zeroThreshold;
2 26 Feb 07 jari 210         this.min_pixels = minDistance;
2 26 Feb 07 jari 211         this.max_pixels = maxDistance;
2 26 Feb 07 jari 212         this.pHeights = getPixelHeights(treeData.node_order, treeData.height);
2 26 Feb 07 jari 213
2 26 Feb 07 jari 214         if (treeData.node_order.length > 1) {
2 26 Feb 07 jari 215             switch (this.orientation) {
2 26 Feb 07 jari 216                 case HORIZONTAL: 
2 26 Feb 07 jari 217                     setSizes(this.pHeights[treeData.node_order[treeData.node_order.length-2]] + xOrigin, getHeight());
2 26 Feb 07 jari 218                     for (int i = 0; i < this.dots.size(); i++) {
2 26 Feb 07 jari 219                       TEASEInfoBox dot = (TEASEInfoBox) this.dots.get(i);
2 26 Feb 07 jari 220                       dot.resetX(this.pHeights[treeData.node_order[treeData.node_order.length-2]] - 
2 26 Feb 07 jari 221                           this.pHeights[treeData.node_list[i]] + xOrigin);
2 26 Feb 07 jari 222                     }
2 26 Feb 07 jari 223                     break;
2 26 Feb 07 jari 224                 case VERTICAL:
2 26 Feb 07 jari 225                     setSizes(getWidth(), this.pHeights[treeData.node_order[treeData.node_order.length-2]]);
2 26 Feb 07 jari 226                     break;
2 26 Feb 07 jari 227             }
2 26 Feb 07 jari 228         }
2 26 Feb 07 jari 229     }
2 26 Feb 07 jari 230     
2 26 Feb 07 jari 231     /**
2 26 Feb 07 jari 232      * Set the tree threshold
2 26 Feb 07 jari 233      */
2 26 Feb 07 jari 234     public void setZeroThreshold(float zeroThreshold){
2 26 Feb 07 jari 235         this.zero_threshold = zeroThreshold;
2 26 Feb 07 jari 236     }
2 26 Feb 07 jari 237     
2 26 Feb 07 jari 238     /**
2 26 Feb 07 jari 239      * Returns the cluster row indices for the current distance threshold
2 26 Feb 07 jari 240      */
2 26 Feb 07 jari 241     public int [][] getClusterRowIndices(){
2 26 Feb 07 jari 242         
2 26 Feb 07 jari 243         int k = this.getNumberOfTerminalNodes();
2 26 Feb 07 jari 244         int index = 0;
2 26 Feb 07 jari 245         int [] endPoints;
2 26 Feb 07 jari 246         int [] rows;
2 26 Feb 07 jari 247         
2 26 Feb 07 jari 248         int testCnt = 0;
2 26 Feb 07 jari 249         int [] terminals;
2 26 Feb 07 jari 250         for(int i = 0; i < this.terminalNodes.length; i++){
2 26 Feb 07 jari 251             if(this.terminalNodes[i] == true)
2 26 Feb 07 jari 252                 testCnt++;
2 26 Feb 07 jari 253         }
2 26 Feb 07 jari 254         terminals = new int[testCnt];
2 26 Feb 07 jari 255         int terminalCnt = 0;
2 26 Feb 07 jari 256         
2 26 Feb 07 jari 257         for(int i = 0; i < this.terminalNodes.length; i++){
2 26 Feb 07 jari 258             if(this.terminalNodes[i] == true){
2 26 Feb 07 jari 259                 terminals[terminalCnt] = i;
2 26 Feb 07 jari 260                 terminalCnt++;
2 26 Feb 07 jari 261             }
2 26 Feb 07 jari 262         }
2 26 Feb 07 jari 263         
2 26 Feb 07 jari 264         int [][] clusters = new int[terminals.length][];
2 26 Feb 07 jari 265         
2 26 Feb 07 jari 266         for(int i = 0; i < clusters.length; i++){
2 26 Feb 07 jari 267             index = terminals[i];
2 26 Feb 07 jari 268             if(index >= this.treeData.node_order.length){
2 26 Feb 07 jari 269                 endPoints = this.getSubTreeEndPointElements(index);
2 26 Feb 07 jari 270                 
2 26 Feb 07 jari 271             }
2 26 Feb 07 jari 272             else{
2 26 Feb 07 jari 273                 endPoints = new int[2];
2 26 Feb 07 jari 274                 endPoints[1] = (int)this.positions[index];
2 26 Feb 07 jari 275                 endPoints[0] = (int)this.positions[index];
2 26 Feb 07 jari 276             }
2 26 Feb 07 jari 277             
2 26 Feb 07 jari 278             rows = new int[endPoints[1]-endPoints[0]+1];
2 26 Feb 07 jari 279             // rows = new int[endPoints[1]-endPoints[0]+1];
2 26 Feb 07 jari 280             
2 26 Feb 07 jari 281             for(int j = 0; j < rows.length; j++){
2 26 Feb 07 jari 282                 rows[j] = endPoints[0]+j;
2 26 Feb 07 jari 283             }
2 26 Feb 07 jari 284             clusters[i] = rows;
2 26 Feb 07 jari 285         }
2 26 Feb 07 jari 286         return clusters;
2 26 Feb 07 jari 287     }
2 26 Feb 07 jari 288     
2 26 Feb 07 jari 289     /**
2 26 Feb 07 jari 290      * Sets the tree height based on min and max distances supplied
2 26 Feb 07 jari 291      */
2 26 Feb 07 jari 292     public void setPixelHeightLimits(int minDistance, int maxDistance){
2 26 Feb 07 jari 293         this.min_pixels = minDistance;
2 26 Feb 07 jari 294         this.max_pixels = maxDistance;
2 26 Feb 07 jari 295         this.pHeights   = getPixelHeights(treeData.node_order, treeData.height);
2 26 Feb 07 jari 296         if (treeData.node_order.length > 1) {
2 26 Feb 07 jari 297             switch (this.orientation) {
2 26 Feb 07 jari 298                 case HORIZONTAL:
2 26 Feb 07 jari 299                     setSizes(this.pHeights[treeData.node_order[treeData.node_order.length-2]] + xOrigin, getHeight());
2 26 Feb 07 jari 300                     for (int i = 0; i < this.dots.size(); i++) {
2 26 Feb 07 jari 301                       TEASEInfoBox dot = (TEASEInfoBox) this.dots.get(i);
2 26 Feb 07 jari 302                       dot.resetX(this.pHeights[treeData.node_order[treeData.node_order.length-2]] - 
2 26 Feb 07 jari 303                           this.pHeights[treeData.node_list[i]] + xOrigin);
2 26 Feb 07 jari 304                     }
2 26 Feb 07 jari 305                     break;
2 26 Feb 07 jari 306                 case VERTICAL:
2 26 Feb 07 jari 307                     setSizes(getWidth(), this.pHeights[treeData.node_order[treeData.node_order.length-2]]);
2 26 Feb 07 jari 308                     break;
2 26 Feb 07 jari 309             }
2 26 Feb 07 jari 310         }
2 26 Feb 07 jari 311     }
2 26 Feb 07 jari 312     
2 26 Feb 07 jari 313     
2 26 Feb 07 jari 314     /**
2 26 Feb 07 jari 315      * Sets horizontal margin (offset for sample tree)
2 26 Feb 07 jari 316      */
2 26 Feb 07 jari 317     public void setHorizontalOffset(int offset){
2 26 Feb 07 jari 318         this.horizontalOffset = offset;
2 26 Feb 07 jari 319     }
2 26 Feb 07 jari 320     
2 26 Feb 07 jari 321     /**
2 26 Feb 07 jari 322      *  finds min dist in tree, initializes zeroThreshold
2 26 Feb 07 jari 323      */
2 26 Feb 07 jari 324     private float findMinDistance(){
2 26 Feb 07 jari 325         float min = Float.POSITIVE_INFINITY;
2 26 Feb 07 jari 326         for(int i = 0; i < treeData.height.length;i++){
2 26 Feb 07 jari 327             min = Math.min(min, treeData.height[i]);
2 26 Feb 07 jari 328         }
2 26 Feb 07 jari 329         return min;
2 26 Feb 07 jari 330     }
2 26 Feb 07 jari 331     
2 26 Feb 07 jari 332     /**
2 26 Feb 07 jari 333      * Sets node color.
2 26 Feb 07 jari 334      */
2 26 Feb 07 jari 335     public void setNodeColor(int node, Color color) {
2 26 Feb 07 jari 336         setSubTreeColor(node, color);
2 26 Feb 07 jari 337         repaint();
2 26 Feb 07 jari 338     }
2 26 Feb 07 jari 339     
2 26 Feb 07 jari 340     private void setSubTreeColor(int node, Color color) {
2 26 Feb 07 jari 341         this.nodesColors[node] = color;
2 26 Feb 07 jari 342         if (treeData.child_1_array[node] != -1) {
2 26 Feb 07 jari 343             setNodeColor(treeData.child_1_array[node], color);
2 26 Feb 07 jari 344         }
2 26 Feb 07 jari 345         if (treeData.child_2_array[node] != -1) {
2 26 Feb 07 jari 346             setNodeColor(treeData.child_2_array[node], color);
2 26 Feb 07 jari 347         }
2 26 Feb 07 jari 348     }
2 26 Feb 07 jari 349     
2 26 Feb 07 jari 350     /**
2 26 Feb 07 jari 351      * Clears all the colored tree nodes.
2 26 Feb 07 jari 352      */
2 26 Feb 07 jari 353     public void resetNodeColors() {
2 26 Feb 07 jari 354         for (int i = this.nodesColors.length; --i >= 0;) {
2 26 Feb 07 jari 355             this.nodesColors[i] = null;
2 26 Feb 07 jari 356         }
2 26 Feb 07 jari 357         repaint();
2 26 Feb 07 jari 358     }
2 26 Feb 07 jari 359     
2 26 Feb 07 jari 360     /**
2 26 Feb 07 jari 361      * Returns the zero threshold attribute.
2 26 Feb 07 jari 362      */
2 26 Feb 07 jari 363     public float getZeroThreshold() {
2 26 Feb 07 jari 364         return zero_threshold;
2 26 Feb 07 jari 365     }
2 26 Feb 07 jari 366     
2 26 Feb 07 jari 367     /**
2 26 Feb 07 jari 368      * Returns the min distance attribute.
2 26 Feb 07 jari 369      */
2 26 Feb 07 jari 370     public int getMinDistance() {
2 26 Feb 07 jari 371         return min_pixels;
2 26 Feb 07 jari 372     }
2 26 Feb 07 jari 373     
2 26 Feb 07 jari 374     /**
2 26 Feb 07 jari 375      * Returns the max distance attribute.
2 26 Feb 07 jari 376      */
2 26 Feb 07 jari 377     public int getMaxDistance() {
2 26 Feb 07 jari 378         return max_pixels;
2 26 Feb 07 jari 379     }
2 26 Feb 07 jari 380     
2 26 Feb 07 jari 381     /**
2 26 Feb 07 jari 382      * Returns the minimum node distance
2 26 Feb 07 jari 383      */
2 26 Feb 07 jari 384     public float getMinNodeDistance(){
2 26 Feb 07 jari 385         return minHeight;
2 26 Feb 07 jari 386     }
2 26 Feb 07 jari 387     
2 26 Feb 07 jari 388     /**
2 26 Feb 07 jari 389      * Returns the maximum node distance
2 26 Feb 07 jari 390      */
2 26 Feb 07 jari 391     public float getMaxNodeDistance(){
2 26 Feb 07 jari 392         return maxHeight;
2 26 Feb 07 jari 393     }
2 26 Feb 07 jari 394     
2 26 Feb 07 jari 395     /**
2 26 Feb 07 jari 396      *
2 26 Feb 07 jari 397      */
2 26 Feb 07 jari 398     public int getNumberOfTerminalNodes(){
2 26 Feb 07 jari 399         int n = 0;
2 26 Feb 07 jari 400         int index = 0;
2 26 Feb 07 jari 401         float [] height = this.treeData.height;
2 26 Feb 07 jari 402         int [] nodeOrder = this.treeData.node_order;
2 26 Feb 07 jari 403         
2 26 Feb 07 jari 404         for(int i = 0; i < nodeOrder.length; i++){
2 26 Feb 07 jari 405             index = nodeOrder[i];
2 26 Feb 07 jari 406             if(index == -1 || height[index] < zero_threshold){
2 26 Feb 07 jari 407                 continue;
2 26 Feb 07 jari 408             }
2 26 Feb 07 jari 409             n++;
2 26 Feb 07 jari 410         }
2 26 Feb 07 jari 411         return n+1;
2 26 Feb 07 jari 412     }
2 26 Feb 07 jari 413     
2 26 Feb 07 jari 414     /**
2 26 Feb 07 jari 415      * Returns a boolean array indicating which nodes are terminal
2 26 Feb 07 jari 416      */
2 26 Feb 07 jari 417     public boolean [] getTerminalNodes(){
2 26 Feb 07 jari 418         return terminalNodes;
2 26 Feb 07 jari 419     }
2 26 Feb 07 jari 420     
2 26 Feb 07 jari 421     /**
2 26 Feb 07 jari 422      * Returns min height of the tree nodes.
2 26 Feb 07 jari 423      */
2 26 Feb 07 jari 424     private float getMinHeight(int[] nodeOrder, float[] height) {
2 26 Feb 07 jari 425         float min = Float.MAX_VALUE;
2 26 Feb 07 jari 426         for (int i=0; i<nodeOrder.length-1; i++) {
2 26 Feb 07 jari 427             min = Math.min(min, height[nodeOrder[i]]);
2 26 Feb 07 jari 428         }
2 26 Feb 07 jari 429         return min;
2 26 Feb 07 jari 430     }
2 26 Feb 07 jari 431     
2 26 Feb 07 jari 432     /**
2 26 Feb 07 jari 433      * Returns true if tree is flat
2 26 Feb 07 jari 434      */
2 26 Feb 07 jari 435     private boolean flatTreeCheck(float [] height){
2 26 Feb 07 jari 436         if(height.length == 1)
2 26 Feb 07 jari 437             return false;
2 26 Feb 07 jari 438         
2 26 Feb 07 jari 439         for(int i = 0; i < height.length-1; i++){
2 26 Feb 07 jari 440             if(height[i] != height[i+1])
2 26 Feb 07 jari 441                 return false;
2 26 Feb 07 jari 442         }
2 26 Feb 07 jari 443         return true;
2 26 Feb 07 jari 444     }
2 26 Feb 07 jari 445     
2 26 Feb 07 jari 446     /**
2 26 Feb 07 jari 447      * Returns height of the tree nodes.
2 26 Feb 07 jari 448      */
2 26 Feb 07 jari 449     private float getMaxHeight(int[] nodeOrder, float[] height) {
2 26 Feb 07 jari 450         float max = Float.MIN_VALUE;
2 26 Feb 07 jari 451         for (int i=0; i<nodeOrder.length-1; i++) {
2 26 Feb 07 jari 452             max = Math.max(max, height[nodeOrder[i]]);
2 26 Feb 07 jari 453         }
2 26 Feb 07 jari 454         //System.out.println("min height of the tree nodes"+max);
2 26 Feb 07 jari 455         return max;
2 26 Feb 07 jari 456     }
2 26 Feb 07 jari 457     
2 26 Feb 07 jari 458     /**
2 26 Feb 07 jari 459      * Deselects the tree.
2 26 Feb 07 jari 460      */
2 26 Feb 07 jari 461     private void deselect(boolean[] selected) {
2 26 Feb 07 jari 462         for (int i = selected.length; --i >= 0;) {
2 26 Feb 07 jari 463             selected[i] = false;
2 26 Feb 07 jari 464         }
2 26 Feb 07 jari 465     }
2 26 Feb 07 jari 466     
2 26 Feb 07 jari 467     /**
2 26 Feb 07 jari 468      * Deselects all nodes
2 26 Feb 07 jari 469      */
2 26 Feb 07 jari 470     public void deselectAllNodes(){
2 26 Feb 07 jari 471         deselect(this.selected);
2 26 Feb 07 jari 472     }
2 26 Feb 07 jari 473     
2 26 Feb 07 jari 474     
2 26 Feb 07 jari 475     /**
2 26 Feb 07 jari 476      * Fills in an array by -1 values.
2 26 Feb 07 jari 477      */
2 26 Feb 07 jari 478     private void clear(int[] array) {
2 26 Feb 07 jari 479         for (int i = array.length; --i >= 0;) {
2 26 Feb 07 jari 480             array[i] = -1;
2 26 Feb 07 jari 481         }
2 26 Feb 07 jari 482     }
2 26 Feb 07 jari 483     
2 26 Feb 07 jari 484     /**
2 26 Feb 07 jari 485      * Calculates the current scale.
2 26 Feb 07 jari 486      */
2 26 Feb 07 jari 487     private float getScale() {
2 26 Feb 07 jari 488         // return this.min_pixels/Math.max(this.minHeight, this.zero_threshold);
2 26 Feb 07 jari 489         //return 1.0f;
2 26 Feb 07 jari 490         return this.max_pixels/this.maxHeight;
2 26 Feb 07 jari 491     }
2 26 Feb 07 jari 492     
2 26 Feb 07 jari 493     /**
2 26 Feb 07 jari 494      * Calculates tree node y positions.
2 26 Feb 07 jari 495      */
2 26 Feb 07 jari 496     private float[] getPositions(int[] nodeOrder, int[] child1, int[] child2) {
2 26 Feb 07 jari 497         float[] positions = new float[child1.length];
2 26 Feb 07 jari 498         Arrays.fill(positions, -1);
2 26 Feb 07 jari 499         if (nodeOrder.length < 2) {
2 26 Feb 07 jari 500             return positions;
2 26 Feb 07 jari 501         }
2 26 Feb 07 jari 502         fillPositions(positions, child1, child2, 0, child1.length-2);
2 26 Feb 07 jari 503         int node;
2 26 Feb 07 jari 504         for (int i=0; i<nodeOrder.length-1; i++) {
2 26 Feb 07 jari 505             node = nodeOrder[i];
2 26 Feb 07 jari 506             positions[node] = (positions[child1[node]] + positions[child2[node]])/2f;
2 26 Feb 07 jari 507         }
2 26 Feb 07 jari 508 //        System.out.println("HCLTree 511, positions[]");
2 26 Feb 07 jari 509 //        for(int i = 0 ; i < positions.length;i++) {
2 26 Feb 07 jari 510 //          System.out.print(positions[i]+"  ");
2 26 Feb 07 jari 511 //        }
2 26 Feb 07 jari 512         return positions;
2 26 Feb 07 jari 513     }
2 26 Feb 07 jari 514     
2 26 Feb 07 jari 515     private int fillPositions(float[] positions, int[] child1, int[] child2, int pos, int index) {
2 26 Feb 07 jari 516         if (child1[index] != -1) {
2 26 Feb 07 jari 517             pos = fillPositions(positions, child1, child2, pos, child1[index]);
2 26 Feb 07 jari 518         }
2 26 Feb 07 jari 519         if (child2[index] != -1) {
2 26 Feb 07 jari 520             pos = fillPositions(positions, child1, child2, pos, child2[index]);
2 26 Feb 07 jari 521         } else {
2 26 Feb 07 jari 522             positions[index] = pos;
2 26 Feb 07 jari 523             pos++;
2 26 Feb 07 jari 524         }
2 26 Feb 07 jari 525         return pos;
2 26 Feb 07 jari 526     }
2 26 Feb 07 jari 527     
2 26 Feb 07 jari 528     /**
2 26 Feb 07 jari 529      * Returns heights shifted by min distance, corrects for distance polarity change
2 26 Feb 07 jari 530      */
2 26 Feb 07 jari 531     private float[] shiftHeights(float [] height, float minH){
2 26 Feb 07 jari 532         for(int i = 0; i < height.length; i++)
2 26 Feb 07 jari 533             height[i] = height[i] - minH;
2 26 Feb 07 jari 534         return height;
2 26 Feb 07 jari 535     }
2 26 Feb 07 jari 536     
2 26 Feb 07 jari 537     
2 26 Feb 07 jari 538     /**
2 26 Feb 07 jari 539      * Returns nodes heights in pixels.
2 26 Feb 07 jari 540      */
2 26 Feb 07 jari 541     private int[] getPixelHeights(int[] nodeOrder, float[] height) {
2 26 Feb 07 jari 542         float scale = getScale();
2 26 Feb 07 jari 543         int[] pHeights = new int[nodeOrder.length*2];
2 26 Feb 07 jari 544         int node;
2 26 Feb 07 jari 545         int child_1, child_2;
2 26 Feb 07 jari 546         for (int i=0; i<nodeOrder.length-1; i++) {
2 26 Feb 07 jari 547             node = nodeOrder[i];
2 26 Feb 07 jari 548             child_1 = treeData.child_1_array[node];
2 26 Feb 07 jari 549             child_2 = treeData.child_2_array[node];
2 26 Feb 07 jari 550             
2 26 Feb 07 jari 551             pHeights[node] = Math.max(pHeights[child_1], pHeights[child_2]) + 
2 26 Feb 07 jari 552       Math.max(Math.min((int)Math.round(height[node]*scale), max_pixels), min_pixels);
2 26 Feb 07 jari 553         }
2 26 Feb 07 jari 554 //        System.out.println("HCLTree 553");
2 26 Feb 07 jari 555 //        for (int i = 0 ; i < pHeights.length; i++)
2 26 Feb 07 jari 556 //          System.out.print(pHeights[i]+ "  ");
2 26 Feb 07 jari 557         return pHeights;
2 26 Feb 07 jari 558     }
2 26 Feb 07 jari 559     
2 26 Feb 07 jari 560     /**
2 26 Feb 07 jari 561      * Paints the tree into specified graphics.
2 26 Feb 07 jari 562      */
2 26 Feb 07 jari 563     public void paint(Graphics g) {
2 26 Feb 07 jari 564         
2 26 Feb 07 jari 565         super.paint(g);
2 26 Feb 07 jari 566         if (this.treeData.node_order.length == 1){
2 26 Feb 07 jari 567             g.setColor(Color.black);
2 26 Feb 07 jari 568             g.drawLine(0,0,10,0);
2 26 Feb 07 jari 569         }
2 26 Feb 07 jari 570         
2 26 Feb 07 jari 571         for(int i = 0 ; i < this.terminalNodes.length; i++){
2 26 Feb 07 jari 572             terminalNodes[i] = false;
2 26 Feb 07 jari 573         }
2 26 Feb 07 jari 574         
2 26 Feb 07 jari 575         if (this.treeData.node_order.length < 2) {
2 26 Feb 07 jari 576             return;
2 26 Feb 07 jari 577         }
2 26 Feb 07 jari 578         int sign = 1;
2 26 Feb 07 jari 579         if (this.orientation == VERTICAL) {
2 26 Feb 07 jari 580             ((Graphics2D)g).rotate(-Math.PI/2.0);
2 26 Feb 07 jari 581             sign = -1;
2 26 Feb 07 jari 582         }
2 26 Feb 07 jari 583         int max_node_height = this.pHeights[this.treeData.node_order[this.treeData.node_order.length-2]];
2 26 Feb 07 jari 584         
2 26 Feb 07 jari 585         int node;
2 26 Feb 07 jari 586         int child_1, child_2;
2 26 Feb 07 jari 587         int child_1_x1, child_1_x2, child_1_y;
2 26 Feb 07 jari 588         int child_2_x1, child_2_x2, child_2_y;
2 26 Feb 07 jari 589         for (int i=0; i<this.treeData.node_order.length-1; i++) {
2 26 Feb 07 jari 590             node = this.treeData.node_order[i];
2 26 Feb 07 jari 591             child_1 = this.treeData.child_1_array[node];
2 26 Feb 07 jari 592             child_2 = this.treeData.child_2_array[node];
2 26 Feb 07 jari 593             child_1_x1 = (max_node_height-this.pHeights[node])*sign;
2 26 Feb 07 jari 594             child_1_x2 = (max_node_height-this.pHeights[child_1])*sign;
2 26 Feb 07 jari 595             child_1_y  = (int)(this.positions[child_1]*this.stepSize)+this.stepSize/2;
2 26 Feb 07 jari 596             child_2_x1 = (max_node_height-this.pHeights[node])*sign;
2 26 Feb 07 jari 597             child_2_x2 = (max_node_height-this.pHeights[child_2])*sign;
2 26 Feb 07 jari 598             child_2_y  = (int)(this.positions[child_2]*this.stepSize)+this.stepSize/2;
2 26 Feb 07 jari 599             
2 26 Feb 07 jari 600             
2 26 Feb 07 jari 601             
2 26 Feb 07 jari 602             if (this.nodesColors[node] == null){
2 26 Feb 07 jari 603                 if(this.treeData.height[node] >= zero_threshold) {
2 26 Feb 07 jari 604                     g.setColor(lineColor);
2 26 Feb 07 jari 605                     this.terminalNodes[node] = false;
2 26 Feb 07 jari 606                     if(this.pHeights[child_1] == 0)
2 26 Feb 07 jari 607                         this.terminalNodes[child_1] = true;
2 26 Feb 07 jari 608                     if(this.pHeights[child_2] == 0)
2 26 Feb 07 jari 609                         this.terminalNodes[child_2] = true;
2 26 Feb 07 jari 610                 } else{
2 26 Feb 07 jari 611                     g.setColor(belowThrColor);
2 26 Feb 07 jari 612                     this.terminalNodes[node] = false;
2 26 Feb 07 jari 613                     
2 26 Feb 07 jari 614                     if(this.treeData.height[parentNodes[node]] >= zero_threshold){
2 26 Feb 07 jari 615                         drawWedge(g, node, child_1_x1+xOrigin, child_2_x1+xOrigin, child_1_y, child_2_y);
2 26 Feb 07 jari 616                         this.terminalNodes[node] = true;
2 26 Feb 07 jari 617                         this.terminalNodes[child_1] = false;
2 26 Feb 07 jari 618                         this.terminalNodes[child_2] = false;
2 26 Feb 07 jari 619                     }
2 26 Feb 07 jari 620                 }
2 26 Feb 07 jari 621             } else {
2 26 Feb 07 jari 622                 g.setColor(this.nodesColors[node]);
2 26 Feb 07 jari 623                 if(this.treeData.height[node] >= zero_threshold) {
2 26 Feb 07 jari 624                     //  g.setColor(lineColor);
2 26 Feb 07 jari 625                     this.terminalNodes[node] = false;
2 26 Feb 07 jari 626                     if(this.pHeights[child_1] == 0)
2 26 Feb 07 jari 627                         this.terminalNodes[child_1] = true;
2 26 Feb 07 jari 628                     if(this.pHeights[child_2] == 0)
2 26 Feb 07 jari 629                         this.terminalNodes[child_2] = true;
2 26 Feb 07 jari 630                 } else{
2 26 Feb 07 jari 631                     //   g.setColor(belowThrColor);
2 26 Feb 07 jari 632                     this.terminalNodes[node] = false;
2 26 Feb 07 jari 633                     
2 26 Feb 07 jari 634                     if(this.treeData.height[parentNodes[node]] > zero_threshold){
2 26 Feb 07 jari 635                         drawWedge(g, node, child_1_x1+xOrigin, child_2_x1+xOrigin, child_1_y, child_2_y);
2 26 Feb 07 jari 636                         this.terminalNodes[node] = true;
2 26 Feb 07 jari 637                         this.terminalNodes[child_1] = false;
2 26 Feb 07 jari 638                         this.terminalNodes[child_2] = false;
2 26 Feb 07 jari 639                     }
2 26 Feb 07 jari 640                 }
2 26 Feb 07 jari 641                 
2 26 Feb 07 jari 642             }
2 26 Feb 07 jari 643             
2 26 Feb 07 jari 644             if (this.selected[node])
2 26 Feb 07 jari 645                 g.setColor(selectedLineColor);
2 26 Feb 07 jari 646             
2 26 Feb 07 jari 647             /*
2 26 Feb 07 jari 648             if (this.selected[node]) {
2 26 Feb 07 jari 649                 g.setColor(selectedLineColor);
2 26 Feb 07 jari 650             } else {
2 26 Feb 07 jari 651              
2 26 Feb 07 jari 652                 if (this.nodesColors[node] == null){
2 26 Feb 07 jari 653                     if(this.treeData.height[node] >= zero_threshold) {
2 26 Feb 07 jari 654                         g.setColor(lineColor);
2 26 Feb 07 jari 655                         this.terminalNodes[node] = false;
2 26 Feb 07 jari 656                         if(this.pHeights[child_1] == 0)
2 26 Feb 07 jari 657                             this.terminalNodes[child_1] = true;
2 26 Feb 07 jari 658                         if(this.pHeights[child_2] == 0)
2 26 Feb 07 jari 659                             this.terminalNodes[child_2] = true;
2 26 Feb 07 jari 660                     } else{
2 26 Feb 07 jari 661                         g.setColor(belowThrColor);
2 26 Feb 07 jari 662                         this.terminalNodes[node] = false;
2 26 Feb 07 jari 663              
2 26 Feb 07 jari 664                         if(this.treeData.height[parentNodes[node]] >= zero_threshold){
2 26 Feb 07 jari 665                             drawWedge(g, node, child_1_x1+xOrigin, child_2_x1+xOrigin, child_1_y, child_2_y);
2 26 Feb 07 jari 666                             this.terminalNodes[node] = true;
2 26 Feb 07 jari 667                             this.terminalNodes[child_1] = false;
2 26 Feb 07 jari 668                             this.terminalNodes[child_2] = false;
2 26 Feb 07 jari 669                         }
2 26 Feb 07 jari 670                     }
2 26 Feb 07 jari 671                 } else {
2 26 Feb 07 jari 672                     g.setColor(this.nodesColors[node]);
2 26 Feb 07 jari 673                 }
2 26 Feb 07 jari 674             }
2 26 Feb 07 jari 675              
2 26 Feb 07 jari 676              */
2 26 Feb 07 jari 677
2 26 Feb 07 jari 678             if(this.orientation == HORIZONTAL){
2 26 Feb 07 jari 679                 g.drawLine(child_1_x1 + xOrigin, child_1_y, child_1_x2 + xOrigin, child_1_y);
2 26 Feb 07 jari 680                 g.drawLine(child_2_x1 + xOrigin, child_2_y, child_2_x2 + xOrigin, child_2_y);
2 26 Feb 07 jari 681                 g.drawLine(child_1_x1 + xOrigin, child_1_y, child_2_x1 + xOrigin, child_2_y);
2 26 Feb 07 jari 682             }
2 26 Feb 07 jari 683             else{
2 26 Feb 07 jari 684                 g.drawLine(child_1_x1, child_1_y + horizontalOffset, child_1_x2, child_1_y+ horizontalOffset);
2 26 Feb 07 jari 685                 g.drawLine(child_2_x1, child_2_y + horizontalOffset, child_2_x2, child_2_y+ horizontalOffset);
2 26 Feb 07 jari 686                 g.drawLine(child_1_x1, child_1_y + horizontalOffset, child_2_x1, child_2_y+ horizontalOffset);
2 26 Feb 07 jari 687             }
2 26 Feb 07 jari 688         }
2 26 Feb 07 jari 689         for (int i = 0; i < this.dots.size(); i ++) {
2 26 Feb 07 jari 690           TEASEInfoBox dot = (TEASEInfoBox)this.dots.get(i);
2 26 Feb 07 jari 691           dot.render(g);
2 26 Feb 07 jari 692         }
2 26 Feb 07 jari 693     }
2 26 Feb 07 jari 694     
2 26 Feb 07 jari 695     public void drawWedge(Graphics g, int node, int x1, int x2, int y1, int y2){
2 26 Feb 07 jari 696         int [] xs = new int[3];
2 26 Feb 07 jari 697         int [] ys = new int[3];
2 26 Feb 07 jari 698         
2 26 Feb 07 jari 699         
2 26 Feb 07 jari 700         int k = node;
2 26 Feb 07 jari 701         int k1 = node;
2 26 Feb 07 jari 702         while(this.treeData.child_1_array[k] != -1){
2 26 Feb 07 jari 703             k = this.treeData.child_1_array[k];
2 26 Feb 07 jari 704         }
2 26 Feb 07 jari 705         while(this.treeData.child_2_array[k1] != -1){
2 26 Feb 07 jari 706             k1 = this.treeData.child_2_array[k1];;
2 26 Feb 07 jari 707         }
2 26 Feb 07 jari 708         
2 26 Feb 07 jari 709         if(this.orientation == HORIZONTAL){
2 26 Feb 07 jari 710             ys[0] = (y2-y1)/2 + y1;
2 26 Feb 07 jari 711             ys[1] = (int)(this.positions[k]*this.stepSize)+this.stepSize/2;
2 26 Feb 07 jari 712             ys[2] = (int)(this.positions[k1]*this.stepSize)+this.stepSize/2;
2 26 Feb 07 jari 713             xs[0] = x1;
2 26 Feb 07 jari 714             xs[1] = this.pHeights[treeData.node_order[treeData.node_order.length-2]] + xOrigin;
2 26 Feb 07 jari 715             xs[2] = this.pHeights[treeData.node_order[treeData.node_order.length-2]] + xOrigin;
2 26 Feb 07 jari 716         } else {
2 26 Feb 07 jari 717             ys[0] = (y2-y1)/2 + y1 + horizontalOffset;
2 26 Feb 07 jari 718             ys[1] = (int)(this.positions[k]*this.stepSize)+this.stepSize/2 + horizontalOffset;
2 26 Feb 07 jari 719             ys[2] = (int)(this.positions[k1]*this.stepSize)+this.stepSize/2 + horizontalOffset;
2 26 Feb 07 jari 720             xs[0] = x1 - xOrigin;
2 26 Feb 07 jari 721             xs[1] = -1*this.pHeights[treeData.node_order[treeData.node_order.length-2]];
2 26 Feb 07 jari 722             xs[2] = -1*this.pHeights[treeData.node_order[treeData.node_order.length-2]];
2 26 Feb 07 jari 723         }
2 26 Feb 07 jari 724         
2 26 Feb 07 jari 725         Color color = g.getColor();
2 26 Feb 07 jari 726         Graphics2D g2 = (Graphics2D)g;
2 26 Feb 07 jari 727         Composite composite = g2.getComposite();
2 26 Feb 07 jari 728         
2 26 Feb 07 jari 729         g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.3f));
2 26 Feb 07 jari 730         g.setColor(Color.blue);
2 26 Feb 07 jari 731         g.fillPolygon( new Polygon(xs,ys,3));
2 26 Feb 07 jari 732         g.setColor(color);
2 26 Feb 07 jari 733         g2.setComposite(composite);
2 26 Feb 07 jari 734     }
2 26 Feb 07 jari 735     
2 26 Feb 07 jari 736     
2 26 Feb 07 jari 737     //THE FOLLOWING METHOD IS USED TO OVERRRIDE THE PAINT METHOD IN SUBCLASSES SUCH AS HCLSUPPORTTREE
2 26 Feb 07 jari 738     
2 26 Feb 07 jari 739     public void paintSubTree(Graphics g) {
2 26 Feb 07 jari 740         super.paint(g);
2 26 Feb 07 jari 741     }
2 26 Feb 07 jari 742     
2 26 Feb 07 jari 743     /**
2 26 Feb 07 jari 744      * Updates the tree size, if element size was changed.
2 26 Feb 07 jari 745      */
2 26 Feb 07 jari 746     public void onSelected(IFramework framework) {
2 26 Feb 07 jari 747         this.framework = framework;
2 26 Feb 07 jari 748         this.data = framework.getData();
2 26 Feb 07 jari 749         updateSize(framework.getDisplayMenu().getElementSize());
2 26 Feb 07 jari 750         
2 26 Feb 07 jari 751 //        for (int i = 0; i < this.dots.size(); i++)
2 26 Feb 07 jari 752 //          ((TEASEInfoBox)this.dots.get(i)).updateSize(framework.getDisplayMenu().getElementSize());
2 26 Feb 07 jari 753     }
2 26 Feb 07 jari 754     
2 26 Feb 07 jari 755     /**
2 26 Feb 07 jari 756      * Updates the tree size, if element size was changed.
2 26 Feb 07 jari 757      */
2 26 Feb 07 jari 758     public void onMenuChanged(IDisplayMenu menu) {
2 26 Feb 07 jari 759         updateSize(menu.getElementSize());
2 26 Feb 07 jari 760     }
2 26 Feb 07 jari 761     
2 26 Feb 07 jari 762     /**
2 26 Feb 07 jari 763      * Updates the tree size with specified element size.
2 26 Feb 07 jari 764      */
2 26 Feb 07 jari 765     protected void updateSize(Dimension elementSize) {
2 26 Feb 07 jari 766         switch (this.orientation) {
2 26 Feb 07 jari 767             case HORIZONTAL:
2 26 Feb 07 jari 768                 if (flatTree || this.stepSize == elementSize.height) {
2 26 Feb 07 jari 769                     return;
2 26 Feb 07 jari 770                 }
2 26 Feb 07 jari 771                 this.stepSize = elementSize.height;
2 26 Feb 07 jari 772                 setSizes(getPreferredSize().width, this.stepSize*this.treeData.node_order.length);
2 26 Feb 07 jari 773                 break;
2 26 Feb 07 jari 774             case VERTICAL:
2 26 Feb 07 jari 775                 if (flatTree || this.stepSize == elementSize.width) {
2 26 Feb 07 jari 776                     return;
2 26 Feb 07 jari 777                 }
2 26 Feb 07 jari 778                 this.stepSize = elementSize.width;
2 26 Feb 07 jari 779                 setSizes(this.stepSize*this.treeData.node_order.length, getPreferredSize().height);
2 26 Feb 07 jari 780                 break;
2 26 Feb 07 jari 781         }
2 26 Feb 07 jari 782     }
2 26 Feb 07 jari 783     
2 26 Feb 07 jari 784     /**
2 26 Feb 07 jari 785      * Sets the tree sizes.
2 26 Feb 07 jari 786      */
2 26 Feb 07 jari 787     public void setSizes(int width, int height) {
2 26 Feb 07 jari 788         if(orientation == HORIZONTAL){
2 26 Feb 07 jari 789             setSize(width, height);
2 26 Feb 07 jari 790             setPreferredSize(new Dimension(width, height));
2 26 Feb 07 jari 791         }
2 26 Feb 07 jari 792         else{
2 26 Feb 07 jari 793             setSize(this.stepSize*this.treeData.node_order.length, height);
2 26 Feb 07 jari 794             setPreferredSize(new Dimension(this.stepSize*this.treeData.node_order.length, height));
2 26 Feb 07 jari 795         }
2 26 Feb 07 jari 796     }
2 26 Feb 07 jari 797     
2 26 Feb 07 jari 798     /**
2 26 Feb 07 jari 799      * Returns the endpoint row indices for the subtree below a node
2 26 Feb 07 jari 800      */
2 26 Feb 07 jari 801     private int [] getSubTreeEndPointElements(int node){
2 26 Feb 07 jari 802         int [] endPoints = new int[2];
2 26 Feb 07 jari 803         endPoints[0] = (int)positions[node];
2 26 Feb 07 jari 804         endPoints[1] = (int)positions[node];
2 26 Feb 07 jari 805         int ptr = node;
2 26 Feb 07 jari 806         
2 26 Feb 07 jari 807         while(this.treeData.child_1_array[ptr] != -1)
2 26 Feb 07 jari 808             ptr = this.treeData.child_1_array[ptr];
2 26 Feb 07 jari 809         
2 26 Feb 07 jari 810         endPoints[0] = (int)positions[ptr];
2 26 Feb 07 jari 811         
2 26 Feb 07 jari 812         ptr = node;
2 26 Feb 07 jari 813         while(this.treeData.child_2_array[ptr] != -1)
2 26 Feb 07 jari 814             ptr = this.treeData.child_2_array[ptr];
2 26 Feb 07 jari 815         endPoints[1] = (int)positions[ptr];
2 26 Feb 07 jari 816         
2 26 Feb 07 jari 817         return endPoints;
2 26 Feb 07 jari 818     }
2 26 Feb 07 jari 819     
2 26 Feb 07 jari 820     
2 26 Feb 07 jari 821     /**
2 26 Feb 07 jari 822      * Selects node by specified x and y coordinaties.
2 26 Feb 07 jari 823      */
2 26 Feb 07 jari 824     private void selectNode(int x, int y) {
2 26 Feb 07 jari 825         deselect(this.selected);
2 26 Feb 07 jari 826         HCLCluster cluster = new HCLCluster(findNode(x, y), Integer.MAX_VALUE, Integer.MIN_VALUE);
2 26 Feb 07 jari 827         selectNode(cluster, cluster.root);
2 26 Feb 07 jari 828         fireEvent(cluster);
2 26 Feb 07 jari 829         repaint();
2 26 Feb 07 jari 830     }
2 26 Feb 07 jari 831     
2 26 Feb 07 jari 832     /**
2 26 Feb 07 jari 833      * Selects tree for specified root node.
2 26 Feb 07 jari 834      */
2 26 Feb 07 jari 835     private void selectNode(HCLCluster cluster, int node) {
2 26 Feb 07 jari 836         if (node == -1) {
2 26 Feb 07 jari 837             cluster.firstElem = -1;
2 26 Feb 07 jari 838             cluster.lastElem = -1;
2 26 Feb 07 jari 839             return;
2 26 Feb 07 jari 840         }
2 26 Feb 07 jari 841         this.selected[node] = true;
2 26 Feb 07 jari 842         if (this.treeData.child_1_array[node] != -1) {
2 26 Feb 07 jari 843             selectNode(cluster, this.treeData.child_1_array[node]);
2 26 Feb 07 jari 844         } else {
2 26 Feb 07 jari 845             if (this.positions[node] < cluster.firstElem) {
2 26 Feb 07 jari 846                 cluster.firstElem = (int)this.positions[node];
2 26 Feb 07 jari 847             }
2 26 Feb 07 jari 848             if (this.positions[node] > cluster.lastElem) {
2 26 Feb 07 jari 849                 cluster.lastElem = (int)this.positions[node];
2 26 Feb 07 jari 850             }
2 26 Feb 07 jari 851             cluster.setFinalSize();
2 26 Feb 07 jari 852         }
2 26 Feb 07 jari 853         if (this.treeData.child_2_array[node] != -1) {
2 26 Feb 07 jari 854             selectNode(cluster, this.treeData.child_2_array[node]);
2 26 Feb 07 jari 855         }
2 26 Feb 07 jari 856     }
2 26 Feb 07 jari 857     
2 26 Feb 07 jari 858     /**
2 26 Feb 07 jari 859      * Returns index of a node by specified x and y coordinaties.
2 26 Feb 07 jari 860      */
2 26 Feb 07 jari 861     private int findNode(int x, int y) {
2 26 Feb 07 jari 862         if(this.orientation == HORIZONTAL)
2 26 Feb 07 jari 863             x -= xOrigin; //add origin offset
2 26 Feb 07 jari 864         int max_node_height = this.pHeights[this.treeData.node_order[this.treeData.node_order.length-2]];
2 26 Feb 07 jari 865         int node;
2 26 Feb 07 jari 866         int child_1, child_2;
2 26 Feb 07 jari 867         int child_1_x1, child_1_x2, child_1_y;
2 26 Feb 07 jari 868         int child_2_x1, child_2_x2, child_2_y;
2 26 Feb 07 jari 869         for (int i=0; i<this.treeData.node_order.length-1; i++) {
2 26 Feb 07 jari 870             node = this.treeData.node_order[i];
2 26 Feb 07 jari 871             child_1 = this.treeData.child_1_array[node];
2 26 Feb 07 jari 872             child_2 = this.treeData.child_2_array[node];
2 26 Feb 07 jari 873             child_1_x1 = (max_node_height-this.pHeights[node]);
2 26 Feb 07 jari 874             child_1_y  = (int)(this.positions[child_1]*this.stepSize)+this.stepSize/2 + horizontalOffset;
2 26 Feb 07 jari 875             child_2_x1 = (max_node_height-this.pHeights[node]);
2 26 Feb 07 jari 876             child_2_y  = (int)(this.positions[child_2]*this.stepSize)+this.stepSize/2 + horizontalOffset;
2 26 Feb 07 jari 877             switch (this.orientation) {
2 26 Feb 07 jari 878                 case HORIZONTAL:
2 26 Feb 07 jari 879                     if (child_1_y < y && child_2_y > y && x > child_1_x1) {
2 26 Feb 07 jari 880                         return node;
2 26 Feb 07 jari 881                     }
2 26 Feb 07 jari 882                     break;
2 26 Feb 07 jari 883                 case VERTICAL:
2 26 Feb 07 jari 884                     if (child_1_y < x && child_2_y > x && y > child_1_x1) {
2 26 Feb 07 jari 885                         return node;
2 26 Feb 07 jari 886                     }
2 26 Feb 07 jari 887                     break;
2 26 Feb 07 jari 888             }
2 26 Feb 07 jari 889         }
2 26 Feb 07 jari 890         return -1;
2 26 Feb 07 jari 891     }
2 26 Feb 07 jari 892     
2 26 Feb 07 jari 893     public void saveGeneNodeHeights(){
2 26 Feb 07 jari 894         String line;
2 26 Feb 07 jari 895         int nodeIndex = 0;
2 26 Feb 07 jari 896         int child1, child2;
2 26 Feb 07 jari 897         
2 26 Feb 07 jari 898         File file = null;
2 26 Feb 07 jari 899 //        final JFileChooser fc = new JFileChooser(TMEV.getFile("data/"));
2 26 Feb 07 jari 900         String dataPath = TMEV.getDataPath();
2 26 Feb 07 jari 901         File fileLoc = TMEV.getFile("data/"); 
2 26 Feb 07 jari 902         // if the data path is null go to default, if not null and not exist then to to default
2 26 Feb 07 jari 903         // else use the dataPath
2 26 Feb 07 jari 904         if(dataPath != null) {
2 26 Feb 07 jari 905             fileLoc = new File(dataPath);
2 26 Feb 07 jari 906             if(!fileLoc.exists()) {
2 26 Feb 07 jari 907                 fileLoc = TMEV.getFile("data/");
2 26 Feb 07 jari 908             }
2 26 Feb 07 jari 909         }
2 26 Feb 07 jari 910         final JFileChooser fc = new JFileChooser(fileLoc);
2 26 Feb 07 jari 911         int ret = fc.showSaveDialog(new javax.swing.JFrame());
2 26 Feb 07 jari 912         if (ret == JFileChooser.APPROVE_OPTION) {
2 26 Feb 07 jari 913             file = fc.getSelectedFile();
2 26 Feb 07 jari 914         }
2 26 Feb 07 jari 915         else return;
2 26 Feb 07 jari 916         
2 26 Feb 07 jari 917         try{
2 26 Feb 07 jari 918             PrintWriter out = new PrintWriter(new FileOutputStream(file));
2 26 Feb 07 jari 919             
2 26 Feb 07 jari 920             for(int i = 0; i < this.treeData.node_order.length-1; i++){
2 26 Feb 07 jari 921                 line = "Node_"+String.valueOf(i)+"\t";
2 26 Feb 07 jari 922                 child1 = this.treeData.child_1_array[this.treeData.node_order[i]];
2 26 Feb 07 jari 923                 child2 = this.treeData.child_2_array[this.treeData.node_order[i]];
2 26 Feb 07 jari 924                 
2 26 Feb 07 jari 925                 if(child1 < this.treeData.height.length/2)
2 26 Feb 07 jari 926                     line += "Gene_" + String.valueOf(child1+1) + "\t";
2 26 Feb 07 jari 927                 else
2 26 Feb 07 jari 928                     line += "Node_" + String.valueOf(child1-this.treeData.height.length/2) + "\t";
2 26 Feb 07 jari 929                 
2 26 Feb 07 jari 930                 if(child2 < this.treeData.height.length/2)
2 26 Feb 07 jari 931                     line += "Gene_" + String.valueOf(child2+1) + "\t";
2 26 Feb 07 jari 932                 else
2 26 Feb 07 jari 933                     line += "Node_" + String.valueOf(child2-this.treeData.height.length/2) + "\t";
2 26 Feb 07 jari 934                 
2 26 Feb 07 jari 935                 line += String.valueOf(this.treeData.height[this.treeData.node_order[i]]);
2 26 Feb 07 jari 936                 
2 26 Feb 07 jari 937                 out.println(line);
2 26 Feb 07 jari 938             }
2 26 Feb 07 jari 939             out.flush();
2 26 Feb 07 jari 940             out.close();
2 26 Feb 07 jari 941         } catch (IOException ioe){
2 26 Feb 07 jari 942             JOptionPane.showMessageDialog(this, "Error saving node height file.", "Error", JOptionPane.WARNING_MESSAGE);
2 26 Feb 07 jari 943             ioe.printStackTrace();
2 26 Feb 07 jari 944         }
2 26 Feb 07 jari 945     }
2 26 Feb 07 jari 946     
2 26 Feb 07 jari 947     public void saveExperimentNodeHeights(){
2 26 Feb 07 jari 948         String line;
2 26 Feb 07 jari 949         int nodeIndex = 0;
2 26 Feb 07 jari 950         int child1, child2;
2 26 Feb 07 jari 951         
2 26 Feb 07 jari 952         File file = null;
2 26 Feb 07 jari 953 //        final JFileChooser fc = new JFileChooser(TMEV.getFile("data/"));
2 26 Feb 07 jari 954         String dataPath = TMEV.getDataPath();
2 26 Feb 07 jari 955         File fileLoc = TMEV.getFile("data/"); 
2 26 Feb 07 jari 956         // if the data path is null go to default, if not null and not exist then to to default
2 26 Feb 07 jari 957         // else use the dataPath
2 26 Feb 07 jari 958         if(dataPath != null) {
2 26 Feb 07 jari 959             fileLoc = new File(dataPath);
2 26 Feb 07 jari 960             if(!fileLoc.exists()) {
2 26 Feb 07 jari 961                 fileLoc = TMEV.getFile("data/");
2 26 Feb 07 jari 962             }
2 26 Feb 07 jari 963         }
2 26 Feb 07 jari 964         final JFileChooser fc = new JFileChooser(fileLoc);
2 26 Feb 07 jari 965         int ret = fc.showSaveDialog(new javax.swing.JFrame());
2 26 Feb 07 jari 966         if (ret == JFileChooser.APPROVE_OPTION) {
2 26 Feb 07 jari 967             file = fc.getSelectedFile();
2 26 Feb 07 jari 968         }
2 26 Feb 07 jari 969         else return;
2 26 Feb 07 jari 970         
2 26 Feb 07 jari 971         try{
2 26 Feb 07 jari 972             PrintWriter out = new PrintWriter(new FileOutputStream(file));
2 26 Feb 07 jari 973             
2 26 Feb 07 jari 974             for(int i = 0; i < this.treeData.node_order.length-1; i++){
2 26 Feb 07 jari 975                 line = "Node_"+String.valueOf(i)+"\t";
2 26 Feb 07 jari 976                 child1 = this.treeData.child_1_array[this.treeData.node_order[i]];
2 26 Feb 07 jari 977                 child2 = this.treeData.child_2_array[this.treeData.node_order[i]];
2 26 Feb 07 jari 978                 
2 26 Feb 07 jari 979                 if(child1 < this.treeData.height.length/2)
2 26 Feb 07 jari 980                     line += "Exp_" + String.valueOf(child1+1) + "\t";
2 26 Feb 07 jari 981                 else
2 26 Feb 07 jari 982                     line += "Node_" + String.valueOf(child1-this.treeData.height.length/2) + "\t";
2 26 Feb 07 jari 983                 
2 26 Feb 07 jari 984                 if(child2 < this.treeData.height.length/2)
2 26 Feb 07 jari 985                     line += "Exp_" + String.valueOf(child2+1) + "\t";
2 26 Feb 07 jari 986                 else
2 26 Feb 07 jari 987                     line += "Node_" + String.valueOf(child2-this.treeData.height.length/2) + "\t";
2 26 Feb 07 jari 988                 
2 26 Feb 07 jari 989                 line += String.valueOf(this.treeData.height[this.treeData.node_order[i]]);
2 26 Feb 07 jari 990                 
2 26 Feb 07 jari 991                 out.println(line);
2 26 Feb 07 jari 992             }
2 26 Feb 07 jari 993             out.flush();
2 26 Feb 07 jari 994             out.close();
2 26 Feb 07 jari 995         } catch (IOException ioe){
2 26 Feb 07 jari 996             JOptionPane.showMessageDialog(this, "Error saving node height file.", "Error", JOptionPane.WARNING_MESSAGE);
2 26 Feb 07 jari 997             ioe.printStackTrace();
2 26 Feb 07 jari 998         }
2 26 Feb 07 jari 999     }
2 26 Feb 07 jari 1000     
2 26 Feb 07 jari 1001     
2 26 Feb 07 jari 1002     public void saveAsNewickFile() {
2 26 Feb 07 jari 1003         NewickFileOutputDialog dialog;
2 26 Feb 07 jari 1004         String newickString;
2 26 Feb 07 jari 1005         String [] annKeys;
2 26 Feb 07 jari 1006         
2 26 Feb 07 jari 1007         if(this.orientation == HCLTree.HORIZONTAL) { //gene tree
2 26 Feb 07 jari 1008             annKeys = data.getFieldNames();
2 26 Feb 07 jari 1009         } else {  //sample tree
2 26 Feb 07 jari 1010             Vector annKeyVector = data.getSampleAnnotationFieldNames();
2 26 Feb 07 jari 1011             annKeys = new String[annKeyVector.size()];
2 26 Feb 07 jari 1012             for(int i = 0; i < annKeys.length; i++) {
2 26 Feb 07 jari 1013                 annKeys[i] = (String)(annKeyVector.elementAt(i));
2 26 Feb 07 jari 1014             }
2 26 Feb 07 jari 1015         }
2 26 Feb 07 jari 1016         
2 26 Feb 07 jari 1017         dialog = new NewickFileOutputDialog(framework.getFrame(), annKeys, this.orientation);
2 26 Feb 07 jari 1018         
2 26 Feb 07 jari 1019         if(dialog.showModal() == JOptionPane.OK_OPTION) {
2 26 Feb 07 jari 1020
2 26 Feb 07 jari 1021             if(this.orientation == HCLTree.HORIZONTAL)
2 26 Feb 07 jari 1022                 newickString = generateNewickStringForGeneTree(dialog.getAnnotationKey());
2 26 Feb 07 jari 1023             else
2 26 Feb 07 jari 1024                 newickString = generateNewickStringForSampleTree(dialog.getAnnotationKey());
2 26 Feb 07 jari 1025             
2 26 Feb 07 jari 1026             saveNewickString(newickString, dialog.getOutputFile());            
2 26 Feb 07 jari 1027         }        
2 26 Feb 07 jari 1028     }
2 26 Feb 07 jari 1029     
2 26 Feb 07 jari 1030     private void saveNewickString(String s, File outputFile) {
2 26 Feb 07 jari 1031         try {
2 26 Feb 07 jari 1032             BufferedWriter bw = new BufferedWriter(new FileWriter(outputFile));
2 26 Feb 07 jari 1033             bw.write(s);
2 26 Feb 07 jari 1034             bw.flush();
2 26 Feb 07 jari 1035             bw.close();
2 26 Feb 07 jari 1036         } catch (IOException ioe) {
2 26 Feb 07 jari 1037             JOptionPane.showMessageDialog(framework.getFrame(), "Error saving Newick file: "+outputFile.getAbsolutePath()+".<BR>"+
2 26 Feb 07 jari 1038             "Please check that file location is valid and permissions are open.", "IO Error Saving Newick File", JOptionPane.ERROR_MESSAGE);
2 26 Feb 07 jari 1039         }
2 26 Feb 07 jari 1040     }
2 26 Feb 07 jari 1041     
2 26 Feb 07 jari 1042     private String generateNewickStringForSampleTree(String annotationKey) {
2 26 Feb 07 jari 1043         
2 26 Feb 07 jari 1044         String s = new String("");
2 26 Feb 07 jari 1045         
2 26 Feb 07 jari 1046         int node, leftChild, rightChild, parent;
2 26 Feb 07 jari 1047         
2 26 Feb 07 jari 1048         float leftHeight, rightHeight;
2 26 Feb 07 jari 1049         
2 26 Feb 07 jari 1050         Hashtable treeHash = new Hashtable();
2 26 Feb 07 jari 1051         String nodeName = "";
2 26 Feb 07 jari 1052         
2 26 Feb 07 jari 1053         for(int i = 0; i < treeData.node_order.length-1; i++) {
2 26 Feb 07 jari 1054             node = treeData.node_order[i];
2 26 Feb 07 jari 1055             
2 26 Feb 07 jari 1056             leftChild = treeData.child_1_array[node];
2 26 Feb 07 jari 1057             rightChild = treeData.child_2_array[node];
2 26 Feb 07 jari 1058             
2 26 Feb 07 jari 1059             leftHeight = treeData.height[leftChild];
2 26 Feb 07 jari 1060             rightHeight = treeData.height[rightChild];
2 26 Feb 07 jari 1061             
2 26 Feb 07 jari 1062             parent = parentNodes[node];
2 26 Feb 07 jari 1063             
2 26 Feb 07 jari 1064             if(leftChild < this.treeData.height.length/2) {
2 26 Feb 07 jari 1065                 s = this.data.getSampleAnnotation(leftChild, annotationKey)+":"+String.valueOf(this.treeData.height[node]/2.0f);
2 26 Feb 07 jari 1066                 treeHash.put(String.valueOf(leftChild),s);
2 26 Feb 07 jari 1067             }
2 26 Feb 07 jari 1068             if(rightChild < this.treeData.height.length/2) {
2 26 Feb 07 jari 1069                 s = this.data.getSampleAnnotation(rightChild, annotationKey)+":"+String.valueOf(this.treeData.height[node]/2.0f);
2 26 Feb 07 jari 1070                 treeHash.put(String.valueOf(rightChild),s);
2 26 Feb 07 jari 1071             }
2 26 Feb 07 jari 1072             if(treeHash.containsKey(String.valueOf(leftChild)) && treeHash.containsKey(String.valueOf(rightChild))) {
2 26 Feb 07 jari 1073                 s = "("+treeHash.get(String.valueOf(leftChild))+","+treeHash.get(String.valueOf(rightChild))+"):"+String.valueOf(this.treeData.height[parentNodes[node]]/2.0f);
2 26 Feb 07 jari 1074                 treeHash.put(String.valueOf(node), s);
2 26 Feb 07 jari 1075                 
2 26 Feb 07 jari 1076                 //remove entries as they become obsolete
2 26 Feb 07 jari 1077                 treeHash.remove(String.valueOf(leftChild));
2 26 Feb 07 jari 1078                 treeHash.remove(String.valueOf(rightChild));
2 26 Feb 07 jari 1079             }
2 26 Feb 07 jari 1080         }        
2 26 Feb 07 jari 1081         return s+";";        
2 26 Feb 07 jari 1082     }
2 26 Feb 07 jari 1083     
2 26 Feb 07 jari 1084     
2 26 Feb 07 jari 1085     private String generateNewickStringForGeneTree(String annotationKey) {
2 26 Feb 07 jari 1086         
2 26 Feb 07 jari 1087         String [] fieldNames = data.getFieldNames();
2 26 Feb 07 jari 1088         
2 26 Feb 07 jari 1089         int attIndex = 0;  //element attribute index, annotation field index
2 26 Feb 07 jari 1090         for(int i = 0; i < fieldNames.length; i++) {
2 26 Feb 07 jari 1091             if(fieldNames[i].equals(annotationKey)) {
2 26 Feb 07 jari 1092                 attIndex = i;
2 26 Feb 07 jari 1093                 break;
2 26 Feb 07 jari 1094             }
2 26 Feb 07 jari 1095         }
2 26 Feb 07 jari 1096         
2 26 Feb 07 jari 1097         String s = new String("");
2 26 Feb 07 jari 1098         
2 26 Feb 07 jari 1099         int node, leftChild, rightChild, parent;
2 26 Feb 07 jari 1100         
2 26 Feb 07 jari 1101         float leftHeight, rightHeight;
2 26 Feb 07 jari 1102         
2 26 Feb 07 jari 1103         Hashtable treeHash = new Hashtable();
2 26 Feb 07 jari 1104         String nodeName = "";
2 26 Feb 07 jari 1105         
2 26 Feb 07 jari 1106         for(int i = 0; i < treeData.node_order.length-1; i++) {
2 26 Feb 07 jari 1107             node = treeData.node_order[i];
2 26 Feb 07 jari 1108             
2 26 Feb 07 jari 1109             leftChild = treeData.child_1_array[node];
2 26 Feb 07 jari 1110             rightChild = treeData.child_2_array[node];
2 26 Feb 07 jari 1111             
2 26 Feb 07 jari 1112             leftHeight = treeData.height[leftChild];
2 26 Feb 07 jari 1113             rightHeight = treeData.height[rightChild];
2 26 Feb 07 jari 1114             
2 26 Feb 07 jari 1115             parent = parentNodes[node];
2 26 Feb 07 jari 1116             
2 26 Feb 07 jari 1117             if(leftChild < this.treeData.height.length/2) {
2 26 Feb 07 jari 1118                 s = this.data.getElementAttribute(leftChild, attIndex)+":"+String.valueOf(this.treeData.height[node]/2.0f);
2 26 Feb 07 jari 1119                 treeHash.put(String.valueOf(leftChild),s);
2 26 Feb 07 jari 1120             }
2 26 Feb 07 jari 1121             if(rightChild < this.treeData.height.length/2) {
2 26 Feb 07 jari 1122                 s = this.data.getElementAttribute(rightChild, attIndex)+":"+String.valueOf(this.treeData.height[node]/2.0f);
2 26 Feb 07 jari 1123                 treeHash.put(String.valueOf(rightChild),s);
2 26 Feb 07 jari 1124             }
2 26 Feb 07 jari 1125             if(treeHash.containsKey(String.valueOf(leftChild)) && treeHash.containsKey(String.valueOf(rightChild))) {
2 26 Feb 07 jari 1126                 s = "("+treeHash.get(String.valueOf(leftChild))+","+treeHash.get(String.valueOf(rightChild))+"):"+String.valueOf(this.treeData.height[parentNodes[node]]/2.0f);
2 26 Feb 07 jari 1127                 treeHash.put(String.valueOf(node), s);
2 26 Feb 07 jari 1128                 
2 26 Feb 07 jari 1129                 //remove entries as they become obsolete
2 26 Feb 07 jari 1130                 treeHash.remove(String.valueOf(leftChild));
2 26 Feb 07 jari 1131                 treeHash.remove(String.valueOf(rightChild));
2 26 Feb 07 jari 1132             }
2 26 Feb 07 jari 1133         }        
2 26 Feb 07 jari 1134         return s+";";        
2 26 Feb 07 jari 1135     }
2 26 Feb 07 jari 1136     
2 26 Feb 07 jari 1137     /**
2 26 Feb 07 jari 1138      * Notifies the tree listener.
2 26 Feb 07 jari 1139      * @see HCLCluster
2 26 Feb 07 jari 1140      */
2 26 Feb 07 jari 1141     private void fireEvent(HCLCluster cluster) {
2 26 Feb 07 jari 1142         if (this.treeListener != null) {
2 26 Feb 07 jari 1143             this.treeListener.valueChanged(this, cluster);
2 26 Feb 07 jari 1144         }
2 26 Feb 07 jari 1145     }
2 26 Feb 07 jari 1146     
2 26 Feb 07 jari 1147     //***************************Inner Class*****************************//
2 26 Feb 07 jari 1148     
2 26 Feb 07 jari 1149     /**
2 26 Feb 07 jari 1150      * The class to listen to mouse events.
2 26 Feb 07 jari 1151      */
2 26 Feb 07 jari 1152     private class Listener extends MouseAdapter{
2 26 Feb 07 jari 1153         public void mouseClicked(MouseEvent e) {
2 26 Feb 07 jari 1154             if (SwingUtilities.isRightMouseButton(e)) {
2 26 Feb 07 jari 1155                 return;
2 26 Feb 07 jari 1156             }
2 26 Feb 07 jari 1157             selectNode(e.getX(), e.getY());
2 26 Feb 07 jari 1158         }
2 26 Feb 07 jari 1159     }
2 26 Feb 07 jari 1160
2 26 Feb 07 jari 1161   /**
2 26 Feb 07 jari 1162    * @return
2 26 Feb 07 jari 1163    */
2 26 Feb 07 jari 1164   public int getOrientation() {
2 26 Feb 07 jari 1165     return this.orientation;
2 26 Feb 07 jari 1166   }
2 26 Feb 07 jari 1167     private static class HCLTreePersistenceDelegate extends PersistenceDelegate {
2 26 Feb 07 jari 1168       public Expression instantiate(Object oldInstance, java.beans.Encoder encoder) {
2 26 Feb 07 jari 1169         HCLTree aTree = (HCLTree) oldInstance;
2 26 Feb 07 jari 1170         return new Expression(aTree, aTree.getClass(), "new", new Object[]{aTree.treeData, new Integer(aTree.orientation), aTree.dots});
2 26 Feb 07 jari 1171       }
2 26 Feb 07 jari 1172     }
2 26 Feb 07 jari 1173 }