use of org.eclipse.elk.core.options.Direction in project elk by eclipse.
the class ElkUtil method resizeNode.
/**
* Resize a node to the given width and height, adjusting port and label positions if needed.
*
* @param node a node
* @param newWidth the new width to set
* @param newHeight the new height to set
* @param movePorts whether port positions should be adjusted
* @param moveLabels whether label positions should be adjusted
* @return a vector holding the width and height resizing ratio
*/
public static KVector resizeNode(final ElkNode node, final double newWidth, final double newHeight, final boolean movePorts, final boolean moveLabels) {
KVector oldSize = new KVector(node.getWidth(), node.getHeight());
KVector newSize = effectiveMinSizeConstraintFor(node);
newSize.x = Math.max(newSize.x, newWidth);
newSize.y = Math.max(newSize.y, newHeight);
double widthRatio = newSize.x / oldSize.x;
double heightRatio = newSize.y / oldSize.y;
double widthDiff = newSize.x - oldSize.x;
double heightDiff = newSize.y - oldSize.y;
// update port positions
if (movePorts) {
Direction direction = node.getParent() == null ? node.getProperty(CoreOptions.DIRECTION) : node.getParent().getProperty(CoreOptions.DIRECTION);
boolean fixedPorts = node.getProperty(CoreOptions.PORT_CONSTRAINTS) == PortConstraints.FIXED_POS;
for (ElkPort port : node.getPorts()) {
PortSide portSide = port.getProperty(CoreOptions.PORT_SIDE);
if (portSide == PortSide.UNDEFINED) {
portSide = calcPortSide(port, direction);
port.setProperty(CoreOptions.PORT_SIDE, portSide);
}
switch(portSide) {
case NORTH:
if (!fixedPorts) {
port.setX(port.getX() * widthRatio);
}
break;
case EAST:
port.setX(port.getX() + widthDiff);
if (!fixedPorts) {
port.setY(port.getY() * heightRatio);
}
break;
case SOUTH:
if (!fixedPorts) {
port.setX(port.getX() * widthRatio);
}
port.setY(port.getY() + heightDiff);
break;
case WEST:
if (!fixedPorts) {
port.setY(port.getY() * heightRatio);
}
break;
}
}
}
// resize the node AFTER ports have been placed, since calcPortSide needs the old size
node.setDimensions(newSize.x, newSize.y);
// update label positions
if (moveLabels) {
for (ElkLabel label : node.getLabels()) {
double midx = label.getX() + label.getWidth() / 2;
double midy = label.getY() + label.getHeight() / 2;
double widthPercent = midx / oldSize.x;
double heightPercent = midy / oldSize.y;
if (widthPercent + heightPercent >= 1) {
if (widthPercent - heightPercent > 0 && midy >= 0) {
// label is on the right
label.setX(label.getX() + widthDiff);
label.setY(label.getY() + heightDiff * heightPercent);
} else if (widthPercent - heightPercent < 0 && midx >= 0) {
// label is on the bottom
label.setX(label.getX() + widthDiff * widthPercent);
label.setY(label.getY() + heightDiff);
}
}
}
}
// set fixed size option for the node: now the size is assumed to stay as determined here
node.setProperty(CoreOptions.NODE_SIZE_CONSTRAINTS, SizeConstraint.fixed());
return new KVector(widthRatio, heightRatio);
}
use of org.eclipse.elk.core.options.Direction in project elk by eclipse.
the class Draw2DLayoutProvider method buildDraw2dGraph.
/**
* Builds the graph which is used internally by the Draw2D layout algorithm.
*
* @param layoutNode parent layout node
* @return a graph that contains the children of the given parent
*/
@SuppressWarnings("unchecked")
private DirectedGraph buildDraw2dGraph(final ElkNode layoutNode) {
DirectedGraph graph = new DirectedGraph();
// set layout options for the graph
double minSpacing = layoutNode.getProperty(Draw2DOptions.SPACING_NODE_NODE);
if (minSpacing < 0) {
minSpacing = DEF_MIN_SPACING;
}
graph.setDefaultPadding(new Insets((int) minSpacing));
ElkPadding padding = layoutNode.getProperty(Draw2DOptions.PADDING);
graph.setMargin(new Insets((int) padding.top, (int) padding.left, (int) padding.bottom, (int) padding.right));
Direction layoutDirection = layoutNode.getProperty(Draw2DOptions.DIRECTION);
switch(layoutDirection) {
case UP:
case DOWN:
graph.setDirection(PositionConstants.SOUTH);
break;
default:
graph.setDirection(PositionConstants.EAST);
break;
}
// add nodes to the graph
Map<ElkNode, Node> nodeMap = new HashMap<>();
for (ElkNode elknode : layoutNode.getChildren()) {
Node draw2dNode = new Node(elknode);
ElkUtil.resizeNode(elknode);
draw2dNode.width = (int) elknode.getWidth();
draw2dNode.height = (int) elknode.getHeight();
nodeMap.put(elknode, draw2dNode);
graph.nodes.add(draw2dNode);
}
// add edges to the graph
for (ElkNode source : layoutNode.getChildren()) {
Node draw2dSource = nodeMap.get(source);
for (ElkEdge kedge : ElkGraphUtil.allOutgoingEdges(source)) {
// we don't support hyperedges
if (kedge.isHyperedge()) {
continue;
}
ElkNode target = ElkGraphUtil.connectableShapeToNode(kedge.getTargets().get(0));
Node draw2dTarget = nodeMap.get(target);
if (draw2dTarget != null && draw2dTarget != draw2dSource) {
Edge draw2dEdge = new Edge(kedge, draw2dSource, draw2dTarget);
graph.edges.add(draw2dEdge);
}
}
}
return graph;
}
use of org.eclipse.elk.core.options.Direction in project elk by eclipse.
the class OneDimensionalCompactor method changeDirection.
/**
* Changes the direction for compaction by transforming the hitboxes.
*
* @param dir
* the new direction
* @return
* this instance of {@link OneDimensionalCompactor}
*/
public OneDimensionalCompactor changeDirection(final Direction dir) {
if (finished) {
throw new IllegalStateException("The " + getClass().getSimpleName() + " instance has been finished already.");
}
// segments would interchange
if (!cGraph.supports(dir)) {
throw new RuntimeException("The direction " + dir + " is not supported by the CGraph instance.");
}
// short-circuit if nothing todo
if (dir == direction) {
return this;
}
Direction oldDirection = direction;
direction = dir;
// being recalculated and CNodes are locked
switch(oldDirection) {
case UNDEFINED:
switch(dir) {
case LEFT:
calculateConstraints();
break;
case RIGHT:
mirrorHitboxes();
calculateConstraints();
break;
case UP:
transposeHitboxes();
calculateConstraints();
break;
case DOWN:
transposeHitboxes();
mirrorHitboxes();
calculateConstraints();
break;
default:
break;
}
break;
case LEFT:
switch(dir) {
case RIGHT:
mirrorHitboxes();
reverseConstraints();
break;
case UP:
transposeHitboxes();
calculateConstraints();
break;
case DOWN:
transposeHitboxes();
mirrorHitboxes();
calculateConstraints();
break;
default:
break;
}
break;
case RIGHT:
switch(dir) {
case LEFT:
mirrorHitboxes();
reverseConstraints();
break;
case UP:
mirrorHitboxes();
transposeHitboxes();
calculateConstraints();
break;
case DOWN:
mirrorHitboxes();
transposeHitboxes();
mirrorHitboxes();
calculateConstraints();
break;
default:
break;
}
break;
case UP:
switch(dir) {
case LEFT:
transposeHitboxes();
calculateConstraints();
break;
case RIGHT:
transposeHitboxes();
mirrorHitboxes();
calculateConstraints();
break;
case DOWN:
mirrorHitboxes();
reverseConstraints();
break;
default:
break;
}
break;
case DOWN:
switch(dir) {
case LEFT:
mirrorHitboxes();
transposeHitboxes();
calculateConstraints();
break;
case RIGHT:
mirrorHitboxes();
transposeHitboxes();
mirrorHitboxes();
calculateConstraints();
break;
case UP:
mirrorHitboxes();
reverseConstraints();
break;
default:
break;
}
break;
default:
break;
}
return this;
}
use of org.eclipse.elk.core.options.Direction in project elk by eclipse.
the class ElkGraphImporter method transformNode.
// /////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Node Transformation
/**
* Transforms the given node and its contained ports.
*
* @param elknode
* the node to transform
* @param lgraph
* the layered graph into which the transformed node is put
* @return the transformed node
*/
private LNode transformNode(final ElkNode elknode, final LGraph lgraph) {
// add a new node to the layered graph, copying its position
LNode lnode = new LNode(lgraph);
lnode.copyProperties(elknode);
lnode.setProperty(InternalProperties.ORIGIN, elknode);
lnode.getSize().x = elknode.getWidth();
lnode.getSize().y = elknode.getHeight();
lnode.getPosition().x = elknode.getX();
lnode.getPosition().y = elknode.getY();
lgraph.getLayerlessNodes().add(lnode);
nodeAndPortMap.put(elknode, lnode);
// check if the node is a compound node in the original graph
if (!elknode.getChildren().isEmpty() || elknode.getProperty(LayeredOptions.INSIDE_SELF_LOOPS_ACTIVATE)) {
lnode.setProperty(InternalProperties.COMPOUND_NODE, true);
}
Set<GraphProperties> graphProperties = lgraph.getProperty(InternalProperties.GRAPH_PROPERTIES);
// port constraints and sides cannot be undefined
PortConstraints portConstraints = lnode.getProperty(LayeredOptions.PORT_CONSTRAINTS);
if (portConstraints == PortConstraints.UNDEFINED) {
lnode.setProperty(LayeredOptions.PORT_CONSTRAINTS, PortConstraints.FREE);
} else if (portConstraints != PortConstraints.FREE) {
// if the port constraints are not free, set the appropriate graph property
graphProperties.add(GraphProperties.NON_FREE_PORTS);
}
// transform the ports
Direction direction = lgraph.getProperty(LayeredOptions.DIRECTION);
for (ElkPort elkport : elknode.getPorts()) {
if (!elkport.getProperty(LayeredOptions.NO_LAYOUT)) {
transformPort(elkport, lnode, graphProperties, direction, portConstraints);
}
}
// add the node's labels
for (ElkLabel elklabel : elknode.getLabels()) {
if (!elklabel.getProperty(LayeredOptions.NO_LAYOUT) && !Strings.isNullOrEmpty(elklabel.getText())) {
lnode.getLabels().add(transformLabel(elklabel));
}
}
if (lnode.getProperty(LayeredOptions.COMMENT_BOX)) {
graphProperties.add(GraphProperties.COMMENTS);
}
// if we have a hypernode without ports, create a default input and output port
if (lnode.getProperty(LayeredOptions.HYPERNODE)) {
graphProperties.add(GraphProperties.HYPERNODES);
graphProperties.add(GraphProperties.HYPEREDGES);
lnode.setProperty(LayeredOptions.PORT_CONSTRAINTS, PortConstraints.FREE);
}
return lnode;
}
use of org.eclipse.elk.core.options.Direction in project elk by eclipse.
the class LabelDummyInserter method process.
@Override
public void process(final LGraph layeredGraph, final IElkProgressMonitor monitor) {
monitor.begin("Label dummy insertions", 1);
// We cannot add the nodes to the graph while we're iterating over it, so remember the dummy nodes we create
List<LNode> newDummyNodes = Lists.newArrayList();
double edgeLabelSpacing = layeredGraph.getProperty(LayeredOptions.SPACING_EDGE_LABEL);
double labelLabelSpacing = layeredGraph.getProperty(LayeredOptions.SPACING_LABEL_LABEL);
Direction layoutDirection = layeredGraph.getProperty(LayeredOptions.DIRECTION);
for (LNode node : layeredGraph.getLayerlessNodes()) {
for (LEdge edge : node.getOutgoingEdges()) {
if (edgeNeedsToBeProcessed(edge)) {
double thickness = retrieveThickness(edge);
// Create dummy node and remember represented labels (to be filled below)
List<LLabel> representedLabels = Lists.newArrayListWithCapacity(edge.getLabels().size());
LNode dummyNode = createLabelDummy(layeredGraph, edge, thickness, representedLabels);
newDummyNodes.add(dummyNode);
// Determine the size of the dummy node and move labels over to it
KVector dummySize = dummyNode.getSize();
ListIterator<LLabel> iterator = edge.getLabels().listIterator();
while (iterator.hasNext()) {
LLabel label = iterator.next();
if (label.getProperty(LayeredOptions.EDGE_LABELS_PLACEMENT) == EdgeLabelPlacement.CENTER) {
// The way we stack labels depends on the layout direction
if (layoutDirection.isVertical()) {
dummySize.x += label.getSize().x + labelLabelSpacing;
dummySize.y = Math.max(dummySize.y, label.getSize().y);
} else {
dummySize.x = Math.max(dummySize.x, label.getSize().x);
dummySize.y += label.getSize().y + labelLabelSpacing;
}
// Move the label over to the dummy node's REPRESENTED_LABELS property
representedLabels.add(label);
iterator.remove();
}
}
// edge-label spacing yet
if (layoutDirection.isVertical()) {
dummySize.x -= labelLabelSpacing;
dummySize.y += edgeLabelSpacing + thickness;
} else {
dummySize.y += edgeLabelSpacing - labelLabelSpacing + thickness;
}
}
}
}
// Add created dummies to graph
layeredGraph.getLayerlessNodes().addAll(newDummyNodes);
monitor.done();
}
Aggregations