/* * 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; } }