Search in sources :

Example 1 with NodeStatement

use of org.eclipse.elk.alg.graphviz.dot.dot.NodeStatement in project elk by eclipse.

the class DotExporter method transformNodes.

/**
 * Transform the child nodes of the given parent node.
 *
 * @param parent a parent node
 * @param statements the list to which new statements are added
 * @param offset offset of the parent node in the whole graph
 * @param transData transformation data
 */
private void transformNodes(final ElkNode parent, final List<Statement> statements, final KVector offset, final IDotTransformationData<ElkNode, GraphvizModel> transData) {
    // set attributes for the whole graph
    setGraphAttributes(statements, parent, transData);
    // create nodes and subgraphs
    boolean hierarchy = transData.getProperty(HIERARCHY);
    boolean transformNodeLayout = transData.getProperty(TRANSFORM_NODE_LAYOUT);
    boolean transformNodeLabels = transData.getProperty(TRANSFORM_NODE_LABELS);
    for (ElkNode childNode : parent.getChildren()) {
        NodeStatement nodeStatement = DotFactory.eINSTANCE.createNodeStatement();
        List<Attribute> attributes = nodeStatement.getAttributes();
        String nodeID;
        // if hierarchy mode is active, create a subgraph, else a regular node
        if (hierarchy && !childNode.getChildren().isEmpty()) {
            String clusterNodeID = getNodeID(childNode, NodeType.CLUSTER, transData);
            Subgraph subgraph = DotFactory.eINSTANCE.createSubgraph();
            subgraph.setName(clusterNodeID);
            statements.add(subgraph);
            // transform child nodes recursively
            ElkPadding padding = childNode.getProperty(CoreOptions.PADDING);
            double subgraphx = childNode.getX() + padding.getLeft();
            double subgraphy = childNode.getY() + padding.getTop();
            transformNodes(childNode, subgraph.getStatements(), new KVector(offset).add(subgraphx, subgraphy), transData);
            // create a dummy node for compound edges
            nodeID = getNodeID(childNode, NodeType.DUMMY, transData);
            attributes.add(createAttribute(Attributes.STYLE, "invis"));
            attributes.add(createAttribute(Attributes.WIDTH, 0));
            attributes.add(createAttribute(Attributes.HEIGHT, 0));
            subgraph.getStatements().add(nodeStatement);
        } else {
            nodeID = getNodeID(childNode, NodeType.NODE, transData);
            // set width and height
            ElkUtil.resizeNode(childNode);
            if (childNode.getWidth() > 0) {
                attributes.add(createAttribute(Attributes.WIDTH, childNode.getWidth() / DPI));
            }
            if (childNode.getHeight() > 0) {
                attributes.add(createAttribute(Attributes.HEIGHT, childNode.getHeight() / DPI));
            }
            if (transformNodeLabels && !childNode.getLabels().isEmpty() && childNode.getLabels().get(0).getText().length() > 0) {
                attributes.add(createAttribute(Attributes.LABEL, createString(childNode.getLabels().get(0).getText())));
            }
            // add node position if interactive layout is chosen
            if (transformNodeLayout && (childNode.getX() != 0 || childNode.getY() != 0)) {
                double xpos = (childNode.getX() + childNode.getWidth() / 2 + offset.x);
                double ypos = (childNode.getY() + childNode.getHeight() / 2 + offset.y);
                String posString = "\"" + Double.toString(xpos) + "," + Double.toString(ypos) + "\"";
                attributes.add(createAttribute(Attributes.POS, posString));
            }
            statements.add(nodeStatement);
        }
        Node node = DotFactory.eINSTANCE.createNode();
        node.setName(nodeID);
        nodeStatement.setNode(node);
    }
}
Also used : ElkNode(org.eclipse.elk.graph.ElkNode) Attribute(org.eclipse.elk.alg.graphviz.dot.dot.Attribute) NodeStatement(org.eclipse.elk.alg.graphviz.dot.dot.NodeStatement) ElkNode(org.eclipse.elk.graph.ElkNode) Node(org.eclipse.elk.alg.graphviz.dot.dot.Node) Subgraph(org.eclipse.elk.alg.graphviz.dot.dot.Subgraph) KVector(org.eclipse.elk.core.math.KVector) ElkPadding(org.eclipse.elk.core.math.ElkPadding)

