X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.graphviz%2Fsrc%2Forg%2Fsimantics%2Fgraphviz%2Fdrawable%2FGraphDrawable2.java;fp=bundles%2Forg.simantics.graphviz%2Fsrc%2Forg%2Fsimantics%2Fgraphviz%2Fdrawable%2FGraphDrawable2.java;h=edba7cea303e50a1d993212f5e4d8c0547f8a715;hp=0000000000000000000000000000000000000000;hb=969bd23cab98a79ca9101af33334000879fb60c5;hpb=866dba5cd5a3929bbeae85991796acb212338a08 diff --git a/bundles/org.simantics.graphviz/src/org/simantics/graphviz/drawable/GraphDrawable2.java b/bundles/org.simantics.graphviz/src/org/simantics/graphviz/drawable/GraphDrawable2.java new file mode 100644 index 000000000..edba7cea3 --- /dev/null +++ b/bundles/org.simantics.graphviz/src/org/simantics/graphviz/drawable/GraphDrawable2.java @@ -0,0 +1,207 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 Association for Decentralized Information Management + * in Industry THTH ry. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * VTT Technical Research Centre of Finland - initial API and implementation + *******************************************************************************/ +package org.simantics.graphviz.drawable; + +import java.awt.Graphics2D; +import java.awt.Shape; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ExecutionException; + +import org.simantics.graphviz.Edge; +import org.simantics.graphviz.Graph; +import org.simantics.graphviz.Graphs; +import org.simantics.graphviz.IGraphPart; +import org.simantics.graphviz.Identifiable; +import org.simantics.graphviz.continuation.Computation; +import org.simantics.graphviz.continuation.Continuation; +import org.simantics.graphviz.internal.parser.ParseException; +import org.simantics.graphviz.internal.xdot.DrawCommand; +import org.simantics.graphviz.internal.xdot.DrawCommandParser; +import org.simantics.graphviz.internal.xdot.ShapeCommand; + +/** + * A drawable that draws a given graph. + * Supports picking elements. + * + * TODO: optimize, uses hashmaps in places where those are not useful. + * + * + * @author Hannu Niemist� + * @author Marko Luukkainen + */ +public class GraphDrawable2 implements Drawable { + + private static String DEFAULT_ALGORITHM = "dot"; + + Collection commands; + Map> partCommands; + Map partBounds; + + Rectangle2D bounds; + + public GraphDrawable2(Graph graph, String algorithm) { + try { + setGraph(graph, algorithm).get(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public GraphDrawable2(Graph graph) { + setGraph(graph); + } + + public GraphDrawable2() { + commands = new ArrayList(); + partCommands = new HashMap>(); + partBounds = new HashMap(); + bounds = new Rectangle2D.Double(0, 0, 100, 100); + } + + /** + * Sets a new graph to be drawn. This operation may take a while. It can + * be called from any thread. + * @param graph + */ + public void setGraph(Graph graph) { + try { + setGraph(graph, DEFAULT_ALGORITHM).get(); + } catch(Exception e) { + e.printStackTrace(); + } + } + + + + /** + * Sets a new graph to be drawn. This operation may take a while. It can + * be called from any thread. + * @param graph + */ + public synchronized Computation setGraph(final Graph graph, String algorithm) { + Computation computation = Graphs.createXDot(graph, algorithm); + computation.addContinuation(new Continuation() { + @Override + public void succeeded(Graph xgraph) { + commands = new ArrayList(); + partCommands = new HashMap>(); + partBounds = new HashMap(); + DrawCommandParser.parse(xgraph,commands,partCommands); + readBoundingBox(xgraph); + updatePartBoundingBoxes(graph, xgraph); + } + + @Override + public void failed(Exception exception) { + } + }); + return computation; + } + + private void readBoundingBox(Graph graph) { + String[] parts = graph.get("bb").split(","); + double minX = Double.parseDouble(parts[0]); + double maxY = -Double.parseDouble(parts[1]); + double maxX = Double.parseDouble(parts[2]); + double minY = -Double.parseDouble(parts[3]); + bounds = new Rectangle2D.Double(minX, minY, maxX-minX, maxY-minY); + } + + private void updatePartBoundingBoxes(Graph graph, Graph xgraph) { + // we have to map input Nodes to XGraph nodes + + Map partMap = new HashMap(); + + for (IGraphPart xPart : xgraph.getParts()) { + if (xPart instanceof Identifiable) { + String xID = ((Identifiable)xPart).getId(); + for (IGraphPart gPart : graph.getParts()) { + if (gPart instanceof Identifiable) { + String gID = ((Identifiable)gPart).getId(); + if (xID.equals(gID)) { + partMap.put(xPart, gPart); + } + } + } + } else if (xPart instanceof Edge) { + String xHeadId = ((Edge)xPart).getHead().getId(); + String xTailId = ((Edge)xPart).getTail().getId(); + for (IGraphPart gPart : graph.getParts()) { + if (gPart instanceof Edge) { + String gHeadId = ((Edge)gPart).getHead().getId(); + String gTailId = ((Edge)gPart).getTail().getId(); + + if (xHeadId.equals(gHeadId) && xTailId.equals(gTailId)) { + partMap.put(xPart, gPart); + } + } + } + } + } + + + + for (IGraphPart part : partCommands.keySet()) { + Collection pCommands = partCommands.get(part); + Rectangle2D r = null; + for (DrawCommand c : pCommands) { + if (c instanceof ShapeCommand) { + Shape s = ((ShapeCommand)c).getShape(); + if (r == null) + r = s.getBounds2D(); + else + r.add(s.getBounds2D()); + } + } + if (r != null) { + partBounds.put(partMap.get(part), r); + } + } + } + + @Override + public synchronized Rectangle2D getBounds() { + return bounds; + } + + + public synchronized Rectangle2D getBounds(IGraphPart part) { + return partBounds.get(part); + } + + public synchronized Collection pick(Point2D point) { + Collection picked = new ArrayList(); + for (IGraphPart part : partBounds.keySet()) { + Rectangle2D r = partBounds.get(part); + if (r.contains(point)) + picked.add(part); + } + return picked; + } + + @Override + public synchronized void draw(Graphics2D g, Rectangle2D area) { + for(DrawCommand command : commands) + command.draw(g); + +// for (Rectangle2D r : partBounds.values()) { +// g.drawRect((int)r.getMinX(), (int)r.getMinY(), (int)r.getWidth(), (int)r.getHeight()); +// } + } + +}