/*
* JBoss, Home of Professional Open Source.
*
* See the LEGAL.txt file distributed with this work for information regarding copyright ownership and licensing.
*
* See the AUTHORS.txt file distributed with this work for a full listing of individual contributors.
*/
package org.teiid.designer.diagram.ui.layout;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.teiid.designer.diagram.ui.model.DiagramModelNode;
/**
* LayoutGroup
* This class represents a group of layout nodes that are either totally connected or totally disconnected.
* This class will provide the hooks to identify the type of connections (if any) i.e. tree, circular links, etc..
*
* @since 8.0
*/
public class LayoutGroup implements LayoutNode {
private double thisX;
private double thisY;
private List layoutNodes;
private int type = LayoutHelper.NO_LINKS_LAYOUT;
private DiagramModelNode startingNode;
private int nConnections = 0;
/**
* Construct an instance of LayoutGroup.
*
*/
public LayoutGroup(List diagramNodes) {
super();
convertNodes(diagramNodes);
calculateType(diagramNodes);
}
public LayoutGroup(List diagramNodes, int layoutType) {
super();
convertNodes(diagramNodes);
}
/**
* @param diagramNodes
*/
public LayoutGroup(List diagramNodes, DiagramModelNode startingNode) {
super();
convertNodes(diagramNodes);
calculateType(diagramNodes);
this.startingNode = startingNode;
}
private void convertNodes(List diagramNodes) {
layoutNodes = new ArrayList(diagramNodes.size());
LayoutNode newLayoutNode = null;
Object nextNode = null;
Iterator iter = diagramNodes.iterator();
while( iter.hasNext() ) {
nextNode = iter.next();
if( nextNode instanceof DiagramModelNode ) {
newLayoutNode = new DefaultLayoutNode((DiagramModelNode)nextNode);
layoutNodes.add(newLayoutNode);
} else if( nextNode instanceof LayoutNode) {
layoutNodes.add(nextNode);
}
}
}
/**
* @return
*/
public List getLayoutNodes() {
return layoutNodes;
}
/**
* @return
*/
public int getType() {
return type;
}
/**
* @param i
*/
public void setType(int i) {
type = i;
}
private void calculateType(List diagramNodes) {
nConnections = LayoutUtilities.getConnectionCount(diagramNodes);
int nNodes = diagramNodes.size();
if( nConnections == (nNodes - 1) ) {
type = LayoutHelper.SIMPLE_LAYOUT;
} else {
type = LayoutHelper.COMPLEX_LAYOUT;
}
}
public void setFinalPositions() {
Iterator iter = layoutNodes.iterator();
LayoutNode nextLayoutNode = null;
while( iter.hasNext() ) {
nextLayoutNode = (LayoutNode)iter.next();
nextLayoutNode.setFinalPosition();
}
}
@Override
public void setPosition(Point point ) {
setX(point.x);
setY(point.y);
move(point.x, point.y);
// System.out.println(" -->> LayoutGroup.setPosition(): New XY Point = " + point);
}
@Override
public double getWidth() {
return getCurrentWidth();
}
@Override
public double getHeight() {
return getCurrentHeight();
}
public void move(double x, double y) {
// System.out.println(" -->> LayoutGroup.move() NEW X = " + x + " Y = " + y);
Iterator iter = layoutNodes.iterator();
LayoutNode nextLayoutNode = null;
while( iter.hasNext() ) {
nextLayoutNode = (LayoutNode)iter.next();
double newX = nextLayoutNode.getX() + x;
double newY = nextLayoutNode.getY() + y;
nextLayoutNode.setPosition(newX, newY);
}
}
public void layout() {
switch( type ) {
case LayoutHelper.COMPLEX_LAYOUT: {
int numNodes = this.getLayoutNodes().size();
int nConn = nConnections;
double connRatio = (double)nConn/(double)numNodes;
if( numNodes > 400 && connRatio > 1.2 ) {
LayoutUtilities.runColumnLayout(this);
} else {
LayoutUtilities.runSpringLayout(this);
}
setBounds(new Rectangle(0, 0, getCurrentWidth(), getCurrentHeight()));
} break;
case LayoutHelper.SIMPLE_LAYOUT: {
if( startingNode == null )
LayoutUtilities.runTreeLayout(this);
else {
LayoutNode startNode = getLayoutNode(startingNode);
LayoutUtilities.runTreeLayout(this, startNode);
}
setBounds(new Rectangle(0, 0, getCurrentWidth(), getCurrentHeight()));
} break;
case LayoutHelper.NO_LINKS_LAYOUT: {
LayoutUtilities.runColumnLayout(this);
setBounds(new Rectangle(0, 0, getCurrentWidth(), getCurrentHeight()));
}
}
// System.out.println(" -->> LayoutGroup.layout()");
}
public int getCurrentWidth() {
if( layoutNodes == null || layoutNodes.isEmpty()) {
return 1;
}
// Walk through springNodes and get the total width
double currentWidth = 0;
double minW = 999999.;
double maxW = -999999.;
double nextXPlusW = 0;
Iterator iter = layoutNodes.iterator();
LayoutNode nextNode;
while( iter.hasNext() ) {
nextNode = (LayoutNode)iter.next();
minW = Math.min(minW, nextNode.getX());
nextXPlusW = nextNode.getX() + nextNode.getWidth();
maxW = Math.max(maxW, nextXPlusW);
}
currentWidth = maxW - minW;
return (int)currentWidth;
}
public int getCurrentHeight() {
if( layoutNodes == null || layoutNodes.isEmpty()) {
return 1;
}
// Walk through springNodes and get the total width
double currentHeight = 0;
double minH = 999999.;
double maxH = -999999.;
double nextYPlusH = 0;
Iterator iter = layoutNodes.iterator();
LayoutNode nextNode;
while( iter.hasNext() ) {
nextNode = (LayoutNode)iter.next();
minH = Math.min(minH, nextNode.getY());
nextYPlusH = nextNode.getY() + nextNode.getHeight();
maxH = Math.max(maxH, nextYPlusH);
}
currentHeight = maxH - minH;
return (int)currentHeight;
}
/* (non-Javadoc)
* @See org.teiid.designer.diagram.ui.layout.LayoutNode#getBounds()
*/
@Override
public Rectangle getBounds() {
return null;
}
/* (non-Javadoc)
* @See org.teiid.designer.diagram.ui.layout.LayoutNode#getCenterX()
*/
@Override
public double getCenterX() {
return 0;
}
/* (non-Javadoc)
* @See org.teiid.designer.diagram.ui.layout.LayoutNode#getCenterY()
*/
@Override
public double getCenterY() {
return 0;
}
/* (non-Javadoc)
* @See org.teiid.designer.diagram.ui.layout.LayoutNode#getModelNode()
*/
@Override
public DiagramModelNode getModelNode() {
return null;
}
/* (non-Javadoc)
* @See org.teiid.designer.diagram.ui.layout.LayoutNode#getPosition()
*/
@Override
public org.eclipse.draw2d.geometry.Point getPosition() {
return null;
}
/* (non-Javadoc)
* @See org.teiid.designer.diagram.ui.layout.LayoutNode#getX()
*/
@Override
public double getX() {
return thisX;
}
/* (non-Javadoc)
* @See org.teiid.designer.diagram.ui.layout.LayoutNode#getY()
*/
@Override
public double getY() {
return thisY;
}
/* (non-Javadoc)
* @See org.teiid.designer.diagram.ui.layout.LayoutNode#setBounds(java.awt.Rectangle)
*/
@Override
public void setBounds(Rectangle rectangle) {
}
/* (non-Javadoc)
* @See org.teiid.designer.diagram.ui.layout.LayoutNode#setCenterX(double)
*/
@Override
public void setCenterX(double x) {
}
/* (non-Javadoc)
* @See org.teiid.designer.diagram.ui.layout.LayoutNode#setCenterXY(double, double)
*/
@Override
public void setCenterXY(double x, double y) {
}
/* (non-Javadoc)
* @See org.teiid.designer.diagram.ui.layout.LayoutNode#setCenterY(double)
*/
@Override
public void setCenterY(double y) {
}
/* (non-Javadoc)
* @See org.teiid.designer.diagram.ui.layout.LayoutNode#setFinalPosition()
*/
@Override
public void setFinalPosition() {
}
/* (non-Javadoc)
* @See org.teiid.designer.diagram.ui.layout.LayoutNode#setPosition(double, double)
*/
@Override
public void setPosition(double x, double y) {
setX(x);
setY(y);
move(x, y);
}
/* (non-Javadoc)
* @See org.teiid.designer.diagram.ui.layout.LayoutNode#setX(double)
*/
@Override
public void setX(double x) {
thisX = x;
}
/* (non-Javadoc)
* @See org.teiid.designer.diagram.ui.layout.LayoutNode#setY(double)
*/
@Override
public void setY(double y) {
thisY = y;
}
public LayoutNode getLayoutNode(Object someObject) {
if( someObject != null && someObject instanceof DiagramModelNode ) {
// Walk through layout nodes and return the one that contains a modelObject matching someObject
Iterator iter = getLayoutNodes().iterator();
LayoutNode nextLN = null;
while( iter.hasNext() ) {
nextLN = (LayoutNode)iter.next();
if( nextLN.getModelNode() != null &&
nextLN.getModelNode().equals(someObject))
return nextLN;
}
}
return null;
}
}