Search in sources :

Example 11 with KEdge

use of de.cau.cs.kieler.klighd.kgraph.KEdge in project lingua-franca by lf-lang.

the class LinguaFrancaSynthesis method createDependencyEdge.

private KEdge createDependencyEdge(Object associate) {
    KEdge edge = _kEdgeExtensions.createEdge();
    if (associate != null) {
        associateWith(edge, associate);
    }
    KPolyline line = _kEdgeExtensions.addPolyline(edge);
    _linguaFrancaStyleExtensions.boldLineSelectionStyle(line);
    _kPolylineExtensions.addJunctionPointDecorator(line);
    if (getBooleanValue(USE_ALTERNATIVE_DASH_PATTERN)) {
        _kRenderingExtensions.setLineStyle(line, LineStyle.CUSTOM);
        _kRenderingExtensions.getLineStyle(line).getDashPattern().addAll(ALTERNATIVE_DASH_PATTERN);
    } else {
        _kRenderingExtensions.setLineStyle(line, LineStyle.DASH);
    }
    return edge;
}
Also used : KEdge(de.cau.cs.kieler.klighd.kgraph.KEdge) KPolyline(de.cau.cs.kieler.klighd.krendering.KPolyline)

Example 12 with KEdge

use of de.cau.cs.kieler.klighd.kgraph.KEdge in project lingua-franca by lf-lang.

the class LinguaFrancaSynthesis method detectAndAnnotateCycles.

