use of de.cau.cs.kieler.klighd.kgraph.KEdge in project lingua-franca by lf-lang.
the class CycleVisualization method detectAndHighlightCycles.
/**
* Performs cycle detection based on the diagram's graph structure and applies given highlighting to the included elements
*/
public boolean detectAndHighlightCycles(ReactorInstance rootReactorInstance, Map<ReactorInstance, KNode> allReactorNodes, Consumer<KGraphElement> highlighter) {
if (rootReactorInstance.hasCycles() && highlighter != null) {
// Highlight cycles
// A cycle consists of reactions and ports.
HashMultimap<ReactorInstance, NamedInstance<?>> cycleElementsByReactor = HashMultimap.create();
Set<NamedInstance<?>> cycles = rootReactorInstance.getCycles();
for (NamedInstance<?> element : cycles) {
// First find the involved reactor instances
if (element instanceof ReactorInstance) {
cycleElementsByReactor.put((ReactorInstance) element, element);
} else {
cycleElementsByReactor.put(element.getParent(), element);
}
}
for (ReactorInstance reactor : cycleElementsByReactor.keySet()) {
KNode node = allReactorNodes.get(reactor);
if (node != null) {
node.setProperty(DEPENDENCY_CYCLE, true);
highlighter.accept(node);
Set<NamedInstance<?>> reactorContentInCycle = cycleElementsByReactor.get(reactor);
// Reactor edges
for (KEdge edge : node.getOutgoingEdges()) {
if (connectsCycleElements(edge, cycles)) {
edge.setProperty(DEPENDENCY_CYCLE, true);
highlighter.accept(edge);
}
}
// Reactor ports
for (KPort port : node.getPorts()) {
if (reactorContentInCycle.contains(NamedInstanceUtil.getLinkedInstance(port))) {
port.setProperty(DEPENDENCY_CYCLE, true);
highlighter.accept(port);
}
}
// Child Nodes
for (KNode childNode : node.getChildren()) {
if (reactorContentInCycle.contains(NamedInstanceUtil.getLinkedInstance(childNode)) && !_utilityExtensions.sourceIsReactor(childNode)) {
childNode.setProperty(DEPENDENCY_CYCLE, true);
highlighter.accept(childNode);
for (KEdge edge : childNode.getOutgoingEdges()) {
if (connectsCycleElements(edge, cycles)) {
edge.setProperty(DEPENDENCY_CYCLE, true);
highlighter.accept(edge);
}
}
}
}
}
}
return true;
}
return false;
}
use of de.cau.cs.kieler.klighd.kgraph.KEdge in project lingua-franca by lf-lang.
the class LinguaFrancaSynthesis method createIODependencyEdge.
private KEdge createIODependencyEdge(Object associate, boolean multiport) {
KEdge edge = _kEdgeExtensions.createEdge();
if (associate != null) {
associateWith(edge, associate);
}
KPolyline line = _kEdgeExtensions.addPolyline(edge);
_linguaFrancaStyleExtensions.boldLineSelectionStyle(line);
_kPolylineExtensions.addJunctionPointDecorator(line);
if (multiport) {
// Render multiport connections and bank connections in bold.
_kRenderingExtensions.setLineWidth(line, 2.2f);
_kRenderingExtensions.setLineCap(line, LineCap.CAP_SQUARE);
// Adjust junction point size
_kPolylineExtensions.setJunctionPointDecorator(line, line.getJunctionPointRendering(), 6, 6);
}
return edge;
}
use of de.cau.cs.kieler.klighd.kgraph.KEdge in project lingua-franca by lf-lang.
the class LinguaFrancaSynthesis method transform.
// -------------------------------------------------------------------------
@Override
public KNode transform(final Model model) {
KNode rootNode = _kNodeExtensions.createNode();
try {
// Find main
Reactor main = IterableExtensions.findFirst(model.getReactors(), _utilityExtensions::isMainOrFederated);
if (main != null) {
ReactorInstance reactorInstance = new ReactorInstance(main, new SynthesisErrorReporter());
rootNode.getChildren().addAll(createReactorNode(reactorInstance, true, null, null, new HashMap<>()));
} else {
KNode messageNode = _kNodeExtensions.createNode();
_linguaFrancaShapeExtensions.addErrorMessage(messageNode, TEXT_NO_MAIN_REACTOR, null);
rootNode.getChildren().add(messageNode);
}
// Show all reactors
if (main == null || getBooleanValue(SHOW_ALL_REACTORS)) {
List<KNode> reactorNodes = new ArrayList<>();
for (Reactor reactor : model.getReactors()) {
if (reactor == main)
continue;
ReactorInstance reactorInstance = new ReactorInstance(reactor, new SynthesisErrorReporter(), new HashSet<>());
reactorNodes.addAll(createReactorNode(reactorInstance, main == null, HashBasedTable.<ReactorInstance, PortInstance, KPort>create(), HashBasedTable.<ReactorInstance, PortInstance, KPort>create(), new HashMap<>()));
}
if (!reactorNodes.isEmpty()) {
// To allow ordering, we need box layout but we also need layered layout for ports thus wrap all node
// TODO use rect packing in the future
reactorNodes.add(0, IterableExtensions.head(rootNode.getChildren()));
int index = 0;
for (KNode node : reactorNodes) {
if (node.getProperty(CoreOptions.COMMENT_BOX))
continue;
KNode child = _kNodeExtensions.createNode();
child.getChildren().add(node);
// Add comment nodes
for (KEdge edge : node.getIncomingEdges()) {
if (!edge.getSource().getProperty(CoreOptions.COMMENT_BOX))
continue;
child.getChildren().add(edge.getSource());
}
_kRenderingExtensions.addInvisibleContainerRendering(child);
setLayoutOption(child, CoreOptions.ALGORITHM, LayeredOptions.ALGORITHM_ID);
setLayoutOption(child, CoreOptions.PADDING, new ElkPadding(0));
// Order!
setLayoutOption(child, CoreOptions.PRIORITY, reactorNodes.size() - index);
rootNode.getChildren().add(child);
index++;
}
setLayoutOption(rootNode, CoreOptions.ALGORITHM, BoxLayouterOptions.ALGORITHM_ID);
setLayoutOption(rootNode, CoreOptions.SPACING_NODE_NODE, 25.0);
}
}
} catch (Exception e) {
e.printStackTrace();
KNode messageNode = _kNodeExtensions.createNode();
_linguaFrancaShapeExtensions.addErrorMessage(messageNode, "Error in Diagram Synthesis", e.getClass().getSimpleName() + " occurred. Could not create diagram.");
rootNode.getChildren().add(messageNode);
}
return rootNode;
}
use of de.cau.cs.kieler.klighd.kgraph.KEdge in project lingua-franca by lf-lang.
the class ReactionPortAdjustment method adjustPositions.
public void adjustPositions(Iterable<Pair<Integer, KPort>> indexedPorts, int count, boolean input) {
float segments = LinguaFrancaShapeExtensions.REACTION_POINTINESS * 2 / (count + 1);
for (Pair<Integer, KPort> indexedPort : indexedPorts) {
KPort port = indexedPort.getValue();
int idx = indexedPort.getKey();
float offset = 0;
if (count % 2 != 0 && idx == count / 2) {
offset += LinguaFrancaShapeExtensions.REACTION_POINTINESS;
} else if (idx < count / 2) {
offset += segments * (idx + 1);
} else {
offset += segments * (count - idx);
}
if (!input) {
// reverse
offset -= LinguaFrancaShapeExtensions.REACTION_POINTINESS;
}
// apply
port.setPos(port.getXpos() + offset, port.getYpos());
for (KEdge edge : port.getEdges()) {
if (input) {
edge.setTargetPoint(adjustedKPoint(edge.getTargetPoint(), offset));
} else {
edge.setSourcePoint(adjustedKPoint(edge.getSourcePoint(), offset));
}
}
}
}
use of de.cau.cs.kieler.klighd.kgraph.KEdge in project lingua-franca by lf-lang.
the class LinguaFrancaSynthesis method addErrorComment.
private KNode addErrorComment(KNode node, String message) {
KNode comment = _kNodeExtensions.createNode();
setLayoutOption(comment, CoreOptions.COMMENT_BOX, true);
KRoundedRectangle commentFigure = _linguaFrancaShapeExtensions.addCommentFigure(comment, message);
_linguaFrancaStyleExtensions.errorStyle(commentFigure);
_kRenderingExtensions.setBackground(commentFigure, Colors.PEACH_PUFF_2);
// connect
KEdge edge = _kEdgeExtensions.createEdge();
edge.setSource(comment);
edge.setTarget(node);
_linguaFrancaStyleExtensions.errorStyle(_linguaFrancaShapeExtensions.addCommentPolyline(edge));
return comment;
}
Aggregations