Example 2 with NodeStatement

use of org.eclipse.elk.alg.graphviz.dot.dot.NodeStatement in project elk by eclipse.

the class DotImporter method applyLayout.

/*---------- Layout Transfer KGraph to Dot ----------*/
/**
 * Apply layout to a parent node and its children.
 *
 * @param parent a parent node
 * @param offset the node's offset in the graph
 * @param graph the Graphviz graph
 */
private void applyLayout(final ElkNode parent, final KVector offset, final Graph graph) {
    for (ElkNode elknode : parent.getChildren()) {
        Statement statement = elknode.getProperty(PROP_STATEMENT);
        if (statement == null) {
            // the node was only declared implicitly - create an explicit declaration
            NodeStatement stm = DotFactory.eINSTANCE.createNodeStatement();
            Node node = DotFactory.eINSTANCE.createNode();
            node.setName(elknode.getProperty(PROP_ID));
            stm.setNode(node);
            graph.getStatements().add(stm);
            statement = stm;
        }
        if (statement instanceof NodeStatement) {
            List<Attribute> attributes = ((NodeStatement) statement).getAttributes();
            // transfer node position
            removeAttributes(attributes, Attributes.POS);
            double xpos = elknode.getX() + elknode.getWidth() / 2 + offset.x;
            double ypos = elknode.getY() + elknode.getHeight() / 2 + offset.y;
            String posString = "\"" + Double.toString(xpos) + "," + Double.toString(ypos) + "\"";
            attributes.add(DotExporter.createAttribute(Attributes.POS, posString));
            // transfer node size
            removeAttributes(attributes, Attributes.WIDTH);
            attributes.add(DotExporter.createAttribute(Attributes.WIDTH, elknode.getWidth() / DotExporter.DPI));
            removeAttributes(attributes, Attributes.HEIGHT);
            attributes.add(DotExporter.createAttribute(Attributes.HEIGHT, elknode.getHeight() / DotExporter.DPI));
        } else if (statement instanceof Subgraph) {
            applyLayout(elknode, new KVector(offset).add(elknode.getX(), elknode.getY()), graph);
        }
        for (ElkEdge elkedge : ElkGraphUtil.allOutgoingEdges(elknode)) {
            applyLayout(elkedge, offset, graph);
        }
    }
    // transfer graph size to bounding box
    List<Statement> statements;
    Statement graphStm = parent.getProperty(PROP_STATEMENT);
    if (graphStm instanceof Subgraph) {
        statements = ((Subgraph) graphStm).getStatements();
    } else {
        statements = graph.getStatements();
    }
    removeGraphAttributes(statements, Attributes.BOUNDINGBOX);
    String bbString = "\"0,0," + Double.toString(parent.getWidth()) + "," + Double.toString(parent.getHeight()) + "\"";
    statements.add(DotExporter.createAttribute(Attributes.BOUNDINGBOX, bbString));
}
Also used : ElkNode(org.eclipse.elk.graph.ElkNode) Attribute(org.eclipse.elk.alg.graphviz.dot.dot.Attribute) EdgeStatement(org.eclipse.elk.alg.graphviz.dot.dot.EdgeStatement) NodeStatement(org.eclipse.elk.alg.graphviz.dot.dot.NodeStatement) AttributeStatement(org.eclipse.elk.alg.graphviz.dot.dot.AttributeStatement) Statement(org.eclipse.elk.alg.graphviz.dot.dot.Statement) NodeStatement(org.eclipse.elk.alg.graphviz.dot.dot.NodeStatement) ElkNode(org.eclipse.elk.graph.ElkNode) Node(org.eclipse.elk.alg.graphviz.dot.dot.Node) Subgraph(org.eclipse.elk.alg.graphviz.dot.dot.Subgraph) KVector(org.eclipse.elk.core.math.KVector) ElkEdge(org.eclipse.elk.graph.ElkEdge)

