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