/*
* 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.Arrays;
import java.util.HashMap;
import java.util.Map;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreeNode;
/**
* A DefaultNodePlacer
places the nodes in a tree in a rather
* simple "top down" pattern.
*
* @author Thomas Finley
*/
public class DefaultNodePlacer implements NodePlacer {
/**
* Given a TreeModel
that contains TreeNode
* objects, this method returns a map from all TreeNode
* objects to Dimension2D
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), sofar = new int[width.length];
Arrays.fill(sofar, 0);
setPoints((TreeNode) tree.getRoot(), width.length - 1, 0, width, sofar,
nodeToPoint);
return nodeToPoint;
}
/**
* Recursively sets the points of the tree going the nodeToPoint
* structure as it goes.
*
* @param node
* the current node in the tree
* @param depth
* the total depth of the tree
* @param thisDepth
* the depth of this particular node
* @param width
* the array of all widths
* @param widthSofar
* the widths sofar
* @param nodeToPoint
* the mapping of nodes to points built
*/
private void setPoints(TreeNode node, int depth, int thisDepth,
int[] width, int[] widthSofar, Map nodeToPoint) {
// Scale points along ([0,1], [0,1]).
float x = (float) (widthSofar[thisDepth] + 1)
/ (float) (width[thisDepth] + 1);
float y = (float) (thisDepth + 1) / (float) (depth + 2);
nodeToPoint.put(node, new Point2D.Float(x, y));
// Check the maximum width.
// max_width = Math.max(max_width, width[thisDepth]);
// Update the depth and width figures.
widthSofar[thisDepth++]++;
// Recurse on children.
TreeNode[] children = Trees.children(node);
for (int i = 0; i < children.length; i++)
setPoints(children[i], depth, thisDepth, width, widthSofar,
nodeToPoint);
}
}