Example 3 with NodeStatement

use of org.eclipse.elk.alg.graphviz.dot.dot.NodeStatement in project elk by eclipse.

the class DotImporter method transform.

/*---------- Transformation Dot to KGraph ----------*/
/**
 * Transform a Dot graph to a KNode.
 *
 * @param statements
 *            a list of Dot statements
 * @param parent
 *            a KNode
 * @param transData
 *            transformation data instance
 * @param nodeProps
 *            properties that are applied to all nodes
 * @param edgeProps
 *            properties that are applied to all edges
 */
private void transform(final List<Statement> statements, final ElkNode parent, final IDotTransformationData<GraphvizModel, ElkNode> transData, final IPropertyHolder nodeProps, final IPropertyHolder edgeProps) {
    DotSwitch<Object> statementSwitch = new DotSwitch<Object>() {

        public Object caseNodeStatement(final NodeStatement statement) {
            transformNode(statement, parent, transData, nodeProps);
            return null;
        }

        public Object caseEdgeStatement(final EdgeStatement statement) {
            transformEdge(statement, parent, transData, edgeProps);
            return null;
        }

        public Object caseSubgraph(final Subgraph subgraph) {
            ElkNode subElkNode = parent;
            if (subgraph.getName() != null && subgraph.getName().startsWith("cluster")) {
                subElkNode = transformNode(subgraph.getName(), parent, transData);
                if (subElkNode.getProperty(PROP_STATEMENT) != null) {
                    transData.log("Discarding cluster subgraph \"" + subgraph.getName() + "\" since its id is already used.");
                    return null;
                } else {
                    // the subgraph inherits all settings of its parent
                    subElkNode.copyProperties(parent);
                    subElkNode.setProperty(PROP_STATEMENT, subgraph);
                }
            }
            MapPropertyHolder subNodeProps = new MapPropertyHolder();
            subNodeProps.copyProperties(nodeProps);
            MapPropertyHolder subEdgeProps = new MapPropertyHolder();
            subEdgeProps.copyProperties(edgeProps);
            transform(subgraph.getStatements(), subElkNode, transData, subNodeProps, subEdgeProps);
            return null;
        }

        public Object caseAttributeStatement(final AttributeStatement statement) {
            switch(statement.getType()) {
                case GRAPH:
                    for (Attribute attr : statement.getAttributes()) {
                        caseAttribute(attr);
                    }
                    break;
                case NODE:
                    for (Attribute attr : statement.getAttributes()) {
                        transformAttribute(nodeProps, attr, transData);
                    }
                    break;
                case EDGE:
                    for (Attribute attr : statement.getAttributes()) {
                        transformAttribute(edgeProps, attr, transData);
                    }
                    break;
            }
            return null;
        }

        public Object caseAttribute(final Attribute attribute) {
            if (Attributes.MARGIN.equals(attribute.getName())) {
                ElkPadding padding = parent.getProperty(CoreOptions.PADDING);
                if (attribute.getValue().indexOf(',') >= 0) {
                    KVector value = new KVector();
                    try {
                        value.parse(attribute.getValue());
                        padding.setLeft((float) value.x);
                        padding.setRight((float) value.x);
                        padding.setTop((float) value.y);
                        padding.setBottom((float) value.y);
                    } catch (IllegalArgumentException exception) {
                        transData.log("Discarding attribute \"" + attribute.getName() + "\" since its value could not be parsed correctly.");
                    }
                } else {
                    try {
                        float value = Float.parseFloat(trimValue(attribute));
                        padding.setLeft(value);
                        padding.setRight(value);
                        padding.setTop(value);
                        padding.setBottom(value);
                    } catch (NumberFormatException exception) {
                        transData.log("Discarding attribute \"" + attribute.getName() + "\" since its value could not be parsed correctly.");
                    }
                }
            } else {
                transformAttribute(parent, attribute, transData);
            }
            return null;
        }
    };
    for (Statement statement : statements) {
        statementSwitch.doSwitch(statement);
    }
}
Also used : ElkNode(org.eclipse.elk.graph.ElkNode) Attribute(org.eclipse.elk.alg.graphviz.dot.dot.Attribute) NodeStatement(org.eclipse.elk.alg.graphviz.dot.dot.NodeStatement) EdgeStatement(org.eclipse.elk.alg.graphviz.dot.dot.EdgeStatement) NodeStatement(org.eclipse.elk.alg.graphviz.dot.dot.NodeStatement) AttributeStatement(org.eclipse.elk.alg.graphviz.dot.dot.AttributeStatement) Statement(org.eclipse.elk.alg.graphviz.dot.dot.Statement) MapPropertyHolder(org.eclipse.elk.graph.properties.MapPropertyHolder) EdgeStatement(org.eclipse.elk.alg.graphviz.dot.dot.EdgeStatement) AttributeStatement(org.eclipse.elk.alg.graphviz.dot.dot.AttributeStatement) Subgraph(org.eclipse.elk.alg.graphviz.dot.dot.Subgraph) KVector(org.eclipse.elk.core.math.KVector) ElkPadding(org.eclipse.elk.core.math.ElkPadding) DotSwitch(org.eclipse.elk.alg.graphviz.dot.dot.util.DotSwitch)

