Top Description Inners Fields Constructors Methods
org.abego.treelayout

public Class TreeLayout<TreeNode>

extends Object
Class Inheritance
Type Parameters
<TreeNode>
Type of elements used as nodes in the tree
Static Imports
org.abego.treelayout.internal.util.Contract.checkArg

Implements the actual tree layout algorithm.

The nodes with their final layout can be retrieved through getNodeBounds().

See this summary to get an overview how to use TreeLayout.
Author
Udo Borkowski ([email protected])

Nested and Inner Type Summary

Modifier and TypeClass and Description
public static class
private class
TreeLayout.NormalizedPosition

The algorithm calculates the position starting with the root at 0.

Field Summary

Modifier and TypeField and Description
private final Map<TreeNode, TreeNode>
private double
private double
private double
private double
private final Map<TreeNode, Double>
private final Configuration<TreeNode>
private final Map<TreeNode, Double>
private Map<TreeNode, Rectangle2D.Double>
private final NodeExtentProvider<TreeNode>
private final Map<TreeNode, Integer>
private final Map<TreeNode, Point2D>
private final Map<TreeNode, Double>
private final Map<TreeNode, Double>
private final List<Double>
private final Map<TreeNode, TreeNode>
private final TreeForTreeLayout<TreeNode>
private final boolean

Constructor Summary

AccessConstructor and Description
public
TreeLayout(TreeForTreeLayout<TreeNode>
 
tree
,
NodeExtentProvider<TreeNode>
 
nodeExtentProvider
,
Configuration<TreeNode>
 
configuration
,
boolean
[default: false] when true, identity ("==") is used instead of equality ("equals(...)") when checking nodes. Within a tree each node must only exist once (using this check).
useIdentity
)

Creates a TreeLayout for a given tree.

public
TreeLayout(TreeForTreeLayout<TreeNode> tree, NodeExtentProvider<TreeNode> nodeExtentProvider, Configuration<TreeNode> configuration)

Method Summary

Modifier and TypeMethod and Description
private void
addUniqueNodes(Map<TreeNode, TreeNode> nodes, TreeNode newNode)

private TreeNode

Returns:

the greatest distinct ancestor of vIMinus and its right neighbor v
ancestor
(TreeNode vIMinus, TreeNode v, TreeNode parentOfV, TreeNode defaultAncestor)

private TreeNode

Returns:

the (possibly changes) defaultAncestor
apportion
(TreeNode v, TreeNode defaultAncestor, TreeNode
[nullable] the left sibling v, if there is any
leftSibling
,
TreeNode
the parent of v
parentOfV
)

In difference to the original algorithm we also pass in the leftSibling and the parent of v.

Why adding the parameter 'parent of v' (parentOfV) ?

private void
calcSizeOfLevels(TreeNode node, int level)

public void
checkTree()

Check if the tree is a "valid" tree.

private void
dumpTree(PrintStream output, TreeNode node, int indent, TreeLayout.DumpConfiguration dumpConfiguration)

public void
dumpTree(PrintStream
 
printStream
,
TreeLayout.DumpConfiguration
[default: new DumpConfiguration()]
dumpConfiguration
)

Prints a dump of the tree to the given printStream, using the node's "toString" method.

public void
dumpTree(PrintStream printStream)

private void
executeShifts(TreeNode
[!tree.isLeaf(v)]
v
)

private void
firstWalk(TreeNode v, TreeNode
[nullable] the left sibling v, if there is any
leftSibling
)

In difference to the original algorithm we also pass in the leftSibling (see apportion(Object, Object, Object, Object) for a motivation).

private TreeNode
getAncestor(TreeNode node)

public Rectangle2D

Returns:

the bounds of the tree layout
getBounds
()

Returns the bounds of the tree layout.

private double
getChange(TreeNode node)

public Configuration<TreeNode>

Returns:

the Configuration used by this TreeLayout
getConfiguration
()

Returns the Configuration used by this TreeLayout.

private double

Returns:

the distance between node v and w
getDistance
(TreeNode v, TreeNode w)

The distance of two nodes is the distance of the centers of both noded.

private int
public int

Returns:

