use of de.cau.cs.kieler.klighd.kgraph.KNode in project lingua-franca by lf-lang.
the class LinguaFrancaShapeExtensions method addReactorFigure.
/**
* Creates the visual representation of a reactor node
*/
public ReactorFigureComponents addReactorFigure(KNode node, ReactorInstance reactorInstance, String text) {
int padding = getBooleanValue(LinguaFrancaSynthesis.SHOW_HYPERLINKS) ? 8 : 6;
Function1<KRoundedRectangle, KRendering> style = r -> {
_kRenderingExtensions.setLineWidth(r, 1);
_kRenderingExtensions.setForeground(r, Colors.GRAY);
_kRenderingExtensions.setBackground(r, Colors.GRAY_95);
return _linguaFrancaStyleExtensions.boldLineSelectionStyle(r);
};
KRoundedRectangle figure = _kRenderingExtensions.addRoundedRectangle(node, 8, 8, 1);
_kContainerRenderingExtensions.setGridPlacement(figure, 1);
style.apply(figure);
figure.setProperty(REACTOR_CONTENT_CONTAINER, true);
// minimal node size is necessary if no text will be added
List<Float> minSize = List.of(2 * figure.getCornerWidth(), 2 * figure.getCornerHeight());
_kNodeExtensions.setMinimalNodeSize(node, minSize.get(0), minSize.get(1));
// Add parent container
KRectangle parentContainer = _kContainerRenderingExtensions.addRectangle(figure);
_kRenderingExtensions.setInvisible(parentContainer, true);
setGridPlacementDataFromPointToPoint(parentContainer, LEFT, padding, 0, TOP, padding, 0, RIGHT, padding, 0, BOTTOM, _utilityExtensions.hasContent(reactorInstance) ? 4 : padding, 0);
// Add centered child container
KRectangle childContainer = _kContainerRenderingExtensions.addRectangle(parentContainer);
_kRenderingExtensions.setInvisible(childContainer, true);
_kRenderingExtensions.setPointPlacementData(childContainer, _kRenderingExtensions.LEFT, 0, 0.5f, _kRenderingExtensions.TOP, 0, 0.5f, _kRenderingExtensions.H_CENTRAL, _kRenderingExtensions.V_CENTRAL, 0, 0, 0, 0);
KGridPlacement placement = _kContainerRenderingExtensions.setGridPlacement(childContainer, 1);
KText childText = _kContainerRenderingExtensions.addText(childContainer, text);
DiagramSyntheses.suppressSelectability(childText);
_linguaFrancaStyleExtensions.underlineSelectionStyle(childText);
if (!_utilityExtensions.isRoot(reactorInstance) && reactorInstance.getDefinition().getHost() != null) {
KRendering cloudUploadIcon = _linguaFrancaStyleExtensions.addCloudUploadIcon(childContainer);
setGridPlacementDataFromPointToPoint(cloudUploadIcon, LEFT, 3, 0, TOP, 0, 0, RIGHT, 0, 0, BOTTOM, 0, 0);
placement.setNumColumns(2);
if (getBooleanValue(LinguaFrancaSynthesis.SHOW_REACTOR_HOST)) {
KText reactorHostText = _kContainerRenderingExtensions.addText(childContainer, _utilityExtensions.toText(reactorInstance.getDefinition().getHost()));
DiagramSyntheses.suppressSelectability(reactorHostText);
_linguaFrancaStyleExtensions.underlineSelectionStyle(reactorHostText);
setGridPlacementDataFromPointToPoint(reactorHostText, LEFT, 3, 0, TOP, 0, 0, RIGHT, 0, 0, BOTTOM, 0, 0);
placement.setNumColumns(3);
}
}
if (reactorInstance.isBank()) {
List<KRendering> bank = new ArrayList<>();
KContainerRendering container = _kRenderingExtensions.addInvisibleContainerRendering(node);
// TODO handle unresolved width
KRoundedRectangle banks;
banks = _kContainerRenderingExtensions.addRoundedRectangle(container, 8, 8, 1);
style.apply(banks);
setGridPlacementDataFromPointToPoint(banks, LEFT, BANK_FIGURE_X_OFFSET_SUM, 0, TOP, BANK_FIGURE_Y_OFFSET_SUM, 0, RIGHT, 0, 0, BOTTOM, 0, 0);
if (reactorInstance.getWidth() == 3) {
banks = _kContainerRenderingExtensions.addRoundedRectangle(container, 8, 8, 1);
style.apply(banks);
setGridPlacementDataFromPointToPoint(banks, LEFT, BANK_FIGURE_X_OFFSET_SUM / 2, 0, TOP, BANK_FIGURE_Y_OFFSET_SUM / 2, 0, RIGHT, BANK_FIGURE_X_OFFSET_SUM / 2, 0, BOTTOM, BANK_FIGURE_Y_OFFSET_SUM / 2, 0);
} else if (reactorInstance.getWidth() != 2 && reactorInstance.getWidth() != 3) {
banks = _kContainerRenderingExtensions.addRoundedRectangle(container, 8, 8, 1);
style.apply(banks);
setGridPlacementDataFromPointToPoint(banks, LEFT, 2 * BANK_FIGURE_X_OFFSET_SUM / 3, 0, TOP, 2 * BANK_FIGURE_Y_OFFSET_SUM / 3, 0, RIGHT, BANK_FIGURE_X_OFFSET_SUM / 3, 0, BOTTOM, BANK_FIGURE_Y_OFFSET_SUM / 3, 0);
banks = _kContainerRenderingExtensions.addRoundedRectangle(container, 8, 8, 1);
style.apply(banks);
setGridPlacementDataFromPointToPoint(banks, LEFT, BANK_FIGURE_X_OFFSET_SUM / 3, 0, TOP, BANK_FIGURE_Y_OFFSET_SUM / 3, 0, RIGHT, 2 * BANK_FIGURE_X_OFFSET_SUM / 3, 0, BOTTOM, 2 * BANK_FIGURE_Y_OFFSET_SUM / 3, 0);
}
container.getChildren().add(figure);
setGridPlacementDataFromPointToPoint(figure, LEFT, 0, 0, TOP, 0, 0, RIGHT, BANK_FIGURE_X_OFFSET_SUM, 0, BOTTOM, BANK_FIGURE_Y_OFFSET_SUM, 0);
bank.addAll(container.getChildren());
KRectangle widthLabelContainer = _kContainerRenderingExtensions.addRectangle(container);
_kRenderingExtensions.setInvisible(widthLabelContainer, true);
setGridPlacementDataFromPointToPoint(widthLabelContainer, LEFT, 12, 0, BOTTOM, 9, 0, RIGHT, 6, 0, BOTTOM, 0.5f, 0);
// Handle unresolved width.
String widthLabel = reactorInstance.getWidth() >= 0 ? Integer.toString(reactorInstance.getWidth()) : "?";
KText widthLabelText = _kContainerRenderingExtensions.addText(widthLabelContainer, widthLabel);
_kRenderingExtensions.setHorizontalAlignment(widthLabelText, HorizontalAlignment.LEFT);
_kRenderingExtensions.setVerticalAlignment(widthLabelText, VerticalAlignment.BOTTOM);
_kRenderingExtensions.setFontSize(widthLabelText, 6);
_linguaFrancaStyleExtensions.noSelectionStyle(widthLabelText);
associateWith(widthLabelText, reactorInstance.getDefinition().getWidthSpec());
return new ReactorFigureComponents(container, figure, bank);
} else {
return new ReactorFigureComponents(figure, figure, List.of(figure));
}
}
use of de.cau.cs.kieler.klighd.kgraph.KNode in project lingua-franca by lf-lang.
the class InterfaceDependenciesVisualization method addInterfaceDependencies.
/**
* Adds interface dependencies to the node if this option is active.
* Visibility will be adjusted based on expansion state.
*/
public Spacing addInterfaceDependencies(KNode node, boolean expanded) {
Spacing marginInit = null;
if (getBooleanValue(SHOW_INTERFACE_DEPENDENCIES)) {
List<Pair<KPort, KPort>> deps = getPortDependencies(node);
if (!deps.isEmpty()) {
for (Pair<KPort, KPort> pair : deps) {
createDependencyEdge(pair, expanded);
}
// Fix content (label) of collapsed rendering
KContainerRendering contentContainer = IterableExtensions.findFirst(Iterables.filter(node.getData(), KContainerRendering.class), it -> {
return it.getProperty(KlighdProperties.COLLAPSED_RENDERING);
});
if (contentContainer != null) {
if (!contentContainer.getProperty(LinguaFrancaShapeExtensions.REACTOR_CONTENT_CONTAINER)) {
contentContainer = IteratorExtensions.findFirst(Iterators.filter(contentContainer.eAllContents(), KContainerRendering.class), it -> {
return it.getProperty(LinguaFrancaShapeExtensions.REACTOR_CONTENT_CONTAINER);
});
}
if (contentContainer != null) {
List<KRendering> content = ImmutableList.copyOf(contentContainer.getChildren());
// Put into two new containers such that they are not centered/maximized
KRectangle firstContainer = _kContainerRenderingExtensions.addRectangle(contentContainer);
_kRenderingExtensions.setInvisible(firstContainer, true);
KRectangle secondContainer = _kContainerRenderingExtensions.addRectangle(firstContainer);
_kRenderingExtensions.setInvisible(secondContainer, true);
_kContainerRenderingExtensions.setGridPlacement(secondContainer, 1);
Iterables.addAll(secondContainer.getChildren(), content);
_kRenderingExtensions.setPointPlacementData(secondContainer, _kRenderingExtensions.LEFT, 0, 0.5f, _kRenderingExtensions.TOP, 0, 0, _kRenderingExtensions.H_CENTRAL, _kRenderingExtensions.V_TOP, 0, 0, 0, 0);
// Adjust ports separate dependency edges from label/content
if (content.size() > 0) {
marginInit = _utilityExtensions.getPortMarginsInitIfAbsent(node).add(new ElkMargin((content.size() * 20) - 8, 0, 0, 0));
}
}
}
}
}
return marginInit;
}
use of de.cau.cs.kieler.klighd.kgraph.KNode in project lingua-franca by lf-lang.
the class InterfaceDependenciesVisualization method getPortDependencies.
/**
* Find dependencies between ports.
*/
private List<Pair<KPort, KPort>> getPortDependencies(KNode node) {
Set<KPort> inputPorts = IterableExtensions.toSet(IterableExtensions.filter(node.getPorts(), it -> {
return it.getProperty(LinguaFrancaSynthesis.REACTOR_INPUT);
}));
Set<KPort> outputPorts = IterableExtensions.toSet(IterableExtensions.filter(node.getPorts(), it -> {
return it.getProperty(LinguaFrancaSynthesis.REACTOR_OUTPUT);
}));
// FIXME Replace with real logic
Random rand = new Random();
return IterableExtensions.toList(IterableExtensions.map(IterableExtensions.filter(Sets.cartesianProduct(inputPorts, outputPorts), it -> {
return rand.nextBoolean();
}), it -> {
return new Pair<KPort, KPort>(it.get(0), it.get(1));
}));
}
use of de.cau.cs.kieler.klighd.kgraph.KNode in project lingua-franca by lf-lang.
the class LinguaFrancaSynthesis method transformReactorNetwork.
private Collection<KNode> transformReactorNetwork(ReactorInstance reactorInstance, Map<PortInstance, KPort> parentInputPorts, Map<PortInstance, KPort> parentOutputPorts, Map<ReactorInstance, KNode> allReactorNodes) {
List<KNode> nodes = new ArrayList<>();
Table<ReactorInstance, PortInstance, KPort> inputPorts = HashBasedTable.create();
Table<ReactorInstance, PortInstance, KPort> outputPorts = HashBasedTable.create();
Map<ReactionInstance, KNode> reactionNodes = new HashMap<>();
Map<KPort, KNode> directConnectionDummyNodes = new HashMap<>();
Multimap<ActionInstance, KPort> actionDestinations = HashMultimap.create();
Multimap<ActionInstance, KPort> actionSources = HashMultimap.create();
Map<TimerInstance, KNode> timerNodes = new HashMap<>();
KNode startupNode = _kNodeExtensions.createNode();
boolean startupUsed = false;
KNode shutdownNode = _kNodeExtensions.createNode();
boolean shutdownUsed = false;
// Transform instances
int index = 0;
for (ReactorInstance child : ListExtensions.reverseView(reactorInstance.children)) {
Boolean expansionState = MemorizingExpandCollapseAction.getExpansionState(child);
Collection<KNode> rNodes = createReactorNode(child, expansionState != null ? expansionState : false, inputPorts, outputPorts, allReactorNodes);
setLayoutOption(IterableExtensions.<KNode>head(rNodes), CoreOptions.PRIORITY, index);
nodes.addAll(rNodes);
index++;
}
// Create timers
for (TimerInstance timer : reactorInstance.timers) {
KNode node = associateWith(_kNodeExtensions.createNode(), timer.getDefinition());
NamedInstanceUtil.linkInstance(node, timer);
_utilityExtensions.setID(node, timer.uniqueID());
nodes.add(node);
Iterables.addAll(nodes, createUserComments(timer.getDefinition(), node));
timerNodes.put(timer, node);
_linguaFrancaShapeExtensions.addTimerFigure(node, timer);
}
// Create reactions
for (ReactionInstance reaction : ListExtensions.reverseView(reactorInstance.reactions)) {
int idx = reactorInstance.reactions.indexOf(reaction);
KNode node = associateWith(_kNodeExtensions.createNode(), reaction.getDefinition());
NamedInstanceUtil.linkInstance(node, reaction);
_utilityExtensions.setID(node, reaction.uniqueID());
nodes.add(node);
Iterables.addAll(nodes, createUserComments(reaction.getDefinition(), node));
reactionNodes.put(reaction, node);
setLayoutOption(node, CoreOptions.PORT_CONSTRAINTS, PortConstraints.FIXED_SIDE);
// always place with higher priority than reactor nodes
setLayoutOption(node, CoreOptions.PRIORITY, (reactorInstance.reactions.size() - idx) * 10);
// try order reactions vertically if in one layer
setLayoutOption(node, LayeredOptions.POSITION, new KVector(0, idx));
_linguaFrancaShapeExtensions.addReactionFigure(node, reaction);
// connect input
KPort port = null;
for (TriggerInstance<?> trigger : reaction.triggers) {
port = addInvisiblePort(node);
setLayoutOption(port, CoreOptions.PORT_SIDE, PortSide.WEST);
int triggersSize = reaction.triggers != null ? reaction.triggers.size() : 0;
int sourcesSize = reaction.sources != null ? reaction.sources.size() : 0;
if (getBooleanValue(REACTIONS_USE_HYPEREDGES) || triggersSize + sourcesSize == 1) {
// manual adjustment disabling automatic one
setLayoutOption(port, CoreOptions.PORT_BORDER_OFFSET, (double) -LinguaFrancaShapeExtensions.REACTION_POINTINESS);
}
if (trigger.isStartup()) {
connect(createDependencyEdge(((TriggerInstance.BuiltinTriggerVariable) trigger.getDefinition()).definition), startupNode, port);
startupUsed = true;
} else if (trigger.isShutdown()) {
connect(createDelayEdge(((TriggerInstance.BuiltinTriggerVariable) trigger.getDefinition()).definition), shutdownNode, port);
shutdownUsed = true;
} else if (trigger instanceof ActionInstance) {
actionDestinations.put(((ActionInstance) trigger), port);
} else if (trigger instanceof PortInstance) {
KPort src = null;
PortInstance triggerAsPort = (PortInstance) trigger;
if (triggerAsPort.getParent() == reactorInstance) {
src = parentInputPorts.get(trigger);
} else {
src = outputPorts.get(triggerAsPort.getParent(), trigger);
}
if (src != null) {
connect(createDependencyEdge(triggerAsPort.getDefinition()), src, port);
}
} else if (trigger instanceof TimerInstance) {
KNode src = timerNodes.get(trigger);
if (src != null) {
connect(createDependencyEdge(trigger.getDefinition()), src, port);
}
}
}
// port = null // create new ports
for (TriggerInstance<?> dep : reaction.sources) {
if (reaction.triggers.contains(dep))
continue;
if (!(getBooleanValue(REACTIONS_USE_HYPEREDGES) && port != null)) {
port = addInvisiblePort(node);
setLayoutOption(port, CoreOptions.PORT_SIDE, PortSide.WEST);
int triggersSize = reaction.triggers != null ? reaction.triggers.size() : 0;
int sourcesSize = reaction.sources != null ? reaction.sources.size() : 0;
if (getBooleanValue(REACTIONS_USE_HYPEREDGES) || triggersSize + sourcesSize == 1) {
// manual adjustment disabling automatic one
setLayoutOption(port, CoreOptions.PORT_BORDER_OFFSET, (double) -LinguaFrancaShapeExtensions.REACTION_POINTINESS);
}
}
if (dep instanceof PortInstance) {
KPort src = null;
PortInstance depAsPort = (PortInstance) dep;
if (dep.getParent() == reactorInstance) {
src = parentInputPorts.get(dep);
} else {
src = outputPorts.get(depAsPort.getParent(), dep);
}
if (src != null) {
connect(createDependencyEdge(dep.getDefinition()), src, port);
}
}
}
// connect outputs
// create new ports
port = null;
Set<TriggerInstance<?>> iterSet = reaction.effects != null ? reaction.effects : new HashSet<>();
for (TriggerInstance<?> effect : iterSet) {
port = addInvisiblePort(node);
setLayoutOption(port, CoreOptions.PORT_SIDE, PortSide.EAST);
if (effect instanceof ActionInstance) {
actionSources.put((ActionInstance) effect, port);
} else if (effect instanceof PortInstance) {
KPort dst = null;
PortInstance effectAsPort = (PortInstance) effect;
if (effectAsPort.isOutput()) {
dst = parentOutputPorts.get(effect);
} else {
dst = inputPorts.get(effectAsPort.getParent(), effect);
}
if (dst != null) {
connect(createDependencyEdge(effect), port, dst);
}
}
}
}
// Connect actions
Set<ActionInstance> actions = new HashSet<>();
actions.addAll(actionSources.keySet());
actions.addAll(actionDestinations.keySet());
for (ActionInstance action : actions) {
KNode node = associateWith(_kNodeExtensions.createNode(), action.getDefinition());
NamedInstanceUtil.linkInstance(node, action);
_utilityExtensions.setID(node, action.uniqueID());
nodes.add(node);
Iterables.addAll(nodes, createUserComments(action.getDefinition(), node));
setLayoutOption(node, CoreOptions.PORT_CONSTRAINTS, PortConstraints.FIXED_SIDE);
Pair<KPort, KPort> ports = _linguaFrancaShapeExtensions.addActionFigureAndPorts(node, action.isPhysical() ? "P" : "L");
// TODO handle variables?
if (action.getMinDelay() != null && action.getMinDelay() != ActionInstance.DEFAULT_MIN_DELAY) {
_kLabelExtensions.addOutsideBottomCenteredNodeLabel(node, String.format("min delay: %s", action.getMinDelay().toString()), 7);
}
// TODO default value?
if (action.getDefinition().getMinSpacing() != null) {
_kLabelExtensions.addOutsideBottomCenteredNodeLabel(node, String.format("min spacing: %s", action.getMinSpacing().toString()), 7);
}
if (!StringExtensions.isNullOrEmpty(action.getDefinition().getPolicy())) {
_kLabelExtensions.addOutsideBottomCenteredNodeLabel(node, String.format("policy: %s", action.getPolicy().toString()), 7);
}
// connect source
for (KPort source : actionSources.get(action)) {
connect(createDelayEdge(action), source, ports.getKey());
}
// connect targets
for (KPort target : actionDestinations.get(action)) {
connect(createDelayEdge(action), ports.getValue(), target);
}
}
// Transform connections.
// First, collect all the source ports.
List<PortInstance> sourcePorts = new LinkedList<>(reactorInstance.inputs);
for (ReactorInstance child : reactorInstance.children) {
sourcePorts.addAll(child.outputs);
}
for (PortInstance leftPort : sourcePorts) {
KPort source = leftPort.getParent() == reactorInstance ? parentInputPorts.get(leftPort) : outputPorts.get(leftPort.getParent(), leftPort);
for (SendRange sendRange : leftPort.getDependentPorts()) {
for (RuntimeRange<PortInstance> rightRange : sendRange.destinations) {
PortInstance rightPort = rightRange.instance;
KPort target = rightPort.getParent() == reactorInstance ? parentOutputPorts.get(rightPort) : inputPorts.get(rightPort.getParent(), rightPort);
// There should be a connection, but skip if not.
Connection connection = sendRange.connection;
if (connection != null) {
KEdge edge = createIODependencyEdge(connection, (leftPort.isMultiport() || rightPort.isMultiport()));
if (connection.getDelay() != null) {
KLabel delayLabel = _kLabelExtensions.addCenterEdgeLabel(edge, ASTUtils.toText(connection.getDelay()));
associateWith(delayLabel, connection.getDelay());
if (connection.isPhysical()) {
_linguaFrancaStyleExtensions.applyOnEdgePysicalDelayStyle(delayLabel, reactorInstance.isMainOrFederated() ? Colors.WHITE : Colors.GRAY_95);
} else {
_linguaFrancaStyleExtensions.applyOnEdgeDelayStyle(delayLabel);
}
} else if (connection.isPhysical()) {
KLabel physicalConnectionLabel = _kLabelExtensions.addCenterEdgeLabel(edge, "---");
_linguaFrancaStyleExtensions.applyOnEdgePysicalStyle(physicalConnectionLabel, reactorInstance.isMainOrFederated() ? Colors.WHITE : Colors.GRAY_95);
}
if (source != null && target != null) {
// check for inside loop (direct in -> out connection with delay)
if (parentInputPorts.values().contains(source) && parentOutputPorts.values().contains(target)) {
// edge.setLayoutOption(CoreOptions.INSIDE_SELF_LOOPS_YO, true) // Does not work as expected
// Introduce dummy node to enable direct connection (that is also hidden when collapsed)
KNode dummy = _kNodeExtensions.createNode();
if (directConnectionDummyNodes.containsKey(target)) {
dummy = directConnectionDummyNodes.get(target);
} else {
nodes.add(dummy);
directConnectionDummyNodes.put(target, dummy);
_kRenderingExtensions.addInvisibleContainerRendering(dummy);
_kNodeExtensions.setNodeSize(dummy, 0, 0);
KEdge extraEdge = createIODependencyEdge(null, (leftPort.isMultiport() || rightPort.isMultiport()));
connect(extraEdge, dummy, target);
}
connect(edge, source, dummy);
} else {
connect(edge, source, target);
}
}
}
}
}
}
// Add startup/shutdown
if (startupUsed) {
_linguaFrancaShapeExtensions.addStartupFigure(startupNode);
nodes.add(0, startupNode);
setLayoutOption(startupNode, LayeredOptions.LAYERING_LAYER_CONSTRAINT, LayerConstraint.FIRST);
if (getBooleanValue(REACTIONS_USE_HYPEREDGES)) {
KPort port = addInvisiblePort(startupNode);
startupNode.getOutgoingEdges().forEach(it -> {
it.setSourcePort(port);
});
}
}
if (shutdownUsed) {
_linguaFrancaShapeExtensions.addShutdownFigure(shutdownNode);
nodes.add(0, shutdownNode);
if (getBooleanValue(REACTIONS_USE_HYPEREDGES)) {
// connect all edges to one port
KPort port = addInvisiblePort(shutdownNode);
shutdownNode.getOutgoingEdges().forEach(it -> {
it.setSourcePort(port);
});
}
}
// Postprocess timer nodes
if (getBooleanValue(REACTIONS_USE_HYPEREDGES)) {
// connect all edges to one port
for (KNode timerNode : timerNodes.values()) {
KPort port = addInvisiblePort(timerNode);
timerNode.getOutgoingEdges().forEach(it -> {
it.setSourcePort(port);
});
}
}
// Add reaction order edges (add last to have them on top of other edges)
if (reactorInstance.reactions.size() > 1) {
KNode prevNode = reactionNodes.get(IterableExtensions.head(reactorInstance.reactions));
Iterable<KNode> iterList = IterableExtensions.map(IterableExtensions.drop(reactorInstance.reactions, 1), reactionNodes::get);
for (KNode node : iterList) {
KEdge edge = createOrderEdge();
edge.setSource(prevNode);
edge.setTarget(node);
edge.setProperty(CoreOptions.NO_LAYOUT, true);
// Do not remove them, as they are needed for cycle detection
KRendering edgeRendering = _kRenderingExtensions.getKRendering(edge);
_kRenderingExtensions.setInvisible(edgeRendering, !getBooleanValue(SHOW_REACTION_ORDER_EDGES));
_kRenderingExtensions.getInvisible(edgeRendering).setPropagateToChildren(true);
// TODO this does not work work with incremental update (https://github.com/kieler/KLighD/issues/37)
// if (!getBooleanValue(SHOW_REACTION_ORDER_EDGES)) edge.initiallyHide()
prevNode = node;
}
}
_modeDiagrams.handleModes(nodes, reactorInstance);
return nodes;
}
use of de.cau.cs.kieler.klighd.kgraph.KNode in project lingua-franca by lf-lang.
the class ShowCycleAction method execute.
@Override
public IAction.ActionResult execute(final IAction.ActionContext context) {
ViewContext vc = context.getViewContext();
// Collapse all
collapseAll.execute(context);
// Expand only errors
Iterator<KNode> knodes = ModelingUtil.eAllContentsOfType(vc.getViewModel(), KNode.class);
// Filter out nodes that are not in cycle or not a reactor
knodes = IteratorExtensions.filter(knodes, it -> {
return it.getProperty(CycleVisualization.DEPENDENCY_CYCLE) && sourceIsReactor(it);
});
// Remove duplicates
Set<KNode> cycleNodes = IteratorExtensions.toSet(knodes);
// Include parents
LinkedList<KNode> check = new LinkedList<>(cycleNodes);
while (!check.isEmpty()) {
KNode parent = check.pop().getParent();
if (parent != null && !cycleNodes.contains(parent)) {
cycleNodes.add(parent);
check.add(parent);
}
}
// Expand
for (KNode node : cycleNodes) {
MemorizingExpandCollapseAction.setExpansionState(node, NamedInstanceUtil.getLinkedInstance(node), vc.getViewer(), true);
}
return IAction.ActionResult.createResult(true);
}
Aggregations