Example 4 with NodeStatement

use of org.eclipse.elk.alg.graphviz.dot.dot.NodeStatement in project elk by eclipse.

the class AbstractGraphvizDotSemanticSequencer method sequence.

@Override
public void sequence(ISerializationContext context, EObject semanticObject) {
    EPackage epackage = semanticObject.eClass().getEPackage();
    ParserRule rule = context.getParserRule();
    Action action = context.getAssignedAction();
    Set<Parameter> parameters = context.getEnabledBooleanParameters();
    if (epackage == DotPackage.eINSTANCE)
        switch(semanticObject.eClass().getClassifierID()) {
            case DotPackage.ATTRIBUTE:
                if (rule == grammarAccess.getStatementRule() || rule == grammarAccess.getAttributeRule()) {
                    sequence_Attribute(context, (Attribute) semanticObject);
                    return;
                } else if (rule == grammarAccess.getListAttributeRule()) {
                    sequence_ListAttribute(context, (Attribute) semanticObject);
                    return;
                } else
                    break;
            case DotPackage.ATTRIBUTE_STATEMENT:
                sequence_AttributeStatement(context, (AttributeStatement) semanticObject);
                return;
            case DotPackage.EDGE_STATEMENT:
                sequence_EdgeStatement(context, (EdgeStatement) semanticObject);
                return;
            case DotPackage.EDGE_TARGET:
                sequence_EdgeTarget(context, (EdgeTarget) semanticObject);
                return;
            case DotPackage.GRAPH:
                sequence_Graph(context, (Graph) semanticObject);
                return;
            case DotPackage.GRAPHVIZ_MODEL:
                sequence_GraphvizModel(context, (GraphvizModel) semanticObject);
                return;
            case DotPackage.NODE:
                sequence_Node(context, (Node) semanticObject);
                return;
            case DotPackage.NODE_STATEMENT:
                sequence_NodeStatement(context, (NodeStatement) semanticObject);
                return;
            case DotPackage.PORT:
                sequence_Port(context, (Port) semanticObject);
                return;
            case DotPackage.SUBGRAPH:
                sequence_Subgraph(context, (Subgraph) semanticObject);
                return;
        }
    if (errorAcceptor != null)
        errorAcceptor.accept(diagnosticProvider.createInvalidContextOrTypeDiagnostic(semanticObject, context));
}
Also used : ParserRule(org.eclipse.xtext.ParserRule) Action(org.eclipse.xtext.Action) Attribute(org.eclipse.elk.alg.graphviz.dot.dot.Attribute) NodeStatement(org.eclipse.elk.alg.graphviz.dot.dot.NodeStatement) Node(org.eclipse.elk.alg.graphviz.dot.dot.Node) Port(org.eclipse.elk.alg.graphviz.dot.dot.Port) EdgeStatement(org.eclipse.elk.alg.graphviz.dot.dot.EdgeStatement) EPackage(org.eclipse.emf.ecore.EPackage) GraphvizModel(org.eclipse.elk.alg.graphviz.dot.dot.GraphvizModel) Graph(org.eclipse.elk.alg.graphviz.dot.dot.Graph) AttributeStatement(org.eclipse.elk.alg.graphviz.dot.dot.AttributeStatement) EdgeTarget(org.eclipse.elk.alg.graphviz.dot.dot.EdgeTarget) Subgraph(org.eclipse.elk.alg.graphviz.dot.dot.Subgraph) Parameter(org.eclipse.xtext.Parameter)

