org.phylowidget.tree.PhyloNode.java Source code

Java tutorial

Introduction

Here is the source code for org.phylowidget.tree.PhyloNode.java

Source

/*******************************************************************************
 * Copyright (c) 2007, 2008 Gregory Jordan
 * 
 * This file is part of PhyloWidget.
 * 
 * PhyloWidget is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 2 of the License, or (at your option) any later
 * version.
 * 
 * PhyloWidget is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU General Public License along with
 * PhyloWidget. If not, see <http://www.gnu.org/licenses/>.
 */
package org.phylowidget.tree;

import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import org.andrewberman.ui.tween.Tween;
import org.andrewberman.ui.tween.TweenQuad;
import org.andrewberman.ui.unsorted.Json;
import org.json.simple.JSONObject;
import org.phylowidget.PWContext;
import org.phylowidget.PWPlatform;
import org.phylowidget.PhyloTree;
import org.phylowidget.PhyloWidget;
import org.phylowidget.UsefulConstants;
import org.phylowidget.render.NodeRange;
import org.phylowidget.render.images.ImageSearcher;

final public class PhyloNode extends CachedVertex implements Comparable, UsefulConstants {
    private double layoutX, layoutY; // Layout position.
    private float realX, realY; // Real-world (i.e. screen) position, after scaling and translation of the layout.
    private float angle; // Angle (in radians) at which the node should be drawn. Clockwise from horizontal.

    public Point2D[] corners;
    public Rectangle2D.Float rect = new Rectangle2D.Float();

    private byte textAlign = ALIGN_LEFT;
    public static final byte ALIGN_LEFT = 0;
    public static final byte ALIGN_RIGHT = 1;

    public float textMult;
    public float unitTextWidth;
    //   public float aspectRatio; // Almost ready to get rid of this one...
    public boolean drawMe, isWithinScreen;

    public float bulgeFactor = 1;
    public boolean found = false;

    private int sorting = RootedTree.FORWARD.intValue();

    private int state = 0;
    public static final int NONE = 0;
    public static final int CUT = 1;
    public static final int COPY = 2;

    //   static TweenFriction fric = TweenFriction
    //         .tween(0.3f * PhyloWidget.TWEEN_FACTOR);
    static TweenQuad quad = TweenQuad.tween;
    static final float mult = 10000f;

    HashMap<String, String> annotations;

    private Tween xTween;
    private Tween yTween;
    public boolean labelWasDrawn;
    public boolean drawLineAndNode;
    public boolean drawLabel;
    public float lastTextSize;

    private ImageSearcher searchResults;
    public NodeRange range;

    PWContext context;

    public PhyloNode() {
        super();
        this.context = PWPlatform.getInstance().getThisAppContext();
        xTween = new Tween(null, quad, Tween.OUT, (float) layoutX, (float) layoutX, 30f);
        yTween = new Tween(null, quad, Tween.OUT, (float) layoutY, (float) layoutY, 30f);
        range = new NodeRange();
        range.node = this;
    }

    public void loadThumbImage() {
        if (searchResults == null)
            searchResults = new ImageSearcher(this);
        else
            searchResults.next();

        searchResults.loadThumbnailURL();
    }

    public void loadFullImage() {
        if (searchResults != null) {
            searchResults.loadFullImageURL();
        }
    }

    public String getFullImageURL() {
        if (getAnnotation("print_img") != null) {
            return getAnnotation("print_img");
        } else if (searchResults != null && context.config().outputFullSizeImages) {
            return searchResults.getFullImageURL();
        } else
            return null;
    }

    @Override
    public double getBranchLength() {
        if (!context.config().useBranchLengths)
            return 1;
        return super.getBranchLength();
    }

    public void setPosition(PhyloNode n) {
        if (n == null)
            return;
        setPosition(n.getLayoutX(), n.getLayoutY());
        fforward();
    }

    public void update() {
        //      zoomTextSize *= 0.9f;
        if (context.config().useAnimations) {
            xTween.update();
            yTween.update();
        } else {
            xTween.fforward();
            yTween.fforward();
        }
        layoutX = xTween.getPosition() / mult;
        layoutY = yTween.getPosition() / mult;
    }

    public void setPosition(float x, float y) {
        setLayoutX(x);
        setLayoutY(y);
    }

    public void fforward() {
        xTween.fforward();
        yTween.fforward();
        update();
    }

    public void setLayoutX(float x) {
        xTween.continueTo(x * mult, context.config().animationFrames);
        this.layoutX = x;
    }

    public void setLayoutY(float y) {
        yTween.continueTo(y * mult, context.config().animationFrames);
        this.layoutY = y;
    }

    public float getLayoutX() {
        return (float) layoutX;
    }

    public float getLayoutY() {
        return (float) layoutY;
    }

    public float getTargetX() {
        return xTween.getFinish() / mult;
    }

    public float getTargetY() {
        return yTween.getFinish() / mult;
    }

    public String toString() {
        return label;
    }

    public String getLabel() {
        return label;
    }

