/**
*
*/
package agg.layout;
import java.awt.Dimension;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.List;
import java.util.Vector;
import org.eclipse.zest.layouts.InvalidLayoutConfiguration;
import org.eclipse.zest.layouts.LayoutAlgorithm;
import org.eclipse.zest.layouts.LayoutEntity;
import org.eclipse.zest.layouts.LayoutRelationship;
import org.eclipse.zest.layouts.LayoutStyles;
import org.eclipse.zest.layouts.algorithms.GridLayoutAlgorithm;
import org.eclipse.zest.layouts.algorithms.HorizontalLayoutAlgorithm;
import org.eclipse.zest.layouts.algorithms.HorizontalTreeLayoutAlgorithm;
import org.eclipse.zest.layouts.algorithms.RadialLayoutAlgorithm;
import org.eclipse.zest.layouts.algorithms.SpringLayoutAlgorithm;
import org.eclipse.zest.layouts.algorithms.TreeLayoutAlgorithm;
import org.eclipse.zest.layouts.algorithms.VerticalLayoutAlgorithm;
import org.eclipse.zest.layouts.exampleStructures.SimpleGraph;
//import org.eclipse.zest.layouts.progress.ProgressEvent;
//import org.eclipse.zest.layouts.progress.ProgressListener;
import agg.editor.impl.EdArc;
import agg.editor.impl.EdGraph;
import agg.editor.impl.EdNode;
/**
* @author olga
*
*/
public class ZestGraphLayout
{
// TODO: user setting for
// dimension,
// GridLayoutAlgorithm.RowPadding,
// SpringLayoutAlgorithm.SpringGravitation, SpringMove, SpringStrain, SpringLength
EdGraph edgraph;
Dimension dimension;
Hashtable<EdNode, LayoutEntity> ednode2node = new Hashtable<EdNode, LayoutEntity>();
Hashtable<EdArc, LayoutRelationship> edarc2arc = new Hashtable<EdArc, LayoutRelationship>();
List<EdNode> ednodes = new Vector<EdNode>();
List<EdArc> edarcs = new Vector<EdArc>();
Dimension averNodeSize = new Dimension(500, 500);
SimpleGraph simplegraph;
LayoutAlgorithm algorithm;
String algorithmName;
Hashtable<String, LayoutAlgorithm> name2algorithm;
/**
* the algorithms ZEST provide
*/
private static final ArrayList<LayoutAlgorithm> algorithms = new ArrayList<LayoutAlgorithm>();
static {
algorithms.add(new SpringLayoutAlgorithm(
LayoutStyles.NO_LAYOUT_NODE_RESIZING));
algorithms.add(new TreeLayoutAlgorithm(
LayoutStyles.NO_LAYOUT_NODE_RESIZING));
algorithms.add(new HorizontalTreeLayoutAlgorithm(
LayoutStyles.NO_LAYOUT_NODE_RESIZING));
algorithms.add(new RadialLayoutAlgorithm(
LayoutStyles.NO_LAYOUT_NODE_RESIZING));
algorithms.add(new GridLayoutAlgorithm(
LayoutStyles.NO_LAYOUT_NODE_RESIZING));
algorithms.add(new HorizontalLayoutAlgorithm(
LayoutStyles.NO_LAYOUT_NODE_RESIZING));
algorithms.add(new VerticalLayoutAlgorithm(
LayoutStyles.NO_LAYOUT_NODE_RESIZING));
}
public static final ArrayList<String> algorithmNames = new ArrayList<String>();
static {
algorithmNames.add("Spring");
algorithmNames.add("Tree (vertical)");
algorithmNames.add("Tree (horizontal)");
algorithmNames.add("Radial");
algorithmNames.add("Grid");
algorithmNames.add("Horizontal");
algorithmNames.add("Vertical");
}
public ZestGraphLayout() {
this.name2algorithm = new Hashtable<String, LayoutAlgorithm>();
for (int i=0; i<algorithmNames.size(); i++) {
this.name2algorithm.put(algorithmNames.get(i), algorithms.get(i));
}
}
public ZestGraphLayout(final EdGraph graph) {
this();
this.edgraph = graph;
}
public ZestGraphLayout(final EdGraph graph, final String algorithmname) {
this();
this.edgraph = graph;
this.setAlgorithm(algorithmname);
}
public void start() {
applyLayout();
}
public void setGraph(final EdGraph graph) {
this.edgraph = graph;
}
public void setGraphDimension(final Dimension dim) {
this.dimension = dim;
}
@SuppressWarnings("rawtypes")
public void setAlgorithm(final String algorithmName) {
this.algorithmName = algorithmName;
this.algorithm = this.name2algorithm.get(algorithmName);
// this.algorithm.setEntityAspectRatio(4/3);
if (this.algorithm instanceof SpringLayoutAlgorithm) {
((SpringLayoutAlgorithm) this.algorithm).setIterations(1000); // default
((SpringLayoutAlgorithm) this.algorithm).setRandom(true); // default
((SpringLayoutAlgorithm) this.algorithm).setSpringGravitation(0.0001d); // default 1.0
// ((SpringLayoutAlgorithm) this.algorithm).setSpringStrain(0.0001d); // default 1.0
// ((SpringLayoutAlgorithm) this.algorithm).setSpringMove(0.001d); // default 1.0
}
else if (this.algorithm instanceof TreeLayoutAlgorithm) {
((TreeLayoutAlgorithm) this.algorithm).setComparator(new Comparator() {
@SuppressWarnings("unchecked")
public int compare(Object o1, Object o2) {
if (o1 instanceof Comparable && o2 instanceof Comparable) {
return ((Comparable) o1).compareTo(o2);
}
return 0;
}
});
}
else if (this.algorithm instanceof GridLayoutAlgorithm) {
((GridLayoutAlgorithm) this.algorithm).setRowPadding(20);
}
}
public boolean applyLayout() {
if (this.edgraph == null)
return false;
setGraphLayoutData();
// extract graph entities and relationships
final List<?> entitiesList = this.simplegraph.getEntities();
final LayoutEntity[] entities = new LayoutEntity[entitiesList.size()];
entitiesList.toArray(entities);
final List<?> relationshipList = this.simplegraph.getRelationships();
final LayoutRelationship[] relationships = new LayoutRelationship[relationshipList.size()];
relationshipList.toArray(relationships);
try {
// long time1 = System.currentTimeMillis();
// System.out.println("*** Zest "+this.algorithmName+" layout running ...");
this.algorithm.applyLayout(entities, relationships, 15.0, 15.0,
this.dimension.width, this.dimension.height,
false, false);
// System.out.println("*** Zest "+this.algorithmName+" layout done in "
// +(System.currentTimeMillis()-time1)+"ms");
} catch (InvalidLayoutConfiguration e) {
System.out.println(e.getLocalizedMessage());
return false;
}
convertFromSimpleGraph();
unsetGraphLayoutData();
return true;
}
private void setGraphLayoutData() {
this.simplegraph = new SimpleGraph();
this.ednodes.clear();
this.edarcs.clear();
this.ednodes.addAll(this.edgraph.getVisibleNodes());
this.edarcs.addAll(this.edgraph.getArcs());
// final List<EdArc> connections = new Vector<EdArc>();
for (int i=0; i<this.ednodes.size(); i++) {
EdNode ednode = this.ednodes.get(i);
final LayoutEntity node = this.simplegraph.addObjectNode(ednode);
node.setLocationInLayout(ednode.getX(), ednode.getY());
node.setSizeInLayout(ednode.getWidth(), ednode.getHeight());
this.ednode2node.put(ednode, node);
}
for (int i=0; i<this.edarcs.size(); i++) {
EdArc edarc = this.edarcs.get(i);
EdNode src = (EdNode)edarc.getSource();
EdNode tar = (EdNode)edarc.getTarget();
if (this.ednodes.contains(src) && this.ednodes.contains(tar)) {
this.simplegraph.addObjectRelationship(src, tar, false, 1);
// connections.add(edarc);
}
}
// if (this.dimension == null)
{
this.averNodeSize.setSize(this.edgraph.getAverageNodeDim(this.ednodes));
this.dimension = getNeededPanelSize(this.averNodeSize, this.ednodes.size(), this.algorithm);
}
}
private void unsetGraphLayoutData() {
this.simplegraph = null;
this.ednodes.clear();
this.edarcs.clear();
this.ednode2node.clear();
this.dimension = null;
}
protected Dimension getNeededPanelSize(
final Dimension averagenodesize,
int count,
final LayoutAlgorithm algorith) {
if (averagenodesize.width < 25 || averagenodesize.height < 25) {
averagenodesize.width = 25;
averagenodesize.height = 25;
}
final int ans = (averagenodesize.width >= averagenodesize.height) ? averagenodesize.width : averagenodesize.height;
// int sizetmp = 2 * (int)Math.sqrt(count);
int sizeX = ans * count/2; //sizetmp;
if (sizeX > 500 && sizeX < 1000)
sizeX = 1000;
int sizeY = sizeX*3/4;
// if (this.algorithm instanceof SpringLayoutAlgorithm) {
// }
// else
// if (this.algorithm instanceof TreeLayoutAlgorithm) {
// } else
// if (this.algorithm instanceof HorizontalTreeLayoutAlgorithm) {
// }
// else
// if (this.algorithm instanceof RadialLayoutAlgorithm) {
// }
// else
// if (this.algorithm instanceof GridLayoutAlgorithm) {
// }
// else
if (this.algorithm instanceof HorizontalLayoutAlgorithm) {
sizeX = (ans +20) * count;
sizeY = 400;
}
else
if (this.algorithm instanceof VerticalLayoutAlgorithm) {
sizeX = 400;
sizeY = (ans +20) * count;
}
final Dimension dim = new Dimension(sizeX, sizeY);
// wenn zu kleine panel
if (dim.width < 400 || dim.height < 400) {
dim.width = 400;
dim.height = 400;
}
// System.out.println(dim.width+" "+dim.height);
return dim;
}
protected void convertFromSimpleGraph() {
if (this.edgraph != null) {
Enumeration<EdNode> list = this.ednode2node.keys();
while (list.hasMoreElements()) {
EdNode ednode = list.nextElement();
LayoutEntity n = this.ednode2node.get(ednode);
ednode.setX((int)n.getXInLayout());
ednode.setY((int)n.getYInLayout());
}
this.edgraph.straightAllArcs();
}
}
/* (non-Javadoc)
* @see org.eclipse.zest.layouts.progress.ProgressListener#progressEnded(org.eclipse.zest.layouts.progress.ProgressEvent)
*/
// public void progressEnded(ProgressEvent arg0) {
// System.out.println("progressEnded "+arg0.getTotalNumberOfSteps()+" "+arg0.getStepsCompleted());
//
// }
/* (non-Javadoc)
* @see org.eclipse.zest.layouts.progress.ProgressListener#progressStarted(org.eclipse.zest.layouts.progress.ProgressEvent)
*/
// public void progressStarted(ProgressEvent arg0) {
// System.out.println("progressStarted ");
//
// }
/* (non-Javadoc)
* @see org.eclipse.zest.layouts.progress.ProgressListener#progressUpdated(org.eclipse.zest.layouts.progress.ProgressEvent)
*/
// public void progressUpdated(ProgressEvent arg0) {
// System.out.println("progressUpdated "+arg0.getTotalNumberOfSteps()+" "+arg0.getStepsCompleted());
//
// }
}