/*
* JFLAP - Formal Languages and Automata Package
*
*
* Susan H. Rodger
* Computer Science Department
* Duke University
* August 27, 2009
* Copyright (c) 2002-2009
* All rights reserved.
* JFLAP is open source software. Please see the LICENSE for terms.
*
*/
package gui.tree;
import java.awt.geom.Point2D;
import java.util.HashMap;
import java.util.Map;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreeNode;
/**
* A LeafNodePlacer
places leaves so that they are evenly spaced
* horizontally.
*
* @author Thomas Finley
*/
public class LeafNodePlacer implements NodePlacer {
/**
* Given a TreeModel
that contains TreeNode
* objects, this method returns a map from all TreeNode
* objects to Point2D
points. This placer works according to
* a rather simple algorithm that places all nodes at a particular depth in
* a tree at regular intervals.
*
* @param tree
* the tree model
* @param drawer
* the object that draws the nodes in the tree
* @return a map from the nodes of the tree to points where those nodes
* should be drawn
*/
public Map placeNodes(TreeModel tree, NodeDrawer drawer) {
HashMap nodeToPoint = new HashMap();
int[] width = Trees.width(tree);
TreeNode[] leaves = Trees.leaves(tree);
int depth = Trees.depth(tree);
setPoints((TreeNode) tree.getRoot(), depth, 0, leaves.length,
new int[] { 0 }, nodeToPoint);
return nodeToPoint;
}
/**
* This will place the nodes. Oooo.
*
* @param node
* the current node being placed
* @param depth
* the depth of the tree
* @param thisDepth
* the depth of this node
* @param leaves
* the total number of leaves
* @param sofar
* the number of leaves placed sofar
* @param nodeToPoint
* the mapping of nodes to points
*/
private void setPoints(TreeNode node, int depth, int thisDepth, int leaves,
int[] sofar, Map nodeToPoint) {
TreeNode[] children = Trees.children(node);
float y = (float) (thisDepth + 1) / (float) (depth + 2);
if (children.length == 0) {
// It is a leaf!
float x = (float) (sofar[0] + 1) / (float) (leaves + 1);
nodeToPoint.put(node, new Point2D.Float(x, y));
sofar[0]++;
return;
}
// Not a leaf!
for (int i = 0; i < children.length; i++)
setPoints(children[i], depth, thisDepth + 1, leaves, sofar,
nodeToPoint);
Point2D leftmost = (Point2D) nodeToPoint.get(children[0]);
Point2D rightmost = (Point2D) nodeToPoint
.get(children[children.length - 1]);
float x = (float) ((leftmost.getX() + rightmost.getX()) / 2.0);
nodeToPoint.put(node, new Point2D.Float(x, y));
}
}