    public void setLabel(String s) {
        label = s;
        if (searchResults != null)
            searchResults.clear();
    }

    public int compareTo(Object o) {
        if (o instanceof PhyloNode) {
            PhyloNode that = (PhyloNode) o;
            float a = this.getTargetY();
            float b = that.getTargetY();
            if (a < b)
                return -1;
            else if (a > b)
                return 1;
        }
        return 0;
    }

    public void setState(int state) {
        this.state = state;
    }

    public int getState() {
        return state;
    }

    public float getX() {
        return realX;
    }

    public void setX(float realX) {
        this.realX = realX;
    }

    public float getY() {
        return realY;
    }

    public void setY(float realY) {
        this.realY = realY;
    }

    public boolean isNHX() {
        return (annotations != null);
    }

    public void clearAnnotations() {
        if (annotations != null)
            annotations.clear();
    }

    public void clearAnnotation(String key) {
        if (annotations == null)
            return;
        annotations.remove(key);
    }

    static NumberFormat fmt = DecimalFormat.getInstance();
    static {
        fmt.setMaximumFractionDigits(3);
    }

    public void setAnnotation(String key, double value) {
        String dblString = fmt.format(value);
        setAnnotation(key, dblString);
    }

    public void setAnnotation(String key, String value) {
        if (annotations == null)
            annotations = new HashMap<String, String>();
        if (value == null) {
            annotations.remove(key);
        } else {
            if (key.equalsIgnoreCase("name")) {
                getTree().setLabel(this, value);
                return;
            } else if (key.equalsIgnoreCase("branch length")) {
                getTree().setBranchLength(this, Double.parseDouble(value));
                return;
            } else if (key.length() <= 3) {
                annotations.put(key.toLowerCase(), value);
            } else {
                annotations.put(key, value); // GJ 2009-02-15 : stop lower-casing annotations for longer keys.
            }
        }
    }

    /**
     * Warning: MAY RETURN NULL
     * 
     * @param key
     * @return
     */
    public String getAnnotation(String key) {
        if (context == null) {
            if (annotations != null)
                return annotations.get(key.toLowerCase());
            else
                return null;
        }
        if (context.config().ignoreAnnotations)
            return null;
        if (annotations == null)
            return null;
        else
            return annotations.get(key.toLowerCase());
    }

    /**
     * May return null!
     * 
     * @return
     */
    public HashMap<String, String> getAnnotations() {
        if (context != null && context.config().ignoreAnnotations)
            return null;
        return annotations;
    }

    public HashMap<String, String> getFullAnnotations() {
        HashMap<String, String> annot = getAnnotations();
        if (annot == null)
            annot = new HashMap<String, String>();
        HashMap<String, String> clone = (HashMap<String, String>) annot.clone();
        clone.put("Label", getLabel());
        clone.put("Branch Length", "" + getTree().getBranchLength(this));
        return clone;
    }

    public HashMap<String, Object> getNodeInfo() {
        HashMap<String, Object> nodeInfo = new HashMap<String, Object>();
        HashMap<String, String> annotations = getFullAnnotations();
        HashMap<String, Object> calculations = new HashMap<String, Object>();
        calculations.put("Enclosed Leaves", getTree().getNumEnclosedLeaves(this));
        calculations.put("Depth to Root", getTree().getDepthToRoot(this));
        calculations.put("Branch Length to Root", getTree().getHeightToRoot(this));
        nodeInfo.put("calculations", calculations);
        nodeInfo.put("annotations", annotations);
        return nodeInfo;
    }

    public void setAngle(float angle) {
        this.angle = angle;
    }

    public float getAngle() {
        return angle;
    }

    public int getTextAlign() {
        return textAlign;
    }

    public void setTextAlign(int textAlign) {
        this.textAlign = (byte) textAlign;
    }

    public static boolean parseTruth(String s) {
        if (s.startsWith("T") || s.startsWith("t") || s.startsWith("y") || s.startsWith("Y") || s.equals("1"))
            return true;
        else
            return false;
    }

    public synchronized PhyloTree getTree() {
        if (range != null) {
            if (range.render != null) {
                return (PhyloTree) range.render.getTree();
            }
            System.out.println("Render null!");
        }
        System.out.println("Range null!");
        return null;
    }

    public void setAnnotationsFromJson(String jsonString) {
        JSONObject map = (JSONObject) Json.jsonToHash(jsonString);
        Set<Object> keys = map.keySet();
        for (Object o : keys) {
            System.out.println("JSON KEY:" + o);
            System.out.println("  VALUE:" + map.get(o).toString());
            String key = o.toString();
            String val = map.get(key).toString();
            if (key.equalsIgnoreCase("name"))
                getTree().setLabel(this, val);
            else if (key.equalsIgnoreCase("branch length"))
                getTree().setBranchLength(this, Double.parseDouble(val));
            else
                setAnnotation(key, val);
        }
    }

    //   public float getTrueAngle()
    //   {
    //      return trueAngle;
    //   }
    //
    //   public void setTrueAngle(float trueAngle)
    //   {
    //      this.trueAngle = trueAngle;
    //   }
}