use of org.osate.ge.internal.diagram.runtime.DockArea in project osate2 by osate.
the class DiagramElementLayoutUtil method getNonGroupDockArea.
/**
* Walks up the tree from the given node and returns the first dock area that isn't the group dock area.
* Checks the specified diagram node and then ancestors.
* @param diagramNode is the diagram for which to return the non group docker area.
* @return the first dock area that isn't the group dock area.
*/
public static DockArea getNonGroupDockArea(DiagramNode diagramNode) {
DockArea result = null;
do {
if (!(diagramNode instanceof DiagramElement)) {
result = null;
break;
}
result = ((DiagramElement) diagramNode).getDockArea();
diagramNode = diagramNode.getParent();
} while (result != null && result == DockArea.GROUP);
return result;
}
use of org.osate.ge.internal.diagram.runtime.DockArea in project osate2 by osate.
the class DiagramElementLayoutUtil method layoutIncrementally.
/**
* Performs layout on elements in the specified diagram which have not been laid out.
* @param diagram the diagram for which to perform the incremental layout
* @param mod the modification to use to modify the diagram
* @param layoutInfoProvider the layout info provider which provides additional information required for laying out the diagram
*/
public static void layoutIncrementally(final AgeDiagram diagram, final DiagramModification mod, final LayoutInfoProvider layoutInfoProvider) {
Objects.requireNonNull(diagram, "diagram must not be null");
Objects.requireNonNull(mod, "mod must not be null");
Objects.requireNonNull(layoutInfoProvider, "layoutInfoProvider must not be null");
final IncrementalLayoutMode currentLayoutMode = LayoutPreferences.getCurrentIncrementalLayoutMode();
// Get all the nodes that need to be layed out.
final Set<DiagramNode> unfilteredNodesToLayout = getNodesToLayoutIncrementally(diagram, currentLayoutMode, new HashSet<>());
if (unfilteredNodesToLayout.size() == 0) {
return;
}
// Lay our flow indicators. In the container is eventually layed out, this will be replaced but in cases where that is not the case,
// we provide a default layout. Flow indicators are connections and as such will be filtered in the next step.
layoutFlowIndicators(mod, unfilteredNodesToLayout.stream().filter(DiagramNodePredicates::isFlowIndicator).map(DiagramElement.class::cast), layoutInfoProvider);
final Collection<DiagramNode> nodesToLayout = DiagramElementLayoutUtil.filterUnnecessaryNodes(unfilteredNodesToLayout, currentLayoutMode == IncrementalLayoutMode.LAYOUT_DIAGRAM);
if (nodesToLayout.size() == 0) {
// If the filtered node list is empty then the unfiltered list still contain feature self loop connections that need to be layed out.
unfilteredNodesToLayout.stream().filter(DiagramElementLayoutUtil::isFeatureSelfLoopConnection).map(DiagramElement.class::cast).forEachOrdered(de -> layoutFeatureSelfLoopConnection(de, mod, layoutInfoProvider));
return;
}
final LayoutOptions layoutOptions = LayoutOptions.createFromPreferences();
if (currentLayoutMode == IncrementalLayoutMode.LAYOUT_DIAGRAM) {
layout(INCREMENTAL_LAYOUT_LABEL, diagram, layoutInfoProvider, layoutOptions);
} else {
layout(mod, nodesToLayout, new StyleCalculator(diagram.getConfiguration(), StyleProvider.EMPTY), layoutInfoProvider, layoutOptions);
// Set Positions of elements which do not have a position set.
for (final DiagramNode dn : nodesToLayout) {
if (dn instanceof DiagramElement) {
final DiagramElement de = (DiagramElement) dn;
if (!de.hasPosition()) {
if (de.getDockArea() == null) {
mod.setPosition(de, new Point(0.0, 0.0));
} else if (de.getDockArea() != DockArea.GROUP && de.getParent() instanceof DiagramElement) {
final DiagramElement parent = (DiagramElement) de.getParent();
final DockingPosition defaultDockingPosition = de.getGraphicalConfiguration().getDefaultDockingPosition();
final DockArea defaultDockArea = DockArea.fromDockingPosition(defaultDockingPosition);
if (parent.hasSize()) {
final Stream<DiagramElement> otherElementsAlongSide = parent.getChildren().stream().filter(c -> c.hasPosition() && c.hasSize() && c.getDockArea() == defaultDockArea);
// Determine the position of the new element along it's preferred docking position.
double locationAlongSide;
if (defaultDockingPosition == DockingPosition.TOP || defaultDockingPosition == DockingPosition.BOTTOM) {
locationAlongSide = otherElementsAlongSide.max(Comparator.comparingDouble(c -> c.getY())).map(c -> c.getX() + c.getWidth()).orElse(0.0);
} else {
locationAlongSide = otherElementsAlongSide.max(Comparator.comparingDouble(c -> c.getY())).map(c -> c.getY() + c.getHeight()).orElse(0.0);
}
// Set position based on the docking position
switch(defaultDockingPosition) {
case TOP:
mod.setPosition(de, new Point(locationAlongSide, 0));
break;
case BOTTOM:
mod.setPosition(de, new Point(locationAlongSide, parent.getHeight()));
break;
case LEFT:
mod.setPosition(de, new Point(0, locationAlongSide));
break;
case RIGHT:
mod.setPosition(de, new Point(parent.getWidth(), locationAlongSide));
break;
default:
break;
}
}
mod.setDockArea(de, defaultDockArea);
}
}
}
}
}
}
use of org.osate.ge.internal.diagram.runtime.DockArea in project osate2 by osate.
the class GefAgeDiagram method ensureSceneNodeExists.
/**
* Ensures that a scene node exists for the specified GEF diagram element.
* Creates or recreates scene nodes and adds to the scene graph as necessary. Updates the specified GEF diagram element.
* @param gefDiagramElement the GEF diagram element for which to ensure that the scene node exists.
* @param parentDiagramElementSceneNode the scene node for the parent of the GEF diagram element. This is specified instead of using
* the value contained in the GEF diagram element because it may not be up to date.
* @return the scene node for the diagram element. This specified GEF diagram element will be updated to hold this value.
*/
private Node ensureSceneNodeExists(GefDiagramElement gefDiagramElement, final Node parentDiagramElementSceneNode) {
Objects.requireNonNull(parentDiagramElementSceneNode, "parentDiagramElementScenenNode must not be null");
final Graphic graphic = Objects.requireNonNull(gefDiagramElement.diagramElement.getGraphic(), "graphic must not be null");
final DiagramElement childDiagramElement = gefDiagramElement.diagramElement;
//
// The following final variables determine the operations that needs to be performed by the remainder of the function.
// They are set by comparing the previous state with the current state of the diagram element.
//
final boolean docked = childDiagramElement.getDockArea() != null;
final boolean parentIsConnection = parentDiagramElementSceneNode instanceof BaseConnectionNode;
final boolean create = !Objects.equals(graphic, gefDiagramElement.sourceGraphic) || docked != gefDiagramElement.sceneNode instanceof DockedShape || parentIsConnection != gefDiagramElement.parentDiagramNodeSceneNode instanceof BaseConnectionNode;
final boolean addToScene = create || gefDiagramElement.parentDiagramNodeSceneNode != parentDiagramElementSceneNode;
final boolean removeFromScene = addToScene && gefDiagramElement.sceneNode != null;
// Update other fields
gefDiagramElement.sourceGraphic = graphic;
// Remove the node for the scene graph
if (removeFromScene) {
removeNode(gefDiagramElement.sceneNode);
}
//
if (create) {
// Remove mapping to old scene node
if (gefDiagramElement.sceneNode != null) {
sceneNodeToGefDiagramElementMap.remove(gefDiagramElement.sceneNode);
}
// Create the new node. Create a graphic and then a wrapper as appropriate
final Node graphicNode = GraphicToFx.createNode(graphic);
if (graphicNode instanceof BaseConnectionNode) {
final BaseConnectionNode newConnectionNode = (BaseConnectionNode) graphicNode;
gefDiagramElement.sceneNode = graphicNode;
// Create the primary label node
final LabelNode primaryLabel = new LabelNode();
newConnectionNode.getPrimaryLabels().add(primaryLabel);
gefDiagramElement.primaryLabel = primaryLabel;
} else if (graphicNode instanceof LabelNode) {
gefDiagramElement.sceneNode = graphicNode;
} else if (parentIsConnection) {
// NOTE: This should only occur for fixed sized graphics
// Rotate midpoint decorations 180.0 degrees because our connection not expects midpoint decorations to be oriented as if
// the connection was left to right and that is not how graphics are specified in the graphical editor.
final Group rotationWrapper = new Group();
rotationWrapper.getChildren().add(graphicNode);
rotationWrapper.setRotate(180.0);
gefDiagramElement.sceneNode = rotationWrapper;
} else {
if (docked) {
final DockedShape newDockedShape = new DockedShape();
newDockedShape.setGraphic(graphicNode);
gefDiagramElement.sceneNode = newDockedShape;
// Create the primary label node
final LabelNode primaryLabel = new LabelNode();
newDockedShape.getPrimaryLabels().add(primaryLabel);
gefDiagramElement.primaryLabel = primaryLabel;
// Create annotation node
final LabelNode annotationLabel = new LabelNode();
newDockedShape.getSecondaryLabels().add(annotationLabel);
gefDiagramElement.annotationLabel = annotationLabel;
} else {
final ContainerShape newContainerShape = new ContainerShape();
newContainerShape.setGraphic(graphicNode);
gefDiagramElement.sceneNode = newContainerShape;
// Create the primary label node
final LabelNode primaryLabel = new LabelNode();
newContainerShape.getPrimaryLabels().add(primaryLabel);
gefDiagramElement.primaryLabel = primaryLabel;
}
}
// Add mapping to scene node
if (gefDiagramElement.sceneNode != null) {
sceneNodeToGefDiagramElementMap.put(gefDiagramElement.sceneNode, gefDiagramElement);
}
StyleRoot.set(gefDiagramElement.sceneNode, true);
}
//
if (addToScene) {
if (gefDiagramElement.sceneNode instanceof BaseConnectionNode) {
diagramNode.getChildren().add(gefDiagramElement.sceneNode);
// Flow indicators are positioned relative to the scene node of the parent diagram element
if (gefDiagramElement.sceneNode instanceof FlowIndicatorNode) {
if (parentDiagramElementSceneNode instanceof ContainerShape) {
((FlowIndicatorNode) gefDiagramElement.sceneNode).setPositioningReference(parentDiagramElementSceneNode);
} else {
throw new AgeGefRuntimeException("Unexpected parent diagram element scene node for flow indicator: " + parentDiagramElementSceneNode);
}
}
} else if (gefDiagramElement.sceneNode instanceof LabelNode) {
// Add label to parent
if (parentDiagramElementSceneNode instanceof ContainerShape) {
((ContainerShape) parentDiagramElementSceneNode).getSecondaryLabels().add(gefDiagramElement.sceneNode);
} else if (parentDiagramElementSceneNode instanceof DockedShape) {
((DockedShape) parentDiagramElementSceneNode).getSecondaryLabels().add(gefDiagramElement.sceneNode);
} else if (parentDiagramElementSceneNode instanceof BaseConnectionNode) {
((BaseConnectionNode) parentDiagramElementSceneNode).getSecondaryLabels().add(gefDiagramElement.sceneNode);
} else {
throw new AgeGefRuntimeException("Unexpected parent node for label: " + parentDiagramElementSceneNode);
}
} else if (parentIsConnection) {
((BaseConnectionNode) parentDiagramElementSceneNode).getMidpointDecorations().add(gefDiagramElement.sceneNode);
} else {
final DockArea dockArea = childDiagramElement.getDockArea();
if (gefDiagramElement.sceneNode instanceof DockedShape) {
final DockedShape dockedShape = (DockedShape) gefDiagramElement.sceneNode;
// Add the docked shape to the appropriate list
if (parentDiagramElementSceneNode instanceof ContainerShape) {
final ContainerShape containerShapeParent = (ContainerShape) parentDiagramElementSceneNode;
containerShapeParent.addOrUpdateDockedChild(dockedShape, GefAgeDiagramUtil.toDockSide(dockArea));
} else if (parentDiagramElementSceneNode instanceof DockedShape) {
final DockedShape dockedShapeParent = (DockedShape) parentDiagramElementSceneNode;
dockedShapeParent.getNestedChildren().add(dockedShape);
} else {
throw new AgeGefRuntimeException("Unexpected parent for docked shape: " + parentDiagramElementSceneNode);
}
} else {
if (parentDiagramElementSceneNode instanceof ContainerShape) {
final ContainerShape containerShapeParent = (ContainerShape) parentDiagramElementSceneNode;
containerShapeParent.getFreeChildren().add(gefDiagramElement.sceneNode);
} else if (parentDiagramElementSceneNode instanceof Group) {
((Group) parentDiagramElementSceneNode).getChildren().add(gefDiagramElement.sceneNode);
} else {
throw new AgeGefRuntimeException("Unexpected parent node for container shape: " + parentDiagramElementSceneNode);
}
}
}
gefDiagramElement.parentDiagramNodeSceneNode = parentDiagramElementSceneNode;
}
return gefDiagramElement.sceneNode;
}
use of org.osate.ge.internal.diagram.runtime.DockArea in project osate2 by osate.
the class GefAgeDiagram method updateSceneNode.
/**
* Updates the scene nodes related to the specified GEF diagram element based on the diagram element.
* Only updates properties which do not effect the structure of the scene graph. Not-recursive
* @param gefDiagramElement is the GEF diagram element for which scene nodes will be updated.
*/
private void updateSceneNode(final GefDiagramElement gefDiagramElement) {
final DiagramElement diagramElement = gefDiagramElement.diagramElement;
final Node sceneNode = gefDiagramElement.sceneNode;
// Update connections
if (sceneNode instanceof BaseConnectionNode) {
final BaseConnectionNode connectionNode = (BaseConnectionNode) sceneNode;
final Point controlPointOrigin = getControlPointOriginFromDiagram(diagramElement, sceneNode);
if (sceneNode instanceof FlowIndicatorNode) {
PreferredPosition.set(sceneNode, convertPoint(diagramElement.getPosition()));
}
// Update the connection anchor
updateConnectionAnchors(diagramElement, (BaseConnectionNode) sceneNode);
// Set control points. Coordinates are specified in the diagram model relative to the diagram. The need to be specified relative to the
// connection position. For regular connection this is the same because the node's parent is the diagram node.
// However, flow indicators have a position and have parent nodes other than the diagram.
connectionNode.getInnerConnection().setControlPoints(diagramElement.getBendpoints().stream().map(p -> new org.eclipse.gef.geometry.planar.Point(p.x - controlPointOrigin.x, p.y - controlPointOrigin.y)).collect(Collectors.toList()));
PreferredPosition.set(gefDiagramElement.primaryLabel, convertPoint(diagramElement.getConnectionPrimaryLabelPosition()));
} else if (sceneNode instanceof LabelNode) {
// Such a label represents a secondary label
final LabelNode label = (LabelNode) sceneNode;
label.setText(Strings.nullToEmpty(diagramElement.getLabelName()));
setLabelVisibility(label);
// Update element position
if (gefDiagramElement.parentDiagramNodeSceneNode instanceof BaseConnectionNode) {
PreferredPosition.set(label, convertPoint(diagramElement.getPosition()));
}
} else if (sceneNode instanceof ContainerShape) {
final ContainerShape containerShape = (ContainerShape) sceneNode;
PreferredPosition.set(sceneNode, convertPoint(diagramElement.getPosition()));
// Set configured size
final Dimension size = diagramElement.getSize();
if (size == null) {
containerShape.setConfiguredWidth(ContainerShape.NOT_SPECIFIED);
containerShape.setConfiguredHeight(ContainerShape.NOT_SPECIFIED);
} else {
containerShape.setConfiguredWidth(size.width);
containerShape.setConfiguredHeight(size.height);
}
} else if (sceneNode instanceof DockedShape) {
final DockedShape n = (DockedShape) sceneNode;
PreferredPosition.set(sceneNode, convertPoint(diagramElement.getPosition()));
// Set configured size
final Dimension size = diagramElement.getSize();
if (size == null) {
n.setConfiguredWidth(ContainerShape.NOT_SPECIFIED);
n.setConfiguredHeight(ContainerShape.NOT_SPECIFIED);
} else {
n.setConfiguredWidth(size.width);
n.setConfiguredHeight(size.height);
}
final DockArea dockArea = diagramElement.getDockArea();
if (dockArea != null && dockArea != DockArea.GROUP && gefDiagramElement.parentDiagramNodeSceneNode instanceof ContainerShape) {
final DockSide side = GefAgeDiagramUtil.toDockSide(dockArea);
final ContainerShape cs = (ContainerShape) gefDiagramElement.parentDiagramNodeSceneNode;
cs.addOrUpdateDockedChild(n, side);
}
}
// Update the primary label
if (gefDiagramElement.primaryLabel != null) {
gefDiagramElement.primaryLabel.setText(getPrimaryLabelText(diagramElement));
setLabelVisibility(gefDiagramElement.primaryLabel);
gefDiagramElement.primaryLabel.setWrapText(diagramElement.getGraphicalConfiguration().isPrimaryLabelIsMultiline());
}
// Update the secondary label
if (gefDiagramElement.annotationLabel != null) {
final String annotation = diagramElement.getGraphicalConfiguration().getAnnotation();
gefDiagramElement.annotationLabel.setText(Strings.nullToEmpty(annotation));
setLabelVisibility(gefDiagramElement.annotationLabel);
}
}
use of org.osate.ge.internal.diagram.runtime.DockArea in project osate2 by osate.
the class DiagramUpdaterTest method testDockArea.
// Test that element docking are works as expected
@Test
public void testDockArea() {
// Assign a Docking Position to an Element
final TestBusinessObject testBoParent = testModel.getModel().children[0];
final TestBusinessObject testBo = testBoParent.children[2];
testBo.setDefaultDockingPosition(DockingPosition.LEFT);
// Update the diagram and assign positions
diagramUpdater.updateDiagram(diagram);
assignPositions(diagram.getChildren());
// Check that the contents of test diagram element have the appropriate docking area
checkElements(diagram.getChildren(), testModel.getModel());
// Check that Changing the Docking Area and updating the diagram does not reset the docking area.
final DiagramElement dockableDiagramElement = diagram.getChildByRelativeReference(testBoParent.getRelativeReference()).getChildByRelativeReference(testBo.getRelativeReference());
assertThat(dockableDiagramElement.getDockArea(), is(equalTo(DockArea.fromDockingPosition(testBo.getDefaultDockingPosition()))));
final DockArea newDockArea = DockArea.fromDockingPosition(DockingPosition.RIGHT);
diagram.modify("Set Dock Area", m -> m.setDockArea(dockableDiagramElement, newDockArea));
diagramUpdater.updateDiagram(diagram);
assertThat(dockableDiagramElement.getDockArea(), is(equalTo(newDockArea)));
}
Aggregations