/*
* JBoss, Home of Professional Open Source
* Copyright 2005, JBoss Inc., and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.hibernate.eclipse.graph.layout;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.draw2d.AbsoluteBendpoint;
import org.eclipse.draw2d.Connection;
import org.eclipse.draw2d.Figure;
import org.eclipse.draw2d.PolylineConnection;
import org.eclipse.draw2d.geometry.Insets;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.draw2d.graph.DirectedGraph;
import org.eclipse.draw2d.graph.Edge;
import org.eclipse.draw2d.graph.Node;
import org.eclipse.draw2d.graph.NodeList;
import org.eclipse.gef.editparts.AbstractGraphicalEditPart;
import org.hibernate.eclipse.graph.parts.AssociationEditPart;
import org.hibernate.eclipse.graph.parts.ConfigurationEditPart;
import org.hibernate.eclipse.graph.parts.PersistentClassEditPart;
public class DirectedGraphLayoutVisitor
{
Map<AbstractGraphicalEditPart, Object> partToNodesMap;
Set<AssociationEditPart> addedAssociations;
DirectedGraph graph;
/**
* Public method for reading graph nodes
*/
public void layoutDiagram(ConfigurationEditPart diagram)
{
partToNodesMap = new HashMap<AbstractGraphicalEditPart, Object>();
addedAssociations = new HashSet<AssociationEditPart>();
graph = new DirectedGraph();
addNodes(diagram);
if (graph.nodes.size() > 0)
{
addEdges(diagram);
new NodeJoiningDirectedGraphLayout().visit(graph);
applyResults(diagram);
}
}
//******************* ConfigurationEditPart contribution methods **********/
protected void addNodes(ConfigurationEditPart diagram)
{
GraphAnimation.recordInitialState(diagram.getFigure());
for (int i = 0; i < diagram.getChildren().size(); i++)
{
PersistentClassEditPart tp = (PersistentClassEditPart) diagram.getChildren().get(i);
addNodes(tp);
}
}
/**
* Adds nodes to the graph object for use by the GraphLayoutManager
*/
@SuppressWarnings("unchecked")
protected void addNodes(PersistentClassEditPart pClassPart)
{
Node n = new Node(pClassPart);
n.width = pClassPart.getFigure().getPreferredSize(400, 300).width;
n.height = pClassPart.getFigure().getPreferredSize(400, 300).height;
n.setPadding(new Insets(50));
partToNodesMap.put(pClassPart, n);
graph.nodes.add(n);
}
protected void addEdges(ConfigurationEditPart diagram)
{
for (int i = 0; i < diagram.getChildren().size(); i++)
{
PersistentClassEditPart classPart = (PersistentClassEditPart) diagram.getChildren().get(i);
addEdges(classPart);
}
}
//******************* PersistentClassEditPart contribution methods **********/
@SuppressWarnings("unchecked")
protected void addEdges(PersistentClassEditPart classPart)
{
List<AssociationEditPart> outgoing = classPart.getSourceConnections();
for (AssociationEditPart relationshipPart : outgoing) {
addEdges(relationshipPart);
}
}
//******************* RelationshipPart contribution methods **********/
@SuppressWarnings("unchecked")
protected void addEdges(AssociationEditPart relationshipPart)
{
GraphAnimation.recordInitialState((Connection) relationshipPart.getFigure());
Node source = (Node) partToNodesMap.get(relationshipPart.getSource());
Node target = (Node) partToNodesMap.get(relationshipPart.getTarget());
if(source==target) {
/*if(addedAssociations.contains(relationshipPart)) {
System.out.println("Ignoring: " + relationshipPart);
return;
} else {
System.out.println("Adding: " + relationshipPart);
addedAssociations.add(relationshipPart);
} */
return;
}
if(source==null || target == null) {
return;
}
Edge e = new Edge(relationshipPart, source, target);
e.weight = 2;
graph.edges.add(e);
partToNodesMap.put(relationshipPart, e);
}
//******************* ConfigurationEditPart apply methods **********/
protected void applyResults(ConfigurationEditPart diagram)
{
applyChildrenResults(diagram);
}
protected void applyChildrenResults(ConfigurationEditPart diagram)
{
for (int i = 0; i < diagram.getChildren().size(); i++)
{
PersistentClassEditPart pClassPart = (PersistentClassEditPart) diagram.getChildren().get(i);
applyResults(pClassPart);
}
}
protected void applyOwnResults(ConfigurationEditPart diagram)
{
}
//******************* PersistentClassEditPart apply methods **********/
public void applyResults(PersistentClassEditPart pClassPart)
{
Node n = (Node) partToNodesMap.get(pClassPart);
Figure classFigure = (Figure) pClassPart.getFigure();
// switched x/y to make it go left to right
Rectangle bounds = new Rectangle(n.y, n.x, classFigure.getPreferredSize().width,
classFigure.getPreferredSize().height);
classFigure.setBounds(bounds);
for (int i = 0; i < pClassPart.getSourceConnections().size(); i++)
{
AssociationEditPart relationship = (AssociationEditPart) pClassPart.getSourceConnections().get(i);
applyResults(relationship);
}
}
//******************* RelationshipPart apply methods **********/
protected void applyResults(AssociationEditPart relationshipPart)
{
Edge e = (Edge) partToNodesMap.get(relationshipPart);
PolylineConnection conn = (PolylineConnection) relationshipPart.getConnectionFigure();
if (e==null) {
//conn.setConnectionRouter(new ShortestPathConnectionRouter(diagram.getFigure()));
return;
}
NodeList nodes = e.vNodes;
if (nodes != null)
{
List<AbsoluteBendpoint> bends = new ArrayList<AbsoluteBendpoint>();
for (int i = 0; i < nodes.size(); i++)
{
Node vn = nodes.getNode(i);
int x = vn.x;
int y = vn.y;
if (e.isFeedback())
{
bends.add(new AbsoluteBendpoint(x, y + vn.height));
bends.add(new AbsoluteBendpoint(x, y));
}
else
{
bends.add(new AbsoluteBendpoint(x, y));
bends.add(new AbsoluteBendpoint(x, y + vn.height));
}
}
conn.setRoutingConstraint(bends);
}
else
{
conn.setRoutingConstraint(Collections.EMPTY_LIST);
}
}
}