[level > 0]
getLevelCount
()

Returns the number of levels of the tree.

private double
getMod(TreeNode node)

public Map<TreeNode, Rectangle2D.Double>

Returns:

maps each node of the tree to its bounds (position and size).
getNodeBounds
()

Returns the layout of the tree nodes by mapping each node of the tree to its bounds (position and size).

public NodeExtentProvider<TreeNode>

Returns:

the NodeExtentProvider used by this TreeLayout
getNodeExtentProvider
()

Returns the NodeExtentProvider used by this TreeLayout.

private double
getNodeHeight(TreeNode node)

private double
getNodeSize(TreeNode treeNode)

When the level changes in Y-axis (i.e. root location Top or Bottom) the width of a node is its size, otherwise the node's height is its size.

private double
getNodeThickness(TreeNode treeNode)

When the level changes in Y-axis (i.e. root location Top or Bottom) the height of a node is its thickness, otherwise the node's width is its thickness.

private double
getNodeWidth(TreeNode node)

private int
getNumber(TreeNode
[tree.isChildOfParent(node, parentNode)]
node
,
TreeNode
parent of node
parentNode
)

private double
getPrelim(TreeNode node)

private double
getShift(TreeNode node)

public double

Returns:

the size of the level [level >= 0 && level < levelCount]
getSizeOfLevel
(int
 
level
)

Returns the size of a level.

private TreeNode
getThread(TreeNode node)

public TreeForTreeLayout<TreeNode>

Returns:

the Tree the layout is created for
getTree
()

Returns the Tree the layout is created for.

private double
getWidthOrHeightOfNode(TreeNode treeNode, boolean returnWidth)

private boolean
private void
moveSubtree(TreeNode wMinus, TreeNode wPlus, TreeNode parent, double shift)

private TreeNode
nextLeft(TreeNode v)

private TreeNode
nextRight(TreeNode v)

private void
secondWalk(TreeNode v, double m, int level, double levelStart)

In difference to the original algorithm we also pass in extra level information.

private void
setAncestor(TreeNode node, TreeNode ancestor)

private void
setChange(TreeNode node, double d)

private void
setMod(TreeNode node, double d)

private void
setPrelim(TreeNode node, double d)

private void
setShift(TreeNode node, double d)

private void
setThread(TreeNode node, TreeNode thread)

private void
updateBounds(TreeNode node, double centerX, double centerY)

Inherited from java.lang.Object:
cloneequalsfinalizegetClasshashCodenotifynotifyAlltoStringwaitwaitwait

Field Detail

ancestorback to summary
private final Map<TreeNode, TreeNode> ancestor
boundsBottomback to summary
private double boundsBottom
boundsLeftback to summary
private double boundsLeft
boundsRightback to summary
private double boundsRight
boundsTopback to summary
private double boundsTop
changeback to summary
private final Map<TreeNode, Double> change
configurationback to summary
private final Configuration<TreeNode> configuration
modback to summary
private final Map<TreeNode, Double> mod
nodeBoundsback to summary
private Map<TreeNode, Rectangle2D.Double> nodeBounds
nodeExtentProviderback to summary
private final NodeExtentProvider<TreeNode> nodeExtentProvider
numberback to summary
private final Map<TreeNode, Integer> number
positionsback to summary
private final Map<TreeNode, Point2D> positions
prelimback to summary
private final Map<TreeNode, Double> prelim
shiftback to summary
private final Map<TreeNode, Double> shift
sizeOfLevelback to summary
private final List<Double> sizeOfLevel
threadback to summary
private final Map<TreeNode, TreeNode> thread
treeback to summary
private final TreeForTreeLayout<TreeNode> tree
useIdentityback to summary
private final boolean useIdentity

Constructor Detail

TreeLayoutback to summary
public TreeLayout(TreeForTreeLayout<TreeNode> tree, NodeExtentProvider<TreeNode> nodeExtentProvider, Configuration<TreeNode> configuration, boolean useIdentity)

Creates a TreeLayout for a given tree.

In addition to the tree the NodeExtentProvider and the Configuration must be given.

Parameters
tree:TreeForTreeLayout<TreeNode>

 

