package de.unisiegen.tpml.graphics.tree;
import java.awt.Dimension;
import java.awt.Point;
import de.unisiegen.tpml.core.ProofNode;
/**
* Handles the layouting of a treebased GUI. The
* TypeChecker- and the BigStep-GUI are handled with this.
* @author marcell
*
*/
public class TreeNodeLayout {
/**
* Contains available width of the layout.
*/
private int availableWidth;
/**
* the singel pages will be filled to avoid deviding the singel nodes while printing
*/
private int actualPageCounter = 0;
/**
* The space between the the singel elements over the sides
*/
private int spaceUnderPage = 12;
/**
* Contains available height of one paper, is Integer.MaxValue if not printing...
*/
private int availableHeight;
/**
* The spacing between the nodes.
*/
private int spacing;
public TreeNodeLayout () {
this.spacing = 10;
}
public TreeNodeLayout (int spacing) {
this.spacing = spacing;
}
/**
* Sets the spacing
* @param spacing
*/
public void setSpacing (int spacing) {
this.spacing = spacing;
}
/**
* Returns the spacing
* @return
*/
public int getSpacing () {
return this.spacing;
}
/**
* Places the nodes.
*
* @param root The rootNode of the tree
* @param posX Left position where the root node should be placed
* @param posY Top position where the root node should be placed
* @param pAvailableWidth The maximum width available for the layout.
* @return
*/
public Point placeNodes (ProofNode root, int posX, int posY, int pAvailableWidth, int pAvailableHeight) {
this.availableWidth = pAvailableWidth;
this.availableHeight = pAvailableHeight;
actualPageCounter = 0;
return placeNode (root, posX, posY, new Point (-1, -1));
}
/**
* Calculates the size for a node and does the placing
* of the Component.
*
* @param node The node that should be
* @param posX The left position of the node
* @param posY The top position of the node
* @return The right bottom pos of the needed width
*/
private Point placeNode (ProofNode node, int posX, int posY, Point rightBottomPos)
{
TreeNodeComponent nodeComponent = (TreeNodeComponent)node.getUserObject();
if (nodeComponent == null) {
// this should not happen
return rightBottomPos;
}
// the available width is shrinked by the already spended
// space by indentating the node
int availableWidth = this.availableWidth - posX;
Dimension size = nodeComponent.update(availableWidth);
// add the needed height to the tmpPaper, if it gets bigger than availableHeight, pagebreak
if (this.actualPageCounter + this.spacing + size.height + this.spaceUnderPage > this.availableHeight)
{
{
// add the rest of space on the page to to posY... So the next node will get to next page
posY += this.availableHeight - this.actualPageCounter;
//posY += 10;
// the actualPageCounter restarts
this.actualPageCounter = 0;
}
}
// add the needed height to the actualPageCounter
this.actualPageCounter += size.height;
// do the real positioning of the node
nodeComponent.setBounds(posX, posY, size.width, size.height);
// let some spacing between two nodes
posY += this.spacing;
this.actualPageCounter += this.spacing;
//
// change the resulting point
//
// check if this node widens the resulting area
if (posX + size.width > rightBottomPos.x) {
rightBottomPos.x = posX + size.width;
}
// we will always go down so the new yPos is always bigger
rightBottomPos.y = posY + size.height;
posY += size.height;
posX += nodeComponent.getIndentationWidth();
// delegate the rest to the other nodes
for (int i=0; i<node.getChildCount(); i++)
{
ProofNode pNode = node.getChildAt(i);
placeNode (pNode, posX, posY, rightBottomPos);
// increment the posY for the next node
posY = rightBottomPos.y;
}
return rightBottomPos;
}
}