private KNode detectAndAnnotateCycles(KNode node, ReactorInstance reactorInstance, Map<ReactorInstance, KNode> allReactorNodes) {
    if (node.getProperty(REACTOR_RECURSIVE_INSTANTIATION)) {
        _filterCycleAction.resetCycleFiltering(node);
        return addErrorComment(node, TEXT_ERROR_CONTAINS_RECURSION);
    } else {
        // only detect dependency cycles if not recursive
        try {
            boolean hasCycle = _cycleVisualization.detectAndHighlightCycles(reactorInstance, allReactorNodes, it -> {
                if (it instanceof KNode) {
                    List<KRendering> renderings = IterableExtensions.toList(Iterables.filter(((KNode) it).getData(), KRendering.class));
                    if (renderings.size() == 1) {
                        _linguaFrancaStyleExtensions.errorStyle(IterableExtensions.head(renderings));
                    } else {
                        IterableExtensions.filter(renderings, rendering -> {
                            return rendering.getProperty(KlighdProperties.COLLAPSED_RENDERING);
                        }).forEach(_linguaFrancaStyleExtensions::errorStyle);
                    }
                } else if (it instanceof KEdge) {
                    Iterables.filter(((KEdge) it).getData(), KRendering.class).forEach(_linguaFrancaStyleExtensions::errorStyle);
                    // TODO initiallyHide does not work with incremental (https://github.com/kieler/KLighD/issues/37)
                    // cycleEgde.initiallyShow() // Show hidden order dependencies
                    _kRenderingExtensions.setInvisible(_kRenderingExtensions.getKRendering(it), false);
                } else if (it instanceof KPort) {
                    Iterables.filter(((KPort) it).getData(), KRendering.class).forEach(_linguaFrancaStyleExtensions::errorStyle);
                // it.reverseTrianglePort()
                }
            });
            if (hasCycle) {
                KNode err = addErrorComment(node, TEXT_ERROR_CONTAINS_CYCLE);
                // Add to existing figure
                KRectangle rectangle = _kContainerRenderingExtensions.addRectangle(_kRenderingExtensions.getKContainerRendering(err));
                _kRenderingExtensions.to(_kRenderingExtensions.from(_kRenderingExtensions.setGridPlacementData(rectangle), _kRenderingExtensions.LEFT, 3, 0, _kRenderingExtensions.TOP, (-1), 0), _kRenderingExtensions.RIGHT, 3, 0, _kRenderingExtensions.BOTTOM, 3, 0);
                _linguaFrancaStyleExtensions.noSelectionStyle(rectangle);
                _kRenderingExtensions.setInvisible(rectangle, true);
                _kContainerRenderingExtensions.setGridPlacement(rectangle, 2);
                KRectangle subrectangle = _kContainerRenderingExtensions.addRectangle(rectangle);
                _kRenderingExtensions.to(_kRenderingExtensions.from(_kRenderingExtensions.setGridPlacementData(subrectangle), _kRenderingExtensions.LEFT, 0, 0, _kRenderingExtensions.TOP, 0, 0), _kRenderingExtensions.RIGHT, 2, 0, _kRenderingExtensions.BOTTOM, 0, 0);
                _linguaFrancaStyleExtensions.noSelectionStyle(subrectangle);
                _kRenderingExtensions.addSingleClickAction(subrectangle, ShowCycleAction.ID);
                KText subrectangleText = _kContainerRenderingExtensions.addText(subrectangle, TEXT_ERROR_CYCLE_BTN_SHOW);
                // Copy text style
                List<KStyle> styles = ListExtensions.map(IterableExtensions.head(_kRenderingExtensions.getKContainerRendering(err).getChildren()).getStyles(), EcoreUtil::copy);
                subrectangleText.getStyles().addAll(styles);
                _kRenderingExtensions.setFontSize(subrectangleText, 5);
                _kRenderingExtensions.setSurroundingSpace(subrectangleText, 1, 0);
                _linguaFrancaStyleExtensions.noSelectionStyle(subrectangleText);
                _kRenderingExtensions.addSingleClickAction(subrectangleText, ShowCycleAction.ID);
                subrectangle = _kContainerRenderingExtensions.addRectangle(rectangle);
                _kRenderingExtensions.to(_kRenderingExtensions.from(_kRenderingExtensions.setGridPlacementData(subrectangle), _kRenderingExtensions.LEFT, 0, 0, _kRenderingExtensions.TOP, 0, 0), _kRenderingExtensions.RIGHT, 0, 0, _kRenderingExtensions.BOTTOM, 0, 0);
                _linguaFrancaStyleExtensions.noSelectionStyle(subrectangle);
                _kRenderingExtensions.addSingleClickAction(subrectangle, FilterCycleAction.ID);
                subrectangleText = _kContainerRenderingExtensions.addText(subrectangle, _filterCycleAction.isCycleFiltered(node) ? TEXT_ERROR_CYCLE_BTN_UNFILTER : TEXT_ERROR_CYCLE_BTN_FILTER);
                // Copy text style
                styles = ListExtensions.map(IterableExtensions.head(_kRenderingExtensions.getKContainerRendering(err).getChildren()).getStyles(), EcoreUtil::copy);
                subrectangleText.getStyles().addAll(styles);
                _kRenderingExtensions.setFontSize(subrectangleText, 5);
                _kRenderingExtensions.setSurroundingSpace(subrectangleText, 1, 0);
                _linguaFrancaStyleExtensions.noSelectionStyle(subrectangleText);
                _kRenderingExtensions.addSingleClickAction(subrectangleText, FilterCycleAction.ID);
                _filterCycleAction.markCycleFilterText(subrectangleText, err);
                // if user interactively requested a filtered diagram keep it filtered during updates
                if (_filterCycleAction.isCycleFiltered(node)) {
                    _filterCycleAction.filterCycle(node);
                }
                return err;
            }
        } catch (Exception e) {
            _filterCycleAction.resetCycleFiltering(node);
            e.printStackTrace();
            return addErrorComment(node, TEXT_ERROR_CYCLE_DETECTION);
        }
    }
    return null;
}
Also used : LineCap(de.cau.cs.kieler.klighd.krendering.LineCap) CoreOptions(org.eclipse.elk.core.options.CoreOptions) ElkMargin(org.eclipse.elk.core.math.ElkMargin) Exceptions(org.eclipse.xtext.xbase.lib.Exceptions) MemorizingExpandCollapseAction(org.lflang.diagram.synthesis.action.MemorizingExpandCollapseAction) LinguaFrancaStyleExtensions(org.lflang.diagram.synthesis.styles.LinguaFrancaStyleExtensions) PortSide(org.eclipse.elk.core.options.PortSide) KLabelExtensions(de.cau.cs.kieler.klighd.krendering.extensions.KLabelExtensions) FileUtil(org.lflang.util.FileUtil) HashBasedTable(com.google.common.collect.HashBasedTable) ExpandAllReactorsAction(org.lflang.diagram.synthesis.action.ExpandAllReactorsAction) Extension(org.eclipse.xtext.xbase.lib.Extension) CollapseAllReactorsAction(org.lflang.diagram.synthesis.action.CollapseAllReactorsAction) LayeredOptions(org.eclipse.elk.alg.layered.options.LayeredOptions) KEdgeExtensions(de.cau.cs.kieler.klighd.krendering.extensions.KEdgeExtensions) KContainerRenderingExtensions(de.cau.cs.kieler.klighd.krendering.extensions.KContainerRenderingExtensions) KRenderingExtensions(de.cau.cs.kieler.klighd.krendering.extensions.KRenderingExtensions) HashMultimap(com.google.common.collect.HashMultimap) KPolyline(de.cau.cs.kieler.klighd.krendering.KPolyline) LineStyle(de.cau.cs.kieler.klighd.krendering.LineStyle) Map(java.util.Map) TriggerInstance(org.lflang.generator.TriggerInstance) ReactorIcons(org.lflang.diagram.synthesis.util.ReactorIcons) Connection(org.lflang.lf.Connection) EnumSet(java.util.EnumSet) KEdge(de.cau.cs.kieler.klighd.kgraph.KEdge) KPolylineExtensions(de.cau.cs.kieler.klighd.krendering.extensions.KPolylineExtensions) KPortExtensions(de.cau.cs.kieler.klighd.krendering.extensions.KPortExtensions) NamedInstanceUtil(org.lflang.diagram.synthesis.util.NamedInstanceUtil) SynthesisOption(de.cau.cs.kieler.klighd.SynthesisOption) Collection(java.util.Collection) Set(java.util.Set) SizeConstraint(org.eclipse.elk.core.options.SizeConstraint) EObject(org.eclipse.emf.ecore.EObject) LinguaFrancaShapeExtensions(org.lflang.diagram.synthesis.styles.LinguaFrancaShapeExtensions) BoxLayouterOptions(org.eclipse.elk.core.options.BoxLayouterOptions) List(java.util.List) InterfaceDependenciesVisualization(org.lflang.diagram.synthesis.util.InterfaceDependenciesVisualization) KlighdProperties(de.cau.cs.kieler.klighd.util.KlighdProperties) Direction(org.eclipse.elk.core.options.Direction) UtilityExtensions(org.lflang.diagram.synthesis.util.UtilityExtensions) KLabel(de.cau.cs.kieler.klighd.kgraph.KLabel) KStyle(de.cau.cs.kieler.klighd.krendering.KStyle) Pair(org.eclipse.xtext.xbase.lib.Pair) StringExtensions(org.eclipse.xtext.xbase.lib.StringExtensions) AbstractDiagramSynthesis(de.cau.cs.kieler.klighd.syntheses.AbstractDiagramSynthesis) FileConfig(org.lflang.FileConfig) ASTUtils(org.lflang.ASTUtils) Iterables(com.google.common.collect.Iterables) KNodeExtensions(de.cau.cs.kieler.klighd.krendering.extensions.KNodeExtensions) HashMap(java.util.HashMap) Multimap(com.google.common.collect.Multimap) ListExtensions(org.eclipse.xtext.xbase.lib.ListExtensions) ModeDiagrams(org.lflang.diagram.synthesis.util.ModeDiagrams) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) Inject(javax.inject.Inject) EdgeStraighteningStrategy(org.eclipse.elk.alg.layered.options.EdgeStraighteningStrategy) ShowCycleAction(org.lflang.diagram.synthesis.action.ShowCycleAction) ElkPadding(org.eclipse.elk.core.math.ElkPadding) KRendering(de.cau.cs.kieler.klighd.krendering.KRendering) CycleVisualization(org.lflang.diagram.synthesis.util.CycleVisualization) TimerInstance(org.lflang.generator.TimerInstance) LinkedList(java.util.LinkedList) SynthesisErrorReporter(org.lflang.diagram.synthesis.util.SynthesisErrorReporter) KText(de.cau.cs.kieler.klighd.krendering.KText) FixedAlignment(org.eclipse.elk.alg.layered.options.FixedAlignment) FilterCycleAction(org.lflang.diagram.synthesis.action.FilterCycleAction) KNode(de.cau.cs.kieler.klighd.kgraph.KNode) KPort(de.cau.cs.kieler.klighd.kgraph.KPort) KRoundedRectangle(de.cau.cs.kieler.klighd.krendering.KRoundedRectangle) RuntimeRange(org.lflang.generator.RuntimeRange) Model(org.lflang.lf.Model) PortConstraints(org.eclipse.elk.core.options.PortConstraints) Property(org.eclipse.elk.graph.properties.Property) Conversions(org.eclipse.xtext.xbase.lib.Conversions) KVector(org.eclipse.elk.core.math.KVector) EcoreUtil(org.eclipse.emf.ecore.util.EcoreUtil) KContainerRendering(de.cau.cs.kieler.klighd.krendering.KContainerRendering) PortInstance(org.lflang.generator.PortInstance) ReactionInstance(org.lflang.generator.ReactionInstance) ParameterInstance(org.lflang.generator.ParameterInstance) SendRange(org.lflang.generator.SendRange) ActionInstance(org.lflang.generator.ActionInstance) LayerConstraint(org.eclipse.elk.alg.layered.options.LayerConstraint) ReactorInstance(org.lflang.generator.ReactorInstance) IterableExtensions(org.eclipse.xtext.xbase.lib.IterableExtensions) ReactorFigureComponents(org.lflang.diagram.synthesis.styles.ReactorFigureComponents) DisplayedActionData(de.cau.cs.kieler.klighd.DisplayedActionData) ViewSynthesisShared(de.cau.cs.kieler.klighd.krendering.ViewSynthesisShared) KRectangle(de.cau.cs.kieler.klighd.krendering.KRectangle) Reactor(org.lflang.lf.Reactor) Colors(de.cau.cs.kieler.klighd.krendering.Colors) HorizontalAlignment(de.cau.cs.kieler.klighd.krendering.HorizontalAlignment) Table(com.google.common.collect.Table) KStyle(de.cau.cs.kieler.klighd.krendering.KStyle) KEdge(de.cau.cs.kieler.klighd.kgraph.KEdge) KPort(de.cau.cs.kieler.klighd.kgraph.KPort) KNode(de.cau.cs.kieler.klighd.kgraph.KNode) KRectangle(de.cau.cs.kieler.klighd.krendering.KRectangle) KText(de.cau.cs.kieler.klighd.krendering.KText) KRendering(de.cau.cs.kieler.klighd.krendering.KRendering) EcoreUtil(org.eclipse.emf.ecore.util.EcoreUtil)

