/****************************************************************************** * Copyright (C) 2006-2013 IFS Institute for Software and others * * 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 * * Original authors: * Dennis Hunziker * Ueli Kistler * Contributors: * Fabio Zadrozny <fabiofz@gmail.com> - initial implementation ******************************************************************************/ /* * Copyright (C) 2006, 2007 Dennis Hunziker, Ueli Kistler */ package ch.hsr.ukistler.astgraph; import java.awt.Color; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import java.io.IOException; import java.util.ArrayList; import java.util.List; import javax.swing.BorderFactory; import org.jgraph.graph.DefaultEdge; import org.jgraph.graph.DefaultGraphCell; import org.jgraph.graph.GraphConstants; import org.python.pydev.parser.jython.SimpleNode; import org.python.pydev.parser.jython.ast.Module; import org.python.pydev.parser.jython.ast.VisitorBase; import org.python.pydev.shared_core.structure.FastStack; /** * Traverse AST and generate the tree (shown by JGraph) * * @author Ueli Kistler * */ public class GraphVisitor extends VisitorBase { private static final int DEPTH_STEP = 30; private static final int INDENT_STEP = 40; private Color nodeColor; private List<DefaultGraphCell> cells; private FastStack<DefaultGraphCell> stack; int depth; int indent; public GraphVisitor() throws IOException { cells = new ArrayList<DefaultGraphCell>(); stack = new FastStack<DefaultGraphCell>(50); depth = 0; indent = 0; nodeColor = Color.GRAY; } private DefaultEdge createConnection(DefaultGraphCell cell) { DefaultEdge edge = new DefaultEdge(); edge.setSource(stack.peek().getChildAt(0)); edge.setTarget(cell); // Set Arrow Style for edge int arrow = GraphConstants.ARROW_TECHNICAL; GraphConstants.setLineEnd(edge.getAttributes(), arrow); GraphConstants.setEndFill(edge.getAttributes(), true); return edge; } public DefaultGraphCell createVertex(String name, double x, double y, Color bg, boolean raised) { // Create vertex with the given name DefaultGraphCell cell = new DefaultGraphCell(name); GraphConstants.setBorder(cell.getAttributes(), BorderFactory.createEtchedBorder()); GraphConstants.setBounds(cell.getAttributes(), new Rectangle2D.Double(x, y, 10, 10)); GraphConstants.setResize(cell.getAttributes(), true); GraphConstants.setAutoSize(cell.getAttributes(), true); // Set fill color if (bg != null) { GraphConstants.setOpaque(cell.getAttributes(), true); GraphConstants.setGradientColor(cell.getAttributes(), bg); } // Set raised border if (raised) GraphConstants.setBorder(cell.getAttributes(), BorderFactory.createRaisedBevelBorder()); else // Set black border GraphConstants.setBorderColor(cell.getAttributes(), Color.black); return cell; } private void decrementPosition() { stack.pop(); indent -= INDENT_STEP; } public DefaultGraphCell[] getCells() { return cells.toArray(new DefaultGraphCell[0]); } private void incrementPosition(DefaultGraphCell cell) { stack.push(cell); indent += INDENT_STEP; depth += DEPTH_STEP; } private void parentAddPort() { Point2D point = new Point2D.Double(0, GraphConstants.PERMILLE); stack.peek().addPort(point); } @Override public void traverse(SimpleNode node) throws Exception { node.traverse(this); decrementPosition(); } @Override protected Object unhandled_node(SimpleNode node) throws Exception { DefaultGraphCell cell = null; String caption = node.toString(); parentAddPort(); cell = createVertex(caption, indent, depth, nodeColor, false); DefaultEdge edge = createConnection(cell); cells.add(cell); cells.add(edge); incrementPosition(cell); return null; } /** * Entry point */ @Override public Object visitModule(Module node) throws Exception { // String caption = node.toString(); DefaultGraphCell moduleCell = createVertex("Module", indent, depth, nodeColor, false); cells.add(moduleCell); incrementPosition(moduleCell); traverse(node); return null; } }