use of org.osate.ge.internal.diagram.runtime.DiagramElement in project osate2 by osate.
the class DiagramElementLayoutUtil method getConnectionsAffectedByMove.
/**
* Returns the connections which are affected by moving the specified elements
* @param movedElement is the element which to get the affected connections
* @param diagram is the diagram which contains the connections.
* @param checkDescendants whether to check descendants of the specified elements when looking for connections
* @return he connections which are affected by moving the specified elements
*/
public static Stream<DiagramElement> getConnectionsAffectedByMove(final DiagramElement movedElement, final AgeDiagram diagram, final boolean checkDescendants) {
// Build a set containing the moved elements and all of their descendant which are represented as shapes
final Set<BusinessObjectContext> diagramElements = checkDescendants ? movedElement.getAllDescendants().collect(Collectors.toSet()) : Collections.singleton(movedElement);
final Stream<DiagramElement> connections = diagram.getAllDiagramNodes().filter(q -> q instanceof DiagramElement && DiagramElementPredicates.isConnection((DiagramElement) q)).map(DiagramElement.class::cast);
// Iterate over all the connections in the diagram and update their bendpoints if their ends are in the set above.
return connections.filter(c -> {
final DiagramElement startElement = c.getStartElement();
final DiagramElement endElement = c.getEndElement();
final boolean isFlowIndicator = ((AgeConnection) c.getGraphic()).isFlowIndicator;
return diagramElements.contains(startElement) && (diagramElements.contains(endElement) || isFlowIndicator);
});
}
use of org.osate.ge.internal.diagram.runtime.DiagramElement in project osate2 by osate.
the class ElkGraphBuilder method buildLayoutGraph.
private LayoutMapping buildLayoutGraph(final DiagramNode rootDiagramNode) {
// Create the graph
final LayoutMapping mapping = new LayoutMapping(null);
final ElkNode rootNode = ElkGraphUtil.createGraph();
rootNode.setProperty(CoreOptions.DIRECTION, Direction.RIGHT);
mapping.setLayoutGraph(rootNode);
// As of 2020-04-06, INCLUDE_CHILDREN causes layout issues. In particular, labels can overlap with children
// https://github.com/eclipse/elk/issues/316
// https://github.com/eclipse/elk/issues/412
rootNode.setProperty(CoreOptions.HIERARCHY_HANDLING, HierarchyHandling.SEPARATE_CHILDREN);
if (rootDiagramNode instanceof AgeDiagram) {
final ElkNode diagramElkNode = ElkGraphUtil.createNode(rootNode);
mapping.getGraphMap().put(diagramElkNode, rootDiagramNode);
createElkGraphElementsForNonLabelChildShapes(rootDiagramNode, diagramElkNode, mapping);
} else if (rootDiagramNode instanceof DiagramElement) {
createElkGraphElementsForElements(Collections.singleton((DiagramElement) rootDiagramNode), rootNode, mapping);
}
createElkGraphElementsForConnections(rootDiagramNode, mapping);
return mapping;
}
use of org.osate.ge.internal.diagram.runtime.DiagramElement in project osate2 by osate.
the class ElkGraphBuilder method createElkLabels.
private void createElkLabels(final DiagramElement parentElement, final ElkGraphElement parentLayoutElement, final LayoutMapping mapping) {
// Don't create labels for ElkPort. The bounds of the port contain their labels.
if (parentLayoutElement instanceof ElkPort) {
return;
}
final boolean isConnection = parentElement.getGraphic() instanceof AgeConnection;
final Style style = styleProvider.getStyle(parentElement);
if (style.getPrimaryLabelVisible()) {
// Create Primary Label
if (parentElement.getLabelName() != null) {
final ElkLabel elkLabel = createElkLabel(parentLayoutElement, parentElement.getLabelName(), layoutInfoProvider.getPrimaryLabelSize(parentElement));
if (isConnection) {
if (!layoutConnectionLabels) {
elkLabel.setProperty(CoreOptions.NO_LAYOUT, true);
}
mapping.getGraphMap().put(elkLabel, new PrimaryConnectionLabelReference(parentElement));
}
}
}
// Create label for annotations which are part of the graphic configuration. These are only supported by non-connections.
if (!isConnection && parentElement.getGraphicalConfiguration().getAnnotation() != null) {
createElkLabel(parentLayoutElement, parentElement.getGraphicalConfiguration().getAnnotation(), layoutInfoProvider.getAnnotationLabelSize(parentElement));
}
// Create Secondary Labels
parentElement.getChildren().stream().filter(c -> c.getGraphic() instanceof Label).forEachOrdered(labelElement -> {
final ElkLabel elkLabel = createElkLabel(parentLayoutElement, labelElement.getLabelName(), layoutInfoProvider.getPrimaryLabelSize(labelElement));
if (isConnection) {
if (!layoutConnectionLabels) {
elkLabel.setProperty(CoreOptions.NO_LAYOUT, true);
}
mapping.getGraphMap().put(elkLabel, new SecondaryConnectionLabelReference(labelElement));
}
});
if (parentLayoutElement instanceof ElkNode) {
parentLayoutElement.setProperty(CoreOptions.NODE_LABELS_PLACEMENT, getNodeLabelPlacement(style));
}
}
use of org.osate.ge.internal.diagram.runtime.DiagramElement in project osate2 by osate.
the class ElkGraphBuilder method createElkPortsForElements.
/**
* Before calling this method, all labels for the parent node should have already been created and the node labels placement property must be set for the parent.
* @param elements
* @param parent
* @param mapping
*/
private void createElkPortsForElements(final Collection<DiagramElement> elements, final ElkNode parent, final LayoutMapping mapping) {
final EnumSet<NodeLabelPlacement> nodeLabelPlacement = parent.getProperty(CoreOptions.NODE_LABELS_PLACEMENT);
final boolean labelsAtTop = nodeLabelPlacement != null && nodeLabelPlacement.contains(NodeLabelPlacement.V_TOP);
final double topPadding = labelsAtTop ? parent.getLabels().stream().mapToDouble(l -> l.getY() + l.getHeight()).sum() : 0.0;
// Group children by the port side to which they should be assigned.
final List<DiagramElement> dockedShapes = elements.stream().filter(dockedShapeFilter).collect(Collectors.toList());
final boolean diagramElementIncludesNestedPorts = dockedShapes.stream().flatMap(de -> de.getChildren().stream()).anyMatch(dockedShapeFilter);
// Set the flag to indicate that there are nested ports which will not be included in the final layout graph
if (omitNestedPorts && diagramElementIncludesNestedPorts) {
mapping.getLayoutGraph().setProperty(AgeLayoutOptions.NESTED_PORTS_WERE_OMITTED, true);
}
// Set port constraints and graph hierarchy handling of the parent based on whether the diagram element actually has nested ports.
final boolean hasNestedPorts = !omitNestedPorts && diagramElementIncludesNestedPorts;
PortConstraints portConstraints;
if (dockedShapes.size() == 0) {
// Don't constrain ports if there aren't any. As of 2017-10-11, some other values can affect the layout even if the node does not contain ports.
portConstraints = PortConstraints.FREE;
} else {
if (hasNestedPorts || options.layoutPortsOnDefaultSides) {
portConstraints = PortConstraints.FIXED_POS;
} else {
portConstraints = PortConstraints.FREE;
}
}
parent.setProperty(CoreOptions.PORT_CONSTRAINTS, portConstraints);
final Map<PortSide, List<DiagramElement>> groupedDockedElements = dockedShapes.stream().collect(Collectors.groupingBy(de -> getPortSide(de, hasNestedPorts), HashMap::new, Collectors.toCollection(ArrayList::new)));
// Determine padding
// Need to pad both left and right sides equally if ELK is determining the side of ports. Otherwise, the space for the
// port may overlap with shapes. This is likely caused by adjusting the border offset of ports
// to lay out ports within the bounds of the containing shape
final boolean padOppositeSides = !portConstraints.isSideFixed();
final ElkPadding parentPadding = new ElkPadding(parent.getParent() == null || parent.getParent().getParent() == null ? 0.0 : portAndContentsPadding);
for (final Entry<PortSide, List<DiagramElement>> entry : groupedDockedElements.entrySet()) {
final PortSide side = entry.getKey();
double maxSize = 0;
for (final DiagramElement de : entry.getValue()) {
maxSize = Math.max(maxSize, getOrthogonalSize(de, side));
}
// Update padding for the side
final double sidePadding = maxSize + portAndContentsPadding;
switch(side) {
case NORTH:
parentPadding.top = Math.max(parentPadding.top, sidePadding);
break;
case SOUTH:
parentPadding.bottom = Math.max(parentPadding.bottom, sidePadding);
break;
case EAST:
parentPadding.right = Math.max(parentPadding.right, sidePadding);
if (padOppositeSides) {
parentPadding.left = Math.max(parentPadding.left, sidePadding);
}
break;
case WEST:
parentPadding.left = Math.max(parentPadding.left, sidePadding);
if (padOppositeSides) {
parentPadding.right = Math.max(parentPadding.right, sidePadding);
}
break;
default:
// Ignore
break;
}
}
// Create and position the ports
for (final Entry<PortSide, List<DiagramElement>> portSideToElementsEntry : groupedDockedElements.entrySet()) {
final PortSide side = portSideToElementsEntry.getKey();
final double additionalPadding;
if (PortSide.SIDES_NORTH_SOUTH.contains(side)) {
additionalPadding = Math.max(parentPadding.left, parentPadding.right);
} else {
additionalPadding = topPadding;
}
createAndPositionPorts(parent, portSideToElementsEntry.getValue(), portSideToElementsEntry.getKey(), additionalPadding, mapping, hasNestedPorts);
}
// Set the padding
parent.setProperty(CoreOptions.PADDING, parentPadding);
}
use of org.osate.ge.internal.diagram.runtime.DiagramElement in project osate2 by osate.
the class SelectionPropertyTester method test.
@Override
public boolean test(final Object receiver, final String property, final Object[] args, final Object expectedValue) {
final ISelection selection = (ISelection) receiver;
if (property.equals("allAreDiagramElementsWithSameParent")) {
return DiagramElementUtil.allHaveSameParent(SelectionUtil.getSelectedDiagramElements(selection, false));
} else if (property.equals("singleNamedElementInComponentImplementation")) {
// Returns false if there is more than one element or if the element is not
// a descendant of a component implementation or if the diagram element's BO is not a named element.
final List<DiagramElement> diagramElements = SelectionUtil.getSelectedDiagramElements(selection, false);
return diagramElements.size() == 1 && ToolUtil.findComponentImplementationBoc(diagramElements.get(0)) != null;
} else if (property.contentEquals("namedElementsInSameComponentImplementation")) {
// Returns false if all selected elements are not descendants of the
// same component implementation or if any diagram element's BO is not a named element.
final List<DiagramElement> diagramElements = SelectionUtil.getSelectedDiagramElements(selection, false);
// Get component implementation ancestor for each named element
final List<BusinessObjectContext> ciBocs = diagramElements.stream().map(de -> ToolUtil.findComponentImplementationBoc(de)).collect(Collectors.toList());
// Require at least one component implement BOC and the first must be non-null.
if (ciBocs.size() == 0 || ciBocs.get(0) == null) {
return false;
}
// Require all component implementation BOCs to be equal
final BusinessObjectContext firstBoc = ciBocs.get(0);
return ciBocs.stream().allMatch(tmpBoc -> tmpBoc == firstBoc);
}
return false;
}
Aggregations