nodeExtentProvider:NodeExtentProvider<TreeNode>

 

configuration:Configuration<TreeNode>

 

useIdentity:boolean

[default: false] when true, identity ("==") is used instead of equality ("equals(...)") when checking nodes. Within a tree each node must only exist once (using this check).

TreeLayoutback to summary
public TreeLayout(TreeForTreeLayout<TreeNode> tree, NodeExtentProvider<TreeNode> nodeExtentProvider, Configuration<TreeNode> configuration)

Method Detail

addUniqueNodesback to summary
private void addUniqueNodes(Map<TreeNode, TreeNode> nodes, TreeNode newNode)
ancestorback to summary
private TreeNode ancestor(TreeNode vIMinus, TreeNode v, TreeNode parentOfV, TreeNode defaultAncestor)
Returns:TreeNode

the greatest distinct ancestor of vIMinus and its right neighbor v

apportionback to summary
private TreeNode apportion(TreeNode v, TreeNode defaultAncestor, TreeNode leftSibling, TreeNode parentOfV)

In difference to the original algorithm we also pass in the leftSibling and the parent of v.

Why adding the parameter 'parent of v' (parentOfV) ?

In this method we need access to the parent of v. Not every tree implementation may support efficient (i.e. constant time) access to it. On the other hand the (only) caller of this method can provide this information with only constant extra time.

Also we need access to the "left most sibling" of v. Not every tree implementation may support efficient (i.e. constant time) access to it. On the other hand the "left most sibling" of v is also the "first child" of the parent of v. The first child of a parent node we can get in constant time. As we got the parent of v we can so also get the "left most sibling" of v in constant time.

Why adding the parameter 'leftSibling' ?

In this method we need access to the "left sibling" of v. Not every tree implementation may support efficient (i.e. constant time) access to it. However it is easy for the caller of this method to provide this information with only constant extra time.

In addition these extra parameters avoid the need for TreeForTreeLayout to include extra methods "getParent", "getLeftSibling", or "getLeftMostSibling". This keeps the interface TreeForTreeLayout small and avoids redundant implementations.

Parameters
leftSibling:TreeNode

[nullable] the left sibling v, if there is any

parentOfV:TreeNode

the parent of v

Returns:TreeNode

the (possibly changes) defaultAncestor

calcSizeOfLevelsback to summary
private void calcSizeOfLevels(TreeNode node, int level)
checkTreeback to summary
public void checkTree()

Check if the tree is a "valid" tree.

Typically you will use this method during development when you get an unexpected layout from your trees.

The following checks are performed:

  • Each node must only occur once in the tree.
dumpTreeback to summary
private void dumpTree(PrintStream output, TreeNode node, int indent, TreeLayout.DumpConfiguration dumpConfiguration)
dumpTreeback to summary
public void dumpTree(PrintStream printStream, TreeLayout.DumpConfiguration dumpConfiguration)

Prints a dump of the tree to the given printStream, using the node's "toString" method.

Parameters
printStream:PrintStream

 

dumpConfiguration:TreeLayout.DumpConfiguration

[default: new DumpConfiguration()]

dumpTreeback to summary
public void dumpTree(PrintStream printStream)
executeShiftsback to summary
private void executeShifts(TreeNode v)
Parameters
v:TreeNode

[!tree.isLeaf(v)]

firstWalkback to summary
private void firstWalk(TreeNode v, TreeNode leftSibling)

In difference to the original algorithm we also pass in the leftSibling (see apportion(Object, Object, Object, Object) for a motivation).

Parameters
leftSibling:TreeNode

[nullable] the left sibling v, if there is any

getAncestorback to summary
private TreeNode getAncestor(TreeNode node)
getBoundsback to summary
public Rectangle2D getBounds()

Returns the bounds of the tree layout.

The bounds of a TreeLayout is the smallest rectangle containing the bounds of all nodes in the layout. It always starts at (0,0).

Returns:Rectangle2D

the bounds of the tree layout

getChangeback to summary
private double getChange(TreeNode node)
getConfigurationback to summary
public Configuration<TreeNode> getConfiguration()

Returns the Configuration used by this TreeLayout.

