Search in sources :

Example 6 with AgeConnection

use of org.osate.ge.graphics.internal.AgeConnection in project osate2 by osate.

the class ElkGraphBuilder method createElkGraphElementsForConnections.

/**
 * Creates ELK edges for connection diagram nodes which are descendants of the specified node.
 * Even though the results of the ELK edge routing are not used, it is still important because it affects the placements of shapes.
 */
private void createElkGraphElementsForConnections(final DiagramNode dn, final LayoutMapping mapping) {
    for (final DiagramElement de : dn.getChildren()) {
        if (de.getGraphic() instanceof AgeConnection) {
            final AgeConnection connection = (AgeConnection) de.getGraphic();
            // Flow indicators are represented by a node in the container which has a port and an edge connecting that port to the starting element
            final ElkConnectableShape edgeStart = getConnectableShape(de.getStartElement(), mapping);
            ElkConnectableShape edgeEnd = null;
            if (connection.isFlowIndicator) {
                // Find the first undocked ancestor for the flow indicator
                final DiagramElement undockedContainer = DiagramElementUtil.getUndockedDiagramElement(de.getParent());
                if (undockedContainer == null) {
                    // Ignore the flow indicator if unable to find a containing element which isn't docked.
                    continue;
                }
                // Find the ELK shape for the ancestor
                final ElkConnectableShape endContainer = getConnectableShape(undockedContainer, mapping);
                if (!(endContainer instanceof ElkNode)) {
                    // Ignore the flow indicator if the container isn't a node.
                    continue;
                }
                // Create the node for the end of the flow indicator
                final ElkNode endNode = ElkGraphUtil.createNode((ElkNode) endContainer);
                endContainer.setDimensions(0, 0);
                endNode.setProperty(CoreOptions.NODE_SIZE_CONSTRAINTS, EnumSet.noneOf(SizeConstraint.class));
                endNode.setProperty(CoreOptions.NODE_SIZE_OPTIONS, EnumSet.noneOf(SizeOptions.class));
                // Create port
                final ElkPort endPort = ElkGraphUtil.createPort(endNode);
                endPort.setProperty(CoreOptions.PORT_SIDE, PortSide.WEST);
                endPort.setX(0);
                endPort.setY(0);
                endPort.setWidth(0);
                endPort.setHeight(0);
                edgeEnd = endPort;
            } else {
                edgeEnd = getConnectableShape(de.getEndElement(), mapping);
            }
            if (edgeStart != null && edgeEnd != null) {
                final ElkConnectableShape start = edgeStart;
                final ElkConnectableShape end = edgeEnd;
                boolean insideSelfLoopsYo = true;
                // An example of this sort of edge is a steady state state transition in the EMV2
                if (start == end) {
                    insideSelfLoopsYo = false;
                }
                final ElkEdge newEdge = ElkGraphUtil.createSimpleEdge(start, end);
                // Allow edges with the same start and end shape because they layout as intended.
                if (start == end && start instanceof ElkPort) {
                    continue;
                }
                // Ensure the edge has at least one section. Fixes NPE that can occur when laying out connections
                // with the same source and destination port.
                ElkGraphUtil.createEdgeSection(newEdge);
                newEdge.setProperty(CoreOptions.INSIDE_SELF_LOOPS_YO, insideSelfLoopsYo);
                mapping.getGraphMap().put(newEdge, de);
                createElkLabels(de, newEdge, mapping);
                // along with other edges
                if (connection.isFlowIndicator && newEdge.getLabels().isEmpty()) {
                    final ElkLabel spacingLabel = createElkLabel(newEdge, "<Spacing>", new Dimension(10, 10));
                    if (!layoutConnectionLabels) {
                        spacingLabel.setProperty(CoreOptions.NO_LAYOUT, true);
                    }
                }
            }
        }
        createElkGraphElementsForConnections(de, mapping);
    }
}
Also used : DiagramElement(org.osate.ge.internal.diagram.runtime.DiagramElement) AgeConnection(org.osate.ge.graphics.internal.AgeConnection) ElkNode(org.eclipse.elk.graph.ElkNode) SizeOptions(org.eclipse.elk.core.options.SizeOptions) ElkLabel(org.eclipse.elk.graph.ElkLabel) ElkPort(org.eclipse.elk.graph.ElkPort) Dimension(org.osate.ge.graphics.Dimension) ElkConnectableShape(org.eclipse.elk.graph.ElkConnectableShape) SizeConstraint(org.eclipse.elk.core.options.SizeConstraint) ElkEdge(org.eclipse.elk.graph.ElkEdge)

Example 7 with AgeConnection

use of org.osate.ge.graphics.internal.AgeConnection in project osate2 by osate.

the class DiagramUpdater method removeInvalidConnections.

/**
 * Removes invalid connections.
 */
