/******************************************************************************* * 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.geom.Rectangle2D; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; import org.simantics.graphviz.Graph; import org.simantics.graphviz.Graphs; import org.simantics.graphviz.continuation.Computation; import org.simantics.graphviz.continuation.Continuation; import org.simantics.graphviz.internal.xdot.DrawCommand; import org.simantics.graphviz.internal.xdot.DrawCommandParser; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * A drawable that draws a given graph. * * @author Hannu Niemist� */ public class GraphDrawable implements Drawable { private static final Logger LOGGER = LoggerFactory.getLogger(GraphDrawable.class); private static String DEFAULT_ALGORITHM = "dot"; DrawCommand[] commands; Rectangle2D bounds; private Graph graph; private String algorithm; public GraphDrawable(Graph graph, String algorithm) { setGraph(graph, algorithm); } public GraphDrawable(Graph graph) { setGraph(graph); } public GraphDrawable() { commands = new DrawCommand[0]; bounds = new Rectangle2D.Double(0, 0, 100, 100); } public Graph getGraph() { return graph; } public String getAlgorithm() { return algorithm; } /** * 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) { setGraph(graph, DEFAULT_ALGORITHM); } /** * Sets a new graph to be drawn. This operation may take a while. It can * be called from any thread. * @param graph */ public Computation setGraph(Graph graph, String algorithm) { this.graph = graph; this.algorithm = algorithm; Computation computation = Graphs.createXDot(graph, algorithm); final Semaphore semaphore = new Semaphore(0); computation.addContinuation(new Continuation() { @Override public void succeeded(Graph xgraph) { commands = DrawCommandParser.parse(xgraph); readBoundingBox(xgraph); semaphore.release(); } @Override public void failed(Exception exception) { exception.printStackTrace(); semaphore.release(); } }); try { semaphore.tryAcquire(5L, TimeUnit.SECONDS); } catch (InterruptedException e) { e.printStackTrace(); } 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); } @Override public synchronized Rectangle2D getBounds() { if(bounds == null) LOGGER.warn("bounds == null"); return bounds; } @Override public synchronized void draw(Graphics2D g, Rectangle2D area) { for(DrawCommand command : commands) command.draw(g); } }