Returns:Configuration<TreeNode>

the Configuration used by this TreeLayout

getDistanceback to summary
private double getDistance(TreeNode v, TreeNode w)

The distance of two nodes is the distance of the centers of both noded.

I.e. the distance includes the gap between the nodes and half of the sizes of the nodes.

Returns:double

the distance between node v and w

getLevelChangeSignback to summary
private int getLevelChangeSign()
getLevelCountback to summary
public int getLevelCount()

Returns the number of levels of the tree.

Returns:int

[level > 0]

getModback to summary
private double getMod(TreeNode node)
getNodeBoundsback to summary
public Map<TreeNode, Rectangle2D.Double> getNodeBounds()

Returns the layout of the tree nodes by mapping each node of the tree to its bounds (position and size).

For each rectangle x and y will be >= 0. At least one rectangle will have an x == 0 and at least one rectangle will have an y == 0.

Returns:Map<TreeNode, Rectangle2D.Double>

maps each node of the tree to its bounds (position and size).

getNodeExtentProviderback to summary
public NodeExtentProvider<TreeNode> getNodeExtentProvider()

Returns the NodeExtentProvider used by this TreeLayout.

Returns:NodeExtentProvider<TreeNode>

the NodeExtentProvider used by this TreeLayout

getNodeHeightback to summary
private double getNodeHeight(TreeNode node)
getNodeSizeback to summary
private double getNodeSize(TreeNode treeNode)

When the level changes in Y-axis (i.e. root location Top or Bottom) the width of a node is its size, otherwise the node's height is its size.

The size of a node is used when calculating the distance between two nodes.

getNodeThicknessback to summary
private double getNodeThickness(TreeNode treeNode)

When the level changes in Y-axis (i.e. root location Top or Bottom) the height of a node is its thickness, otherwise the node's width is its thickness.

The thickness of a node is used when calculating the locations of the levels.

getNodeWidthback to summary
private double getNodeWidth(TreeNode node)
getNumberback to summary
private int getNumber(TreeNode node, TreeNode parentNode)
Parameters
node:TreeNode

[tree.isChildOfParent(node, parentNode)]

parentNode:TreeNode

parent of node

getPrelimback to summary
private double getPrelim(TreeNode node)
getShiftback to summary
private double getShift(TreeNode node)
getSizeOfLevelback to summary
public double getSizeOfLevel(int level)

Returns the size of a level.

When the root is located at the top or bottom the size of a level is the maximal height of the nodes of that level. When the root is located at the left or right the size of a level is the maximal width of the nodes of that level.

Parameters
level:int

 

Returns:double

the size of the level [level >= 0 && level < levelCount]

getThreadback to summary
private TreeNode getThread(TreeNode node)
getTreeback to summary
public TreeForTreeLayout<TreeNode> getTree()

Returns the Tree the layout is created for.

Returns:TreeForTreeLayout<TreeNode>

the Tree the layout is created for

getWidthOrHeightOfNodeback to summary
private double getWidthOrHeightOfNode(TreeNode treeNode, boolean returnWidth)
isLevelChangeInYAxisback to summary
private boolean isLevelChangeInYAxis()
moveSubtreeback to summary
private void moveSubtree(TreeNode wMinus, TreeNode wPlus, TreeNode parent, double shift)
nextLeftback to summary
private TreeNode nextLeft(TreeNode v)
nextRightback to summary
private TreeNode nextRight(TreeNode v)
secondWalkback to summary
private void secondWalk(TreeNode v, double m, int level, double levelStart)

In difference to the original algorithm we also pass in extra level information.

setAncestorback to summary
private void setAncestor(TreeNode node, TreeNode ancestor)
setChangeback to summary
private void setChange(TreeNode node, double d)
setModback to summary
private void setMod(TreeNode node, double d)
setPrelimback to summary
private void setPrelim(TreeNode node, double d)
setShiftback to summary
private void setShift(TreeNode node, double d)
setThreadback to summary
private void setThread(TreeNode node, TreeNode thread)
updateBoundsback to summary
private void updateBounds(TreeNode node, double centerX, double centerY)
org.abego.treelayout back to summary

public Class TreeLayout.DumpConfiguration