Example 5 with NodeStatement

use of org.eclipse.elk.alg.graphviz.dot.dot.NodeStatement in project elk by eclipse.

the class DotExporter method applyLayout.

/**
 * Applies layout information from a Graphviz model to the original graph.
 * Note that GraphViz uses cubic B-Splines for edge routing, some generalization of Bezier curves.
 * Edge offsets are given separately, since on some platforms edges seem to have a different
 * reference point than nodes.
 *
 * @param parentNode parent node of the original graph
 * @param statements list of statements to process
 * @param baseOffset offset to be added to edge and subgraph coordinates
 * @param transData transformation data
 */
private void applyLayout(final ElkNode parentNode, final List<Statement> statements, final KVector baseOffset, final ElkPadding outerPadding, final IDotTransformationData<ElkNode, GraphvizModel> transData) {
    // process attributes: determine bounding box of the parent node
    ElkPadding padding = outerPadding;
    KVector nodeOffset = new KVector();
    attr_loop: for (Statement statement : statements) {
        if (statement instanceof AttributeStatement) {
            AttributeStatement attributeStatement = (AttributeStatement) statement;
            if (attributeStatement.getType() == AttributeType.GRAPH) {
                for (Attribute attribute : attributeStatement.getAttributes()) {
                    if (attribute.getName().equals(Attributes.BOUNDINGBOX)) {
                        try {
                            StringTokenizer tokenizer = new StringTokenizer(attribute.getValue(), ATTRIBUTE_DELIM);
                            double leftx = Double.parseDouble(tokenizer.nextToken());
                            double bottomy = Double.parseDouble(tokenizer.nextToken());
                            double rightx = Double.parseDouble(tokenizer.nextToken());
                            double topy = Double.parseDouble(tokenizer.nextToken());
                            // set parent node attributes
                            double width = rightx - leftx;
                            double height = bottomy - topy;
                            if (parentNode == transData.getSourceGraph()) {
                                // the root node, representing the drawing frame
                                width += padding.getHorizontal();
                                height += padding.getVertical();
                                baseOffset.add(-leftx, -topy);
                                nodeOffset.add(-leftx, -topy);
                            } else {
                                // a child or descendant of the root node
                                parentNode.setX(baseOffset.x + leftx + padding.getLeft());
                                parentNode.setY(baseOffset.y + topy + padding.getTop());
                                // since dot uses a 'compound' layout instead of laying out a hierarchical graph,
                                // no padding is supported for children
                                padding = new ElkPadding();
                                // ... and the children's offset must be somewhat adjusted
                                nodeOffset.x = -(baseOffset.x + leftx);
                                nodeOffset.y = -(baseOffset.y + topy);
                            }
                            ElkUtil.resizeNode(parentNode, width, height, false, true);
                            parentNode.setProperty(CoreOptions.NODE_SIZE_CONSTRAINTS, SizeConstraint.fixed());
                            break attr_loop;
                        } catch (NumberFormatException exception) {
                        // ignore exception
                        } catch (NoSuchElementException exception) {
                        // ignore exception
                        }
                    }
                }
            }
        }
    }
    // process nodes and subgraphs to collect all offset data
    for (Statement statement : statements) {
        if (statement instanceof NodeStatement) {
            applyNodeLayout((NodeStatement) statement, nodeOffset, padding, transData);
        } else if (statement instanceof Subgraph) {
            Subgraph subgraph = (Subgraph) statement;
            ElkNode elknode = (ElkNode) transData.getProperty(GRAPH_ELEMS).get(subgraph.getName());
            applyLayout(elknode, subgraph.getStatements(), baseOffset, padding, transData);
            elknode.setX(elknode.getX() + nodeOffset.x);
            elknode.setY(elknode.getY() + nodeOffset.y);
        }
    }
}
Also used : StringTokenizer(java.util.StringTokenizer) ElkNode(org.eclipse.elk.graph.ElkNode) Attribute(org.eclipse.elk.alg.graphviz.dot.dot.Attribute) EdgeStatement(org.eclipse.elk.alg.graphviz.dot.dot.EdgeStatement) NodeStatement(org.eclipse.elk.alg.graphviz.dot.dot.NodeStatement) AttributeStatement(org.eclipse.elk.alg.graphviz.dot.dot.AttributeStatement) Statement(org.eclipse.elk.alg.graphviz.dot.dot.Statement) AttributeStatement(org.eclipse.elk.alg.graphviz.dot.dot.AttributeStatement) NodeStatement(org.eclipse.elk.alg.graphviz.dot.dot.NodeStatement) Subgraph(org.eclipse.elk.alg.graphviz.dot.dot.Subgraph) KVector(org.eclipse.elk.core.math.KVector) ElkPadding(org.eclipse.elk.core.math.ElkPadding) NoSuchElementException(java.util.NoSuchElementException)

