use of org.eclipse.elk.core.math.ElkMargin 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 org.eclipse.elk.core.math.ElkMargin in project elk by eclipse.
the class NodeMarginCalculator method processNode.
/**
* Calculates the margin of the given node.
*
* @param node the node whose margin to calculate.
* @param labelSpacing label spacing set on the layered graph.
*/
private void processNode(final NodeAdapter<?> node, final double labelSpacing) {
// This will be our bounding box. We'll start with one that's the same size
// as our node, and at the same position.
ElkRectangle boundingBox = new ElkRectangle(node.getPosition().x, node.getPosition().y, node.getSize().x, node.getSize().y);
// We'll reuse this rectangle as our box for elements to add to the bounding box
ElkRectangle elementBox = new ElkRectangle();
// Put the node's labels into the bounding box
if (includeLabels) {
for (LabelAdapter<?> label : node.getLabels()) {
elementBox.x = label.getPosition().x + node.getPosition().x;
elementBox.y = label.getPosition().y + node.getPosition().y;
elementBox.width = label.getSize().x;
elementBox.height = label.getSize().y;
boundingBox.union(elementBox);
}
}
// Do the same for ports and their labels
for (PortAdapter<?> port : node.getPorts()) {
// Calculate the port's upper left corner's x and y coordinate
double portX = port.getPosition().x + node.getPosition().x;
double portY = port.getPosition().y + node.getPosition().y;
// The port itself
if (includePorts) {
elementBox.x = portX;
elementBox.y = portY;
elementBox.width = port.getSize().x;
elementBox.height = port.getSize().y;
boundingBox.union(elementBox);
}
// The port's labels
if (includePortLabels) {
for (LabelAdapter<?> label : port.getLabels()) {
elementBox.x = label.getPosition().x + portX;
elementBox.y = label.getPosition().y + portY;
elementBox.width = label.getSize().x;
elementBox.height = label.getSize().y;
boundingBox.union(elementBox);
}
}
// End labels of edges connected to the port
if (includeEdgeHeadTailLabels) {
KVector requiredPortLabelSpace = new KVector(-labelSpacing, -labelSpacing);
// TODO: maybe leave space for manually placed ports
if (node.getProperty(CoreOptions.PORT_LABELS_PLACEMENT).contains(PortLabelPlacement.OUTSIDE)) {
for (LabelAdapter<?> label : port.getLabels()) {
requiredPortLabelSpace.x += label.getSize().x + labelSpacing;
requiredPortLabelSpace.y += label.getSize().y + labelSpacing;
}
}
requiredPortLabelSpace.x = Math.max(requiredPortLabelSpace.x, 0.0);
requiredPortLabelSpace.y = Math.max(requiredPortLabelSpace.y, 0.0);
processEdgeHeadTailLabels(boundingBox, port.getOutgoingEdges(), port.getIncomingEdges(), node, port, requiredPortLabelSpace, labelSpacing);
}
}
// Process end labels of edges directly connected to the node
if (includeEdgeHeadTailLabels) {
processEdgeHeadTailLabels(boundingBox, node.getOutgoingEdges(), node.getIncomingEdges(), node, null, null, labelSpacing);
}
// Reset the margin (guard against very small double precision errors which can cause the results to be small
// negative values, which doesn't make sense -- see #616)
ElkMargin margin = new ElkMargin(node.getMargin());
margin.top = Math.max(0, node.getPosition().y - boundingBox.y);
margin.bottom = Math.max(0, boundingBox.y + boundingBox.height - (node.getPosition().y + node.getSize().y));
margin.left = Math.max(0, node.getPosition().x - boundingBox.x);
margin.right = Math.max(0, boundingBox.x + boundingBox.width - (node.getPosition().x + node.getSize().x));
node.setMargin(margin);
}
use of org.eclipse.elk.core.math.ElkMargin in project elk by eclipse.
the class InteractiveExternalPortPositioner method findNorthSouthPortXCoordinate.
private Optional<Double> findNorthSouthPortXCoordinate(final LNode dummy) {
// external port dummies must have exactly one port
assert dummy.getPorts().size() == 1;
LPort port = dummy.getPorts().get(0);
if (!port.getOutgoingEdges().isEmpty() && !port.getIncomingEdges().isEmpty()) {
throw new IllegalStateException("Interactive layout does not support " + "NORTH/SOUTH ports with incoming _and_ outgoing edges.");
}
if (!port.getOutgoingEdges().isEmpty()) {
// find the minimum position
double min = Double.POSITIVE_INFINITY;
for (LEdge e : port.getOutgoingEdges()) {
LNode n = e.getTarget().getNode();
ElkMargin margins = n.getProperty(LayeredOptions.MARGINS);
min = Math.min(min, n.getPosition().x - margins.left);
}
return Optional.of(min);
}
if (!port.getIncomingEdges().isEmpty()) {
// find the maximum value
double max = Double.NEGATIVE_INFINITY;
for (LEdge e : port.getIncomingEdges()) {
LNode n = e.getSource().getNode();
ElkMargin margins = n.getProperty(LayeredOptions.MARGINS);
max = Math.max(max, n.getPosition().x + n.getSize().x + margins.right);
}
return Optional.of(max);
}
// we should never reach here
return Optional.absent();
}
use of org.eclipse.elk.core.math.ElkMargin in project elk by eclipse.
the class ElkGraphImporter method importGraph.
@Override
public Graph importGraph(final ElkNode inputGraph) {
elkGraph = inputGraph;
nodeMap = Maps.newHashMap();
// calculate margins
ElkGraphAdapter adapter = ElkGraphAdapters.adapt(elkGraph);
NodeDimensionCalculation.calculateNodeMargins(adapter);
// retrieve layout options
String preferredRootID = elkGraph.getProperty(SporeCompactionOptions.PROCESSING_ORDER_PREFERRED_ROOT);
SpanningTreeCostFunction costFunctionID = elkGraph.getProperty(SporeCompactionOptions.PROCESSING_ORDER_SPANNING_TREE_COST_FUNCTION);
TreeConstructionStrategy treeConstructionStrategy = elkGraph.getProperty(SporeCompactionOptions.PROCESSING_ORDER_TREE_CONSTRUCTION);
CompactionStrategy compactionStrategy = elkGraph.getProperty(SporeCompactionOptions.COMPACTION_COMPACTION_STRATEGY);
RootSelection rootSelection = elkGraph.getProperty(SporeCompactionOptions.PROCESSING_ORDER_ROOT_SELECTION);
spacingNodeNode = elkGraph.getProperty(SporeCompactionOptions.SPACING_NODE_NODE);
ICostFunction costFunction = centerDistance;
switch(costFunctionID) {
case CENTER_DISTANCE:
costFunction = centerDistance;
break;
case CIRCLE_UNDERLAP:
costFunction = circleUnderlap;
break;
case RECTANGLE_UNDERLAP:
costFunction = rectangleUnderlap;
break;
case INVERTED_OVERLAP:
costFunction = invertedOverlap;
break;
case MINIMUM_ROOT_DISTANCE:
costFunction = minimumRootDistance;
break;
default:
throw new IllegalArgumentException("No implementation available for " + costFunctionID.toString());
}
// instantiate Graph
graph = new Graph(costFunction, treeConstructionStrategy, compactionStrategy);
graph.setProperty(InternalProperties.DEBUG_SVG, elkGraph.getProperty(SporeCompactionOptions.DEBUG_MODE));
graph.orthogonalCompaction = elkGraph.getProperty(SporeCompactionOptions.COMPACTION_ORTHOGONAL);
if (elkGraph.getChildren().isEmpty()) {
// don't bother
return graph;
}
// create Nodes representing the ElkNodes
for (ElkNode elkNode : elkGraph.getChildren()) {
double halfWidth = elkNode.getWidth() / 2;
double halfHeight = elkNode.getHeight() / 2;
KVector vertex = new KVector(elkNode.getX() + halfWidth, elkNode.getY() + halfHeight);
// randomly shift identical points a tiny bit to make them unique
while (nodeMap.containsKey(vertex)) {
// SUPPRESS CHECKSTYLE NEXT 1 MagicNumber
vertex.add((Math.random() - 0.5) * 0.001, (Math.random() - 0.5) * 0.001);
// If two positions were identical, their corresponding edge in the spanning tree would be
// of zero length, had no direction, and couldn't be scaled by anything.
}
ElkMargin margin = elkNode.getProperty(CoreOptions.MARGINS);
Node node = new Node(vertex, new ElkRectangle(vertex.x - halfWidth - spacingNodeNode / 2 - margin.left, vertex.y - halfHeight - spacingNodeNode / 2 - margin.top, elkNode.getWidth() + spacingNodeNode + margin.getHorizontal(), elkNode.getHeight() + spacingNodeNode + margin.getVertical()));
graph.vertices.add(node);
nodeMap.put(vertex, Pair.of(node, elkNode));
}
// spanning tree root selection method
switch(rootSelection) {
case FIXED:
if (preferredRootID == null) {
// get first Node in list if no ID specified
graph.preferredRoot = graph.vertices.get(0);
} else {
// find Node associated with the ElkNode containing the ID
for (Node node : graph.vertices) {
String id = nodeMap.get(node.originalVertex).getSecond().getIdentifier();
if (id != null && id.equals(preferredRootID)) {
graph.preferredRoot = node;
}
}
}
break;
case CENTER_NODE:
// find node that is most central in the drawing
KVector center = new KVector(elkGraph.getWidth(), elkGraph.getHeight());
// CHECKSTYLEOFF MagicNumber
center.scale(0.5);
center.add(elkGraph.getX(), elkGraph.getY());
double closest = Double.POSITIVE_INFINITY;
for (Node node : graph.vertices) {
double distance = node.originalVertex.distance(center);
if (distance < closest) {
closest = distance;
graph.preferredRoot = node;
}
}
break;
default:
throw new IllegalArgumentException("No implementation available for " + rootSelection.toString());
}
return graph;
}
use of org.eclipse.elk.core.math.ElkMargin in project elk by eclipse.
the class CalculateGraphSize method process.
/**
* Shift the nodes such that each nodes has x and y coordinates bigger 0.
*/
public void process(final ElkNode graph, final IElkProgressMonitor progressMonitor) {
progressMonitor.begin("Calculate Graph Size", 1);
progressMonitor.logGraph(graph, "Before");
// calculate the offset from border spacing and node distribution
double minXPos = Double.MAX_VALUE;
double minYPos = Double.MAX_VALUE;
double maxXPos = Double.MIN_VALUE;
double maxYPos = Double.MIN_VALUE;
for (ElkNode node : graph.getChildren()) {
double posX = node.getX();
double posY = node.getY();
double width = node.getWidth();
double height = node.getHeight();
ElkMargin margins = node.getProperty(CoreOptions.MARGINS);
minXPos = Math.min(minXPos, posX - margins.left);
minYPos = Math.min(minYPos, posY - margins.top);
maxXPos = Math.max(maxXPos, posX + width + margins.right);
maxYPos = Math.max(maxYPos, posY + height + margins.bottom);
}
ElkPadding padding = graph.getProperty(CoreOptions.PADDING);
KVector offset = new KVector(minXPos - padding.getLeft(), minYPos - padding.getTop());
// process the nodes
for (ElkNode node : graph.getChildren()) {
// set the node position
node.setX(node.getX() - offset.x);
node.setY(node.getY() - offset.y);
}
// set up the graph
double width = maxXPos - minXPos + padding.getHorizontal();
double height = maxYPos - minYPos + padding.getVertical();
graph.setWidth(width);
graph.setHeight(height);
progressMonitor.logGraph(graph, "After");
}
Aggregations