extends Object
Class Inheritance

Field Summary

Modifier and TypeField and Description
public final boolean
includeNodeSize

When true the dump also includes the size of each node, otherwise not.

public final boolean
includeObjectToString

When true, the text as returned by Object#toString(), is included in the dump, in addition to the text returned by the possibly overridden toString method of the node.

public final String
indent

The text used to indent the output per level.

Constructor Summary

AccessConstructor and Description
public
DumpConfiguration(String
[default: " "]
indent
,
boolean
[default: false]
includeNodeSize
,
boolean
[default: false]
includePointer
)

public

Method Summary

Inherited from java.lang.Object:
cloneequalsfinalizegetClasshashCodenotifynotifyAlltoStringwaitwaitwait

Field Detail

includeNodeSizeback to summary
public final boolean includeNodeSize

When true the dump also includes the size of each node, otherwise not.

includeObjectToStringback to summary
public final boolean includeObjectToString

When true, the text as returned by Object#toString(), is included in the dump, in addition to the text returned by the possibly overridden toString method of the node. When the hashCode method is overridden the output will also include the "identityHashCode".

indentback to summary
public final String indent

The text used to indent the output per level.

Constructor Detail

DumpConfigurationback to summary
public DumpConfiguration(String indent, boolean includeNodeSize, boolean includePointer)
Parameters
indent:String

[default: " "]

includeNodeSize:boolean

[default: false]

includePointer:boolean

[default: false]

DumpConfigurationback to summary
public DumpConfiguration()
org.abego.treelayout back to summary

private Class TreeLayout.NormalizedPosition

extends Point2D
Class Inheritance

The algorithm calculates the position starting with the root at 0. I.e. the left children will get negative positions. However we want the result to be normalized to (0,0).

NormalizedPosition will normalize the position (given relative to the root position), taking the current bounds into account. This way the left most node bounds will start at x = 0, the top most node bounds at y = 0.

Field Summary

Modifier and TypeField and Description
private double
private double

Constructor Summary

AccessConstructor and Description
public
NormalizedPosition(double x_relativeToRoot, double y_relativeToRoot)

Method Summary

Modifier and TypeMethod and Description
public double
getX()

Implements abstract java.awt.geom.Point2D.getX.

Returns the X coordinate of this Point2D in double precision.
public double
getY()

Implements abstract java.awt.geom.Point2D.getY.

Returns the Y coordinate of this Point2D in double precision.
public void
setLocation(double
the new X coordinate of this Point2D
x_relativeToRoot
,
double
the new Y coordinate of this Point2D
y_relativeToRoot
)

Implements abstract java.awt.geom.Point2D.setLocation.

Sets the location of this Point2D to the specified double coordinates.
Inherited from java.awt.geom.Point2D:
clonedistancedistancedistancedistanceSqdistanceSqdistanceSqequalshashCodesetLocation

Field Detail

x_relativeToRootback to summary
private double x_relativeToRoot
y_relativeToRootback to summary
private double y_relativeToRoot

Constructor Detail

NormalizedPositionback to summary
public NormalizedPosition(double x_relativeToRoot, double y_relativeToRoot)

Method Detail

getXback to summary
public double getX()

Implements abstract java.awt.geom.Point2D.getX.

Doc from java.awt.geom.Point2D.getX.

Returns the X coordinate of this Point2D in double precision.

Returns:double

the X coordinate of this Point2D.

Annotations
@Override
getYback to summary
public double getY()

Implements abstract java.awt.geom.Point2D.getY.

Doc from java.awt.geom.Point2D.getY.

Returns the Y coordinate of this Point2D in double precision.

Returns:double

the Y coordinate of this Point2D.

Annotations
@Override
setLocationback to summary
public void setLocation(double x_relativeToRoot, double y_relativeToRoot)

Implements abstract java.awt.geom.Point2D.setLocation.

Doc from java.awt.geom.Point2D.setLocation.

Sets the location of this Point2D to the specified double coordinates.

Parameters
x_relativeToRoot:double

the new X coordinate of this Point2D

y_relativeToRoot:double

the new Y coordinate of this Point2D

Annotations
@Override