use of org.eclipse.elk.core.options.PortSide in project elk by eclipse.
the class AbstractBarycenterPortDistributor method distributePortsWhileSweeping.
// /////////////////////////////////////////////////////////////////////////////
// Port Rank Assignment
@Override
public boolean distributePortsWhileSweeping(final LNode[][] nodeOrder, final int currentIndex, final boolean isForwardSweep) {
updateNodePositions(nodeOrder, currentIndex);
LNode[] freeLayer = nodeOrder[currentIndex];
PortSide side = isForwardSweep ? PortSide.WEST : PortSide.EAST;
if (isNotFirstLayer(nodeOrder.length, currentIndex, isForwardSweep)) {
LNode[] fixedLayer = nodeOrder[isForwardSweep ? currentIndex - 1 : currentIndex + 1];
calculatePortRanks(fixedLayer, portTypeFor(isForwardSweep));
for (LNode node : freeLayer) {
distributePorts(node, side);
}
calculatePortRanks(freeLayer, portTypeFor(!isForwardSweep));
for (LNode node : fixedLayer) {
if (!hasNestedGraph(node)) {
distributePorts(node, side.opposed());
}
}
} else {
for (LNode node : freeLayer) {
distributePorts(node, side);
}
}
// which do not need to count.
return false;
}
use of org.eclipse.elk.core.options.PortSide in project elk by eclipse.
the class AbstractBarycenterPortDistributor method sortPorts.
/**
* Sort the ports of a node using the given relative position values. These values are
* interpreted as a hint for the clockwise order of ports.
*
* @param node
* a node
*/
private void sortPorts(final LNode node) {
Collections.sort(node.getPorts(), (port1, port2) -> {
PortSide side1 = port1.getSide();
PortSide side2 = port2.getSide();
if (side1 != side2) {
// sort according to the node side
return side1.ordinal() - side2.ordinal();
} else {
float port1Bary = portBarycenter[port1.id];
float port2Bary = portBarycenter[port2.id];
if (port1Bary == 0 && port2Bary == 0) {
return 0;
} else if (port1Bary == 0) {
return -1;
} else if (port2Bary == 0) {
return 1;
} else {
// sort according to the position value
return Float.compare(port1Bary, port2Bary);
}
}
});
}
use of org.eclipse.elk.core.options.PortSide in project elk by eclipse.
the class ElkGraphImporter method transformExternalPort.
/**
* Transforms the given external port into a dummy node.
*
* @param elkgraph
* the original KGraph
* @param lgraph
* the corresponding layered graph
* @param elkport
* the port to be transformed
*/
private void transformExternalPort(final ElkNode elkgraph, final LGraph lgraph, final ElkPort elkport) {
// We need some information about the port
KVector elkportPosition = new KVector(elkport.getX() + elkport.getWidth() / 2.0, elkport.getY() + elkport.getHeight() / 2.0);
int netFlow = calculateNetFlow(elkport);
PortConstraints portConstraints = elkgraph.getProperty(LayeredOptions.PORT_CONSTRAINTS);
// If we don't have a proper port side, calculate one
PortSide portSide = elkport.getProperty(LayeredOptions.PORT_SIDE);
assert portSide != PortSide.UNDEFINED;
// If we don't have a port offset, infer one
if (!elkport.getAllProperties().containsKey(LayeredOptions.PORT_BORDER_OFFSET)) {
double portOffset;
// if port coordinates are (0,0), we default to port offset 0 to make the common case frustration-free
if (elkport.getX() == 0.0 && elkport.getY() == 0.0) {
portOffset = 0.0;
} else {
portOffset = ElkUtil.calcPortOffset(elkport, portSide);
}
elkport.setProperty(LayeredOptions.PORT_BORDER_OFFSET, portOffset);
}
// Create the external port dummy node
KVector graphSize = new KVector(elkgraph.getWidth(), elkgraph.getHeight());
LNode dummy = LGraphUtil.createExternalPortDummy(elkport, portConstraints, portSide, netFlow, graphSize, elkportPosition, new KVector(elkport.getWidth(), elkport.getHeight()), lgraph.getProperty(LayeredOptions.DIRECTION), lgraph);
dummy.setProperty(InternalProperties.ORIGIN, elkport);
// The dummy only has one port
LPort dummyPort = dummy.getPorts().get(0);
dummyPort.setConnectedToExternalNodes(isConnectedToExternalNodes(elkport));
dummy.setProperty(LayeredOptions.PORT_LABELS_PLACEMENT, PortLabelPlacement.outside());
// If the compound node wants to have its port labels placed on the inside, we need to leave
// enough space for them by creating an LLabel for the KLabels. If the compound node wants to
// have its port labels placed on the outside, we still need to leave enough space for them
// so the port placement does not cause problems on the outside, but we also don't want to waste
// space inside. Thus, for east and west ports, we reduce the label width to zero, otherwise
// we reduce the label height to zero
boolean insidePortLabels = elkgraph.getProperty(LayeredOptions.PORT_LABELS_PLACEMENT).contains(PortLabelPlacement.INSIDE);
// Transform all of the port's labels
for (ElkLabel elklabel : elkport.getLabels()) {
if (!elklabel.getProperty(LayeredOptions.NO_LAYOUT) && !Strings.isNullOrEmpty(elklabel.getText())) {
LLabel llabel = transformLabel(elklabel);
dummyPort.getLabels().add(llabel);
// If the port labels are fixed, we should consider the part that is inside the node and not 0.
if (!insidePortLabels) {
double insidePart = 0;
if (PortLabelPlacement.isFixed(elkgraph.getProperty(LayeredOptions.PORT_LABELS_PLACEMENT))) {
// We use 0 as port border offset here, as we only want the label part that is
// inside the node "after" the port.
insidePart = ElkUtil.computeInsidePart(new KVector(elklabel.getX(), elklabel.getY()), new KVector(elklabel.getWidth(), elklabel.getHeight()), new KVector(elkport.getWidth(), elkport.getHeight()), 0, portSide);
}
switch(portSide) {
case EAST:
case WEST:
llabel.getSize().x = insidePart;
break;
case NORTH:
case SOUTH:
llabel.getSize().y = insidePart;
break;
}
}
}
}
// Remember the relevant spacings that will apply to the labels here. It's not the spacings in the graph, but
// in the parent
dummy.setProperty(LayeredOptions.SPACING_LABEL_PORT, elkgraph.getParent().getProperty(LayeredOptions.SPACING_LABEL_PORT));
dummy.setProperty(LayeredOptions.SPACING_LABEL_LABEL, elkgraph.getParent().getProperty(LayeredOptions.SPACING_LABEL_LABEL));
// Put the external port dummy into our graph and associate it with the original KPort
lgraph.getLayerlessNodes().add(dummy);
nodeAndPortMap.put(elkport, dummy);
}
use of org.eclipse.elk.core.options.PortSide in project elk by eclipse.
the class ElkGraphImporter method ensureDefinedPortSide.
/**
* Ensures that the given port has a defined port side.
*/
private void ensureDefinedPortSide(final LGraph lgraph, final ElkPort elkport) {
Direction layoutDirection = lgraph.getProperty(LayeredOptions.DIRECTION);
PortSide portSide = elkport.getProperty(LayeredOptions.PORT_SIDE);
PortConstraints portConstraints = lgraph.getProperty(LayeredOptions.PORT_CONSTRAINTS);
if (!portConstraints.isSideFixed()) {
// We are free to assign ports to sides, so the port side will depend on the layout direction and the
// port's net flow
int netFlow = calculateNetFlow(elkport);
if (netFlow > 0) {
portSide = PortSide.fromDirection(layoutDirection);
} else {
portSide = PortSide.fromDirection(layoutDirection).opposed();
}
} else {
// We are not free to assign port sides. If none is set, try inferring it from the port's position
if (portSide == PortSide.UNDEFINED) {
portSide = ElkUtil.calcPortSide(elkport, layoutDirection);
// There are cases where ELK may have failed to infer the port side
if (portSide == PortSide.UNDEFINED) {
portSide = PortSide.fromDirection(layoutDirection);
}
}
}
elkport.setProperty(LayeredOptions.PORT_SIDE, portSide);
}
use of org.eclipse.elk.core.options.PortSide in project elk by eclipse.
the class ComponentsCompactor method transformLEdge.
/**
* Converts an external edge to an external extension. While doing so, the the original edge
* contributes three things as explained in the code.
*/
private IExternalExtension<LEdge> transformLEdge(final LEdge externalEdge, final Hullpoints hullPoints, final OuterSegments outerSegments) {
InternalExternalExtension externalExtension = new InternalExternalExtension(externalEdge);
// #1 convert the edge's path into a set of segments
Segments segments = edgeToSegments(externalEdge, externalExtension);
// #2 all 'inner' segments contribute to the hull (consider the edge's thickness)
double thickness = Math.max(externalEdge.getProperty(LayeredOptions.EDGE_THICKNESS).doubleValue(), 1);
for (Pair<KVector, KVector> segment : segments.innerSegments) {
ElkRectangle rect = segmentToRectangle(segment.getFirst(), segment.getSecond(), thickness);
hullPoints.add(rect);
}
// #3 the 'outer' segment, being the segment that actually connects to the external port,
// contributes to the 'union external segment' that we create
// for one direction of the component
PortSide side = externalExtension.externalPortSide;
ElkRectangle outerSegmentRect = segmentToRectangle(segments.outerSegment.getFirst(), segments.outerSegment.getSecond(), thickness);
if (side == PortSide.WEST || side == PortSide.EAST) {
outerSegments.min[side.ordinal()] = Math.min(outerSegments.min[side.ordinal()], outerSegmentRect.y);
outerSegments.max[side.ordinal()] = Math.max(outerSegments.max[side.ordinal()], outerSegmentRect.y + outerSegmentRect.height);
} else {
outerSegments.min[side.ordinal()] = Math.min(outerSegments.min[side.ordinal()], outerSegmentRect.x);
outerSegments.max[side.ordinal()] = Math.max(outerSegments.max[side.ordinal()], outerSegmentRect.x + outerSegmentRect.width);
}
// extent
double extent = Double.NEGATIVE_INFINITY;
LMargin margins = externalExtension.externalPort.getNode().getMargin();
switch(side) {
case WEST:
extent = margins.right;
break;
case EAST:
extent = margins.left;
break;
case NORTH:
extent = margins.bottom;
break;
case SOUTH:
extent = margins.top;
break;
}
outerSegments.extent[side.ordinal()] = Math.max(outerSegments.extent[side.ordinal()], extent);
return externalExtension;
}
Aggregations