private void removeInvalidConnections(final DiagramModification m, final Collection<DiagramElement> connectionElements) {
    // Build Collection of All Invalid Connections
    final Set<DiagramElement> invalidConnectionElements = new HashSet<>();
    Iterator<DiagramElement> connectionElementsIt = connectionElements.iterator();
    while (connectionElementsIt.hasNext()) {
        final DiagramElement e = connectionElementsIt.next();
        if (e.getStartElement() == null || (e.getEndElement() == null && !((AgeConnection) e.getGraphic()).isFlowIndicator)) {
            invalidConnectionElements.add(e);
            // Remove the connection from the connection collection and the diagram
            connectionElementsIt.remove();
            ghostAndRemove(m, e);
        }
    }
    // Loop through the connections repeatedly until there are no longer any invalid connections referenced.
    for (int lastSize = 0; (invalidConnectionElements.size() - lastSize) > 0; lastSize = invalidConnectionElements.size()) {
        connectionElementsIt = connectionElements.iterator();
        while (connectionElementsIt.hasNext()) {
            final DiagramElement e = connectionElementsIt.next();
            if (invalidConnectionElements.contains(e.getStartElement()) || invalidConnectionElements.contains(e.getEndElement())) {
                invalidConnectionElements.add(e);
                // Remove the connection from the connection collection and the diagram
                removeConnectionAndDescendantConnections(e, connectionElements);
                ghostAndRemove(m, e);
            }
        }
    }
}
Also used : DiagramElement(org.osate.ge.internal.diagram.runtime.DiagramElement) AgeConnection(org.osate.ge.graphics.internal.AgeConnection) Point(org.osate.ge.graphics.Point) HashSet(java.util.HashSet)

Example 8 with AgeConnection

use of org.osate.ge.graphics.internal.AgeConnection in project osate2 by osate.

the class DiagramUpdater method updateElements.

/**
 * @param container is the container for which to update the elements
 * @param bos
 * @param connectionElements is a collection to populate with connection elements.
 */
private void updateElements(final DiagramModification m, final DiagramNode container, final Collection<BusinessObjectNode> bos, final Collection<DiagramElement> connectionElements) {
    for (final BusinessObjectNode n : bos) {
        // Get existing element. The updateStructure() pass should have ensured that it exists if a valid element could be created.
        final DiagramElement element = container.getChildByRelativeReference(n.getRelativeReference());
        if (element == null) {
            continue;
        }
        // Set fields
        m.setCompleteness(element, n.getCompleteness());
        // Set name fields
        m.setLabelName(element, infoProvider.getLabelName(element));
        m.setUserInterfaceName(element, infoProvider.getUserInterfaceName(element));
        // Set the graphical Configuration
        final GraphicalConfiguration graphicalConfiguration = infoProvider.getGraphicalConfiguration(element);
        if (graphicalConfiguration == null) {
            ghostAndRemove(m, element);
        } else {
            // Reset position of flow indicators if the start element has changed. This can occur when feature groups are expanded for example.
            if (element.hasPosition() && DiagramElementPredicates.isFlowIndicator(element) && graphicalConfiguration.getConnectionSource() != element.getStartElement()) {
                m.setPosition(element, null);
            }
            m.setGraphicalConfiguration(element, graphicalConfiguration);
            // Set the dock area based on the default docking position
            final DockingPosition defaultDockingPosition = graphicalConfiguration.getDefaultDockingPosition();
            final boolean dockable = defaultDockingPosition != DockingPosition.NOT_DOCKABLE;
            if (dockable) {
                // If parent is docked, the child should use the group docking area
                if (container instanceof DiagramElement && ((DiagramElement) container).getDockArea() != null) {
                    m.setDockArea(element, DockArea.GROUP);
                } else if (element.getDockArea() == null) {
                    m.setDockArea(element, DockArea.fromDockingPosition(defaultDockingPosition));
                }
            } else {
                // Ensure the dock area is null
                m.setDockArea(element, null);
            }
            // Set the initial position if there is a value in the future element position map
            // Set the position after the dock area so that setPosition() will know whether the element is dockable.
            final Map<RelativeBusinessObjectReference, FutureElementInfo> futureElementInfos = futureElementInfoMap.get(container);
            final FutureElementInfo futureElementInfo = futureElementInfos == null ? null : futureElementInfos.get(n.getRelativeReference());
            final Point initialPosition = futureElementInfo != null ? futureElementInfo.position : null;
            if (initialPosition != null) {
                m.setPosition(element, initialPosition);
            }
            if (element.getGraphic() instanceof AgeConnection) {
                // Add connection elements to the list so that they can be access later.
                connectionElements.add(element);
            }
            // Update the element's children
            updateElements(m, element, n.getChildren(), connectionElements);
        }
    }
}
Also used : DiagramElement(org.osate.ge.internal.diagram.runtime.DiagramElement) AgeConnection(org.osate.ge.graphics.internal.AgeConnection) GraphicalConfiguration(org.osate.ge.GraphicalConfiguration) DockingPosition(org.osate.ge.DockingPosition) RelativeBusinessObjectReference(org.osate.ge.RelativeBusinessObjectReference) Point(org.osate.ge.graphics.Point)

Aggregations

AgeConnection (org.osate.ge.graphics.internal.AgeConnection)8 DiagramElement (org.osate.ge.internal.diagram.runtime.DiagramElement)8 SizeConstraint (org.eclipse.elk.core.options.SizeConstraint)5 ElkEdge (org.eclipse.elk.graph.ElkEdge)5 ElkLabel (org.eclipse.elk.graph.ElkLabel)5 ElkNode (org.eclipse.elk.graph.ElkNode)5 ElkPort (org.eclipse.elk.graph.ElkPort)5 DockingPosition (org.osate.ge.DockingPosition)5 Dimension (org.osate.ge.graphics.Dimension)5 Collection (java.util.Collection)4 Collections (java.util.Collections)4 EnumSet (java.util.EnumSet)4 HashSet (java.util.HashSet)4 List (java.util.List)4 Entry (java.util.Map.Entry)4 Objects (java.util.Objects)4 Optional (java.util.Optional)4 Collectors (java.util.stream.Collectors)4 KVector (org.eclipse.elk.core.math.KVector)4 CoreOptions (org.eclipse.elk.core.options.CoreOptions)4