Example 13 with KEdge

use of de.cau.cs.kieler.klighd.kgraph.KEdge in project lingua-franca by lf-lang.

the class LinguaFrancaSynthesis method createUserComments.

private Iterable<KNode> createUserComments(EObject element, KNode targetNode) {
    if (getBooleanValue(SHOW_USER_LABELS)) {
        String commentText = ASTUtils.findAnnotationInComments(element, "@label");
        if (!StringExtensions.isNullOrEmpty(commentText)) {
            KNode comment = _kNodeExtensions.createNode();
            setLayoutOption(comment, CoreOptions.COMMENT_BOX, true);
            KRoundedRectangle commentFigure = _linguaFrancaShapeExtensions.addCommentFigure(comment, commentText);
            _linguaFrancaStyleExtensions.commentStyle(commentFigure);
            // connect
            KEdge edge = _kEdgeExtensions.createEdge();
            edge.setSource(comment);
            edge.setTarget(targetNode);
            _linguaFrancaStyleExtensions.commentStyle(_linguaFrancaShapeExtensions.addCommentPolyline(edge));
            return List.of(comment);
        }
    }
    return List.of();
}
Also used : KEdge(de.cau.cs.kieler.klighd.kgraph.KEdge) KNode(de.cau.cs.kieler.klighd.kgraph.KNode) KRoundedRectangle(de.cau.cs.kieler.klighd.krendering.KRoundedRectangle)

