use of org.osate.ge.gef.ContainerShape in project osate2 by osate.
the class ResizeInteraction method onMouseDragged.
@Override
protected Interaction.InteractionState onMouseDragged(final MouseEvent e) {
if (e.getButton() != MouseButton.PRIMARY) {
return super.onMouseDragged(e);
}
guides.reset();
final Transform sceneToDiagramTransform = editor.getGefDiagram().getSceneNode().getSceneToLocalTransform();
final Point2D eventInDiagram = sceneToDiagramTransform.transform(e.getSceneX(), e.getSceneY());
final Point2D totalDelta = eventInDiagram.subtract(initialClickLocationInDiagram);
final boolean snapToGrid = !e.isAltDown();
// Resize all selection diagram elements
for (final DiagramElementSnapshot snapshot : elementsToResize) {
// Determine position adjustment and new size
double newPositionX = snapshot.sceneNode.getLayoutX();
double newPositionY = snapshot.sceneNode.getLayoutY();
double newWidth = snapshot.boundsInDiagram.getWidth();
double newHeight = snapshot.boundsInDiagram.getHeight();
final Vector dir = handle.getDirection();
final Node container = InputEventHandlerUtil.getLogicalShapeContainer(snapshot.sceneNode);
//
// Determine the minimum layout X and Y values for shapes which will be repositioned during the resize.
// This value is used to constrain the new position of the node when the resize results in both a movement
// and a size change.
//
double minChildLayoutX = Double.POSITIVE_INFINITY;
double minChildLayoutY = Double.POSITIVE_INFINITY;
for (final DiagramElement childDiagramElement : snapshot.diagramElement.getChildren()) {
final Node childSceneNode = editor.getGefDiagram().getSceneNode(childDiagramElement);
if (childSceneNode instanceof ContainerShape) {
minChildLayoutX = Math.min(minChildLayoutX, childSceneNode.getLayoutX());
minChildLayoutY = Math.min(minChildLayoutY, childSceneNode.getLayoutY());
}
// Docked shapes are only repositioned in one axis.
if (childSceneNode instanceof DockedShape) {
final DockSide side = ((DockedShape) childSceneNode).getSide();
if (side.vertical) {
minChildLayoutY = Math.min(minChildLayoutY, childSceneNode.getLayoutY());
} else {
minChildLayoutX = Math.min(minChildLayoutX, childSceneNode.getLayoutX());
}
}
}
if (dir.x < 0) {
double newPositionDiagramX = InputEventHandlerUtil.snapX(editor, snapshot.boundsInDiagram.getMinX() + totalDelta.getX(), snapToGrid);
// It is critical to not consider children that are being repositioned. Otherwise the minimum width
// will change as the node is resized. The layout of such children are considered to ensure that the resize
// does not clip children not included in the minimum width.
final double minWidthOfNotRepositionedChildren = snapshot.sceneNode instanceof ContainerShape ? ((ContainerShape) snapshot.sceneNode).computeMinWidth(false) : snapshot.sceneNode.minWidth(-1);
newPositionDiagramX = Math.min(newPositionDiagramX, snapshot.boundsInDiagram.getMaxX() - minWidthOfNotRepositionedChildren);
newPositionX = snapshot.positionInLocal.getX() + (newPositionDiagramX - snapshot.boundsInDiagram.getMinX());
newPositionX = Math.min(newPositionX, snapshot.sceneNode.getLayoutX() + minChildLayoutX);
if (container instanceof ContainerShape) {
newPositionX = Math.max(newPositionX, 0);
}
newWidth = snapshot.boundsInDiagram.getWidth() + (snapshot.positionInLocal.getX() - newPositionX);
} else if (dir.x > 0) {
final double newMaxX = InputEventHandlerUtil.snapX(editor, snapshot.boundsInDiagram.getMaxX() + totalDelta.getX(), snapToGrid);
newWidth = newMaxX - snapshot.boundsInDiagram.getMinX();
}
if (dir.y < 0) {
double newPositionDiagramY = InputEventHandlerUtil.snapX(editor, snapshot.boundsInDiagram.getMinY() + totalDelta.getY(), snapToGrid);
// It is critical to not consider children that are being repositioned. Otherwise the minimum height
// will change as the node is resized. The layout of such children are considered to ensure that the resize
// does not clip children not included in the minimum height.
final double minHeightWithoutFreeChildren = snapshot.sceneNode instanceof ContainerShape ? ((ContainerShape) snapshot.sceneNode).computeMinHeight(false) : snapshot.sceneNode.minHeight(-1);
newPositionDiagramY = Math.min(newPositionDiagramY, snapshot.boundsInDiagram.getMaxY() - minHeightWithoutFreeChildren);
newPositionY = snapshot.positionInLocal.getY() + (newPositionDiagramY - snapshot.boundsInDiagram.getMinY());
newPositionY = Math.min(newPositionY, snapshot.sceneNode.getLayoutY() + minChildLayoutY);
if (container instanceof ContainerShape) {
newPositionY = Math.max(newPositionY, 0);
}
newHeight = snapshot.boundsInDiagram.getHeight() + (snapshot.positionInLocal.getY() - newPositionY);
} else if (dir.y > 0) {
final double newMaxY = InputEventHandlerUtil.snapX(editor, snapshot.boundsInDiagram.getMaxY() + totalDelta.getY(), snapToGrid);
newHeight = newMaxY - snapshot.boundsInDiagram.getMinY();
}
// Adjust the position and size
final Point2D currentPreferredPosition = PreferredPosition.get(snapshot.sceneNode);
if (currentPreferredPosition == null || currentPreferredPosition.getX() != newPositionX || currentPreferredPosition.getY() != newPositionY) {
PreferredPosition.set(snapshot.sceneNode, new Point2D(newPositionX, newPositionY));
final double dx = currentPreferredPosition == null ? 0 : (newPositionX - currentPreferredPosition.getX());
final double dy = currentPreferredPosition == null ? 0 : (newPositionY - currentPreferredPosition.getY());
// Reposition children so that their absolute positions do not change.
for (final DiagramElement childDiagramElement : snapshot.diagramElement.getChildren()) {
final Node childSceneNode = editor.getGefDiagram().getSceneNode(childDiagramElement);
if (childSceneNode instanceof ContainerShape || childSceneNode instanceof DockedShape || childSceneNode instanceof FlowIndicatorNode) {
final Point2D childPosition = PreferredPosition.get(childSceneNode);
if (childPosition != null) {
final double newPreferredPositionX;
final double newPreferredPositionY;
// This assumes the flow indicator is attaches to a vertical side.
if (childSceneNode instanceof FlowIndicatorNode) {
newPreferredPositionX = childPosition.getX();
newPreferredPositionY = childPosition.getY() - dy;
} else {
newPreferredPositionX = childPosition.getX() - dx;
newPreferredPositionY = childPosition.getY() - dy;
}
PreferredPosition.set(childSceneNode, new Point2D(newPreferredPositionX, newPreferredPositionY));
}
}
}
}
final ConfigureSize configureSize = (ConfigureSize) snapshot.sceneNode;
final double minWidth = snapshot.sceneNode.minWidth(-1);
final double minHeight = snapshot.sceneNode.minHeight(-1);
configureSize.setConfiguredWidth(Math.max(newWidth, minWidth));
configureSize.setConfiguredHeight(Math.max(newHeight, minHeight));
// Update guide overlay
if (guides.shouldUpdate()) {
final Bounds newBoundsInDiagram = sceneToDiagramTransform.transform(snapshot.sceneNode.getLocalToSceneTransform().transform(snapshot.sceneNode.getLayoutBounds()));
// Show guides for the values in the bounds that are being changed as part of the resize
if (dir.x < 0) {
guides.updateX(newBoundsInDiagram.getMinX());
guides.updateCenterX(newBoundsInDiagram.getCenterX());
} else if (dir.x > 0) {
guides.updateX(newBoundsInDiagram.getMaxX());
guides.updateCenterX(newBoundsInDiagram.getCenterX());
}
if (dir.y < 0) {
guides.updateY(newBoundsInDiagram.getMinY());
guides.updateCenterY(newBoundsInDiagram.getCenterY());
} else if (dir.y > 0) {
guides.updateY(newBoundsInDiagram.getMaxY());
guides.updateCenterY(newBoundsInDiagram.getCenterY());
}
}
}
return InteractionState.IN_PROGRESS;
}
use of org.osate.ge.gef.ContainerShape in project osate2 by osate.
the class Overlays method refresh.
/**
* Refreshes the overlays based on the current selection
* This should be called by the editor whenever a change could affect the overlay.
* Specifically, it needs to be called whenever the diagram changes. Connection diagram elements may change to shapes and vice versa
* which would cause the nodes to change without changing the selected diagram elements.
* @param selection the current selection.
*/
@SuppressWarnings("unchecked")
public void refresh(final IStructuredSelection selection) {
Display.getCurrent().asyncExec(() -> {
final ImmutableMap.Builder<DiagramElement, SelectedNodeOverlay> newDiagramElementToSelectedNodeOverlayMapBuilder = ImmutableMap.builderWithExpectedSize(selection.size());
final ArrayList<DiagramElement> selectedDiagramElements = selectionToDiagramElements(selection);
// Add existing selected node overlays for selected diagram elements to new map.
for (final Entry<DiagramElement, SelectedNodeOverlay> existingEntry : diagramElementToSelectedNodeOverlayMap.entrySet()) {
if (selectedDiagramElements.contains(existingEntry.getKey()) && gefDiagram.getSceneNode(existingEntry.getKey()) == existingEntry.getValue().getSelectedNode()) {
newDiagramElementToSelectedNodeOverlayMapBuilder.put(existingEntry.getKey(), existingEntry.getValue());
}
}
// Create selected node overlays for newly selected nodes.
for (int i = 0; i < selectedDiagramElements.size(); i++) {
final DiagramElement selectedDiagramElement = selectedDiagramElements.get(i);
final boolean primary = i == selectedDiagramElements.size() - 1;
final SelectedNodeOverlay existingOverlay = diagramElementToSelectedNodeOverlayMap.get(selectedDiagramElement);
if (diagramElementToSelectedNodeOverlayMap.containsKey(selectedDiagramElement)) {
// Set whether it is primary
existingOverlay.setPrimary(primary);
} else {
final Node selectedNode = gefDiagram.getSceneNode(selectedDiagramElement);
if (selectedNode != null) {
if (selectedNode instanceof ContainerShape || selectedNode instanceof DockedShape || selectedNode instanceof LabelNode) {
newDiagramElementToSelectedNodeOverlayMapBuilder.put(selectedDiagramElement, new SelectedShapeOverlay(this, selectedDiagramElement, selectedNode, primary));
} else if (selectedNode instanceof BaseConnectionNode) {
// Create overlay for connection nodes
newDiagramElementToSelectedNodeOverlayMapBuilder.put(selectedDiagramElement, new SelectedConnectionOverlay(this, selectedDiagramElement, (BaseConnectionNode) selectedNode, primary));
}
}
}
}
diagramElementToSelectedNodeOverlayMap = newDiagramElementToSelectedNodeOverlayMapBuilder.build();
// Update children to reflect the new nodes.
selectionOverlays.getChildren().setAll((Collection<? extends Node>) diagramElementToSelectedNodeOverlayMap.values());
});
}
Aggregations