Java tutorial
/******************************************************************************* * 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; // } }