Example 14 with KEdge

use of de.cau.cs.kieler.klighd.kgraph.KEdge in project lingua-franca by lf-lang.

the class FilterCycleAction method filterCycle.

public void filterCycle(KNode root) {
    Predicate<KNode> knodeNotInCycle = it -> {
        return !it.getProperty(CycleVisualization.DEPENDENCY_CYCLE);
    };
    Predicate<KEdge> kedgeNotInCycle = it -> {
        return !it.getProperty(CycleVisualization.DEPENDENCY_CYCLE);
    };
    root.getChildren().removeIf(knodeNotInCycle);
    for (KNode node : root.getChildren()) {
        node.getOutgoingEdges().removeIf(kedgeNotInCycle);
        this.filterCycle(node);
    }
}
Also used : KEdge(de.cau.cs.kieler.klighd.kgraph.KEdge) KNode(de.cau.cs.kieler.klighd.kgraph.KNode) Iterables(com.google.common.collect.Iterables) Iterator(java.util.Iterator) Property(org.eclipse.elk.graph.properties.Property) Predicate(java.util.function.Predicate) ListExtensions(org.eclipse.xtext.xbase.lib.ListExtensions) Iterators(com.google.common.collect.Iterators) IteratorExtensions(org.eclipse.xtext.xbase.lib.IteratorExtensions) List(java.util.List) IterableExtensions(org.eclipse.xtext.xbase.lib.IterableExtensions) IAction(de.cau.cs.kieler.klighd.IAction) LinguaFrancaSynthesis(org.lflang.diagram.synthesis.LinguaFrancaSynthesis) ViewContext(de.cau.cs.kieler.klighd.ViewContext) CycleVisualization(org.lflang.diagram.synthesis.util.CycleVisualization) KText(de.cau.cs.kieler.klighd.krendering.KText) WeakHashMap(java.util.WeakHashMap) Function1(org.eclipse.xtext.xbase.lib.Functions.Function1) KEdge(de.cau.cs.kieler.klighd.kgraph.KEdge) KNode(de.cau.cs.kieler.klighd.kgraph.KNode)