Aggregations

Attribute (org.eclipse.elk.alg.graphviz.dot.dot.Attribute)5 NodeStatement (org.eclipse.elk.alg.graphviz.dot.dot.NodeStatement)5 Subgraph (org.eclipse.elk.alg.graphviz.dot.dot.Subgraph)5 AttributeStatement (org.eclipse.elk.alg.graphviz.dot.dot.AttributeStatement)4 EdgeStatement (org.eclipse.elk.alg.graphviz.dot.dot.EdgeStatement)4 KVector (org.eclipse.elk.core.math.KVector)4 ElkNode (org.eclipse.elk.graph.ElkNode)4 Node (org.eclipse.elk.alg.graphviz.dot.dot.Node)3 Statement (org.eclipse.elk.alg.graphviz.dot.dot.Statement)3 ElkPadding (org.eclipse.elk.core.math.ElkPadding)3 NoSuchElementException (java.util.NoSuchElementException)1 StringTokenizer (java.util.StringTokenizer)1 EdgeTarget (org.eclipse.elk.alg.graphviz.dot.dot.EdgeTarget)1 Graph (org.eclipse.elk.alg.graphviz.dot.dot.Graph)1 GraphvizModel (org.eclipse.elk.alg.graphviz.dot.dot.GraphvizModel)1 Port (org.eclipse.elk.alg.graphviz.dot.dot.Port)1 DotSwitch (org.eclipse.elk.alg.graphviz.dot.dot.util.DotSwitch)1 ElkEdge (org.eclipse.elk.graph.ElkEdge)1 MapPropertyHolder (org.eclipse.elk.graph.properties.MapPropertyHolder)1 EPackage (org.eclipse.emf.ecore.EPackage)1