Example 15 with KEdge

use of de.cau.cs.kieler.klighd.kgraph.KEdge in project lingua-franca by lf-lang.

the class ModeDiagrams method handleModes.

public void handleModes(List<KNode> nodes, ReactorInstance reactor) {
    if (!reactor.modes.isEmpty()) {
        var modeNodes = new LinkedHashMap<ModeInstance, KNode>();
        var modeDefinitionMap = new LinkedHashMap<Mode, ModeInstance>();
        for (ModeInstance mode : reactor.modes) {
            var node = _kNodeExtensions.createNode();
            associateWith(node, mode.getDefinition());
            NamedInstanceUtil.linkInstance(node, mode);
            _utilityExtensions.setID(node, mode.uniqueID());
            modeNodes.put(mode, node);
            modeDefinitionMap.put(mode.getDefinition(), mode);
            if (mode.isInitial()) {
                DiagramSyntheses.setLayoutOption(node, LayeredOptions.LAYERING_LAYER_CONSTRAINT, LayerConstraint.FIRST);
            }
            DiagramSyntheses.setLayoutOption(node, LayeredOptions.CROSSING_MINIMIZATION_SEMI_INTERACTIVE, true);
            var expansionState = MemorizingExpandCollapseAction.getExpansionState(mode);
            DiagramSyntheses.setLayoutOption(node, KlighdProperties.EXPAND, expansionState != null ? expansionState : !this.getBooleanValue(INITIALLY_COLLAPSE_MODES));
            // Expanded Rectangle
            var expandFigure = addModeFigure(node, mode, true);
            expandFigure.setProperty(KlighdProperties.EXPANDED_RENDERING, true);
            _kRenderingExtensions.addDoubleClickAction(expandFigure, MemorizingExpandCollapseAction.ID);
            if (getBooleanValue(LinguaFrancaSynthesis.SHOW_HYPERLINKS)) {
                // Collapse button
                KText textButton = _linguaFrancaShapeExtensions.addTextButton(expandFigure, LinguaFrancaSynthesis.TEXT_HIDE_ACTION);
                _kRenderingExtensions.to(_kRenderingExtensions.from(_kRenderingExtensions.setGridPlacementData(textButton), _kRenderingExtensions.LEFT, 8, 0, _kRenderingExtensions.TOP, 0, 0), _kRenderingExtensions.RIGHT, 8, 0, _kRenderingExtensions.BOTTOM, 0, 0);
                _kRenderingExtensions.addSingleClickAction(textButton, MemorizingExpandCollapseAction.ID);
                _kRenderingExtensions.addDoubleClickAction(textButton, MemorizingExpandCollapseAction.ID);
            }
            _kContainerRenderingExtensions.addChildArea(expandFigure);
            // Collapse Rectangle
            var collapseFigure = addModeFigure(node, mode, false);
            collapseFigure.setProperty(KlighdProperties.COLLAPSED_RENDERING, true);
            if (this.hasContent(mode)) {
                _kRenderingExtensions.addDoubleClickAction(collapseFigure, MemorizingExpandCollapseAction.ID);
                if (getBooleanValue(LinguaFrancaSynthesis.SHOW_HYPERLINKS)) {
                    // Expand button
                    KText textButton = _linguaFrancaShapeExtensions.addTextButton(collapseFigure, LinguaFrancaSynthesis.TEXT_SHOW_ACTION);
                    _kRenderingExtensions.to(_kRenderingExtensions.from(_kRenderingExtensions.setGridPlacementData(textButton), _kRenderingExtensions.LEFT, 8, 0, _kRenderingExtensions.TOP, 0, 0), _kRenderingExtensions.RIGHT, 8, 0, _kRenderingExtensions.BOTTOM, 8, 0);
                    _kRenderingExtensions.addSingleClickAction(textButton, MemorizingExpandCollapseAction.ID);
                    _kRenderingExtensions.addDoubleClickAction(textButton, MemorizingExpandCollapseAction.ID);
                }
            }
        }
        var modeChildren = HashMultimap.<ModeInstance, KNode>create();
        var nodeModes = new HashMap<KNode, ModeInstance>();
        for (var node : nodes) {
            var instance = NamedInstanceUtil.getLinkedInstance(node);
            if (instance == null && node.getProperty(CoreOptions.COMMENT_BOX)) {
                var firstEdge = IterableExtensions.<KEdge>head(node.getOutgoingEdges());
                if (firstEdge != null && firstEdge.getTarget() != null) {
                    instance = NamedInstanceUtil.getLinkedInstance(firstEdge.getTarget());
                }
            }
            if (instance != null) {
                var mode = instance.getMode(true);
                modeChildren.put(mode, node);
                nodeModes.put(node, mode);
            } else {
                modeChildren.put(null, node);
            }
        }
        var modeContainer = _kNodeExtensions.createNode();
        modeContainer.getChildren().addAll(modeNodes.values());
        var fig = addModeContainerFigure(modeContainer);
        _kRenderingExtensions.addDoubleClickAction(fig, MemorizingExpandCollapseAction.ID);
        if (modeChildren.get(null).isEmpty()) {
            _kRenderingExtensions.setInvisible(fig, true);
            DiagramSyntheses.setLayoutOption(modeContainer, CoreOptions.PADDING, new ElkPadding());
        }
        DiagramSyntheses.setLayoutOption(modeContainer, CoreOptions.NODE_SIZE_CONSTRAINTS, SizeConstraint.minimumSizeWithPorts());
        DiagramSyntheses.setLayoutOption(modeContainer, CoreOptions.EDGE_ROUTING, EdgeRouting.SPLINES);
        DiagramSyntheses.setLayoutOption(modeContainer, CoreOptions.DIRECTION, Direction.DOWN);
        DiagramSyntheses.setLayoutOption(modeContainer, CoreOptions.PORT_CONSTRAINTS, PortConstraints.FIXED_ORDER);
        var modeContainerPorts = new HashMap<KPort, KPort>();
        for (var mode : ListExtensions.reverseView(reactor.modes)) {
            var modeNode = modeNodes.get(mode);
            var edges = new HashSet<KEdge>();
            // add children
            for (var child : modeChildren.get(mode)) {
                nodes.remove(child);
                modeNode.getChildren().add(child);
                edges.addAll(child.getIncomingEdges());
                edges.addAll(child.getOutgoingEdges());
            }
            // add transitions
            var representedTargets = new HashSet<Pair<ModeInstance, ModeInstance.ModeTransitionType>>();
            for (var transition : ListExtensions.reverseView(mode.transitions)) {
                if (!representedTargets.contains(new Pair<ModeInstance, ModeInstance.ModeTransitionType>(transition.target, transition.type))) {
                    var edge = _kEdgeExtensions.createEdge();
                    edge.setSource(modeNode);
                    edge.setTarget(modeNodes.get(transition.target));
                    addTransitionFigure(edge, transition);
                    if (getBooleanValue(SHOW_TRANSITION_LABELS)) {
                        associateWith(edge, transition.getDefinition());
                    } else {
                        // Bundle similar transitions
                        representedTargets.add(new Pair<ModeInstance, ModeInstance.ModeTransitionType>(transition.target, transition.type));
                    }
                }
            }
            // handle cross hierarchy edges
            var portCopies = new HashMap<KPort, KPort>();
            for (var edge : edges) {
                if (!edge.getProperty(CoreOptions.NO_LAYOUT)) {
                    var sourceNodeMode = nodeModes.get(edge.getSource());
                    if (sourceNodeMode == null) {
                        sourceNodeMode = nodeModes.get(edge.getSource().getParent());
                    }
                    var sourceIsInMode = sourceNodeMode != null;
                    var targetNodeMode = nodeModes.get(edge.getTarget());
                    if (targetNodeMode == null) {
                        targetNodeMode = nodeModes.get(edge.getTarget().getParent());
                    }
                    var targetIsInMode = targetNodeMode != null;
                    if (!sourceIsInMode || !targetIsInMode) {
                        var node = sourceIsInMode ? edge.getTarget() : edge.getSource();
                        var port = sourceIsInMode ? edge.getTargetPort() : edge.getSourcePort();
                        var isLocal = modeChildren.get(null).contains(node);
                        if (isLocal) {
                            // Add port to mode container
                            if (modeContainerPorts.containsKey(port)) {
                                node = modeContainer;
                                port = modeContainerPorts.get(port);
                            } else {
                                var containerPort = _kPortExtensions.createPort();
                                modeContainerPorts.put(port, containerPort);
                                modeContainer.getPorts().add(containerPort);
                                _kPortExtensions.setPortSize(containerPort, 8, 4);
                                KRectangle rect = _kRenderingExtensions.addRectangle(containerPort);
                                _kRenderingExtensions.setBackground(rect, Colors.BLACK);
                                DiagramSyntheses.setLayoutOption(containerPort, CoreOptions.PORT_BORDER_OFFSET, -4.0);
                                DiagramSyntheses.setLayoutOption(containerPort, CoreOptions.PORT_SIDE, sourceIsInMode ? PortSide.EAST : PortSide.WEST);
                                var source = _utilityExtensions.sourceElement(node);
                                var label = "";
                                if (source instanceof Action) {
                                    label = ((Action) source).getName();
                                } else if (source instanceof Timer) {
                                    label = ((Timer) source).getName();
                                }
                                _kLabelExtensions.addOutsidePortLabel(containerPort, label, 8);
                                // new connection
                                var copy = EcoreUtil.copy(edge);
                                if (sourceIsInMode) {
                                    copy.setSource(modeContainer);
                                    copy.setSourcePort(containerPort);
                                    copy.setTarget(edge.getTarget());
                                } else {
                                    copy.setTarget(modeContainer);
                                    copy.setTargetPort(containerPort);
                                    copy.setSource(edge.getSource());
                                }
                                node = modeContainer;
                                port = containerPort;
                            }
                        }
                        // Duplicate port
                        if (!portCopies.containsKey(port)) {
                            var copy = EcoreUtil.copy(port);
                            portCopies.put(port, copy);
                            var dummyNode = _kNodeExtensions.createNode();
                            var newID = mode.uniqueID() + "_";
                            if (!port.getLabels().isEmpty()) {
                                newID += IterableExtensions.head(port.getLabels()).getText();
                            }
                            _utilityExtensions.setID(dummyNode, newID);
                            _kRenderingExtensions.addInvisibleContainerRendering(dummyNode);
                            dummyNode.getPorts().add(copy);
                            DiagramSyntheses.setLayoutOption(dummyNode, LayeredOptions.LAYERING_LAYER_CONSTRAINT, port.getProperty(CoreOptions.PORT_SIDE) == PortSide.WEST ? LayerConstraint.FIRST : LayerConstraint.LAST);
                            modeNode.getChildren().add(dummyNode);
                        }
                        var newPort = portCopies.get(port);
                        if (sourceIsInMode) {
                            edge.setTarget(newPort.getNode());
                            edge.setTargetPort(newPort);
                        } else {
                            edge.setSource(newPort.getNode());
                            edge.setSourcePort(newPort);
                        }
                    }
                }
            }
        }
        nodes.add(modeContainer);
    }
}
Also used : ModeInstance(org.lflang.generator.ModeInstance) MemorizingExpandCollapseAction(org.lflang.diagram.synthesis.action.MemorizingExpandCollapseAction) Action(org.lflang.lf.Action) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) KEdge(de.cau.cs.kieler.klighd.kgraph.KEdge) KNode(de.cau.cs.kieler.klighd.kgraph.KNode) LinkedHashMap(java.util.LinkedHashMap) KRectangle(de.cau.cs.kieler.klighd.krendering.KRectangle) KText(de.cau.cs.kieler.klighd.krendering.KText) Timer(org.lflang.lf.Timer) ElkPadding(org.eclipse.elk.core.math.ElkPadding) HashSet(java.util.HashSet) ModeTransitionType(org.lflang.generator.ModeInstance.ModeTransitionType) Pair(org.eclipse.xtext.xbase.lib.Pair)

Aggregations

KEdge (de.cau.cs.kieler.klighd.kgraph.KEdge)15 KNode (de.cau.cs.kieler.klighd.kgraph.KNode)8 KPolyline (de.cau.cs.kieler.klighd.krendering.KPolyline)6 KPort (de.cau.cs.kieler.klighd.kgraph.KPort)5 HashMap (java.util.HashMap)4 KRendering (de.cau.cs.kieler.klighd.krendering.KRendering)3 KRoundedRectangle (de.cau.cs.kieler.klighd.krendering.KRoundedRectangle)3 KText (de.cau.cs.kieler.klighd.krendering.KText)3 HashSet (java.util.HashSet)3 ElkPadding (org.eclipse.elk.core.math.ElkPadding)3 ReactorInstance (org.lflang.generator.ReactorInstance)3 Iterables (com.google.common.collect.Iterables)2 KLabel (de.cau.cs.kieler.klighd.kgraph.KLabel)2 KRectangle (de.cau.cs.kieler.klighd.krendering.KRectangle)2 ArrayList (java.util.ArrayList)2 List (java.util.List)2 LayerConstraint (org.eclipse.elk.alg.layered.options.LayerConstraint)2 SizeConstraint (org.eclipse.elk.core.options.SizeConstraint)2 Property (org.eclipse.elk.graph.properties.Property)2 IterableExtensions (org.eclipse.xtext.xbase.lib.IterableExtensions)2