Search in sources :

Example 6 with ContainerShape

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;
}
Also used : Node(javafx.scene.Node) FlowIndicatorNode(org.osate.ge.gef.FlowIndicatorNode) DockedShape(org.osate.ge.gef.DockedShape) Bounds(javafx.geometry.Bounds) DiagramElement(org.osate.ge.internal.diagram.runtime.DiagramElement) FlowIndicatorNode(org.osate.ge.gef.FlowIndicatorNode) DockSide(org.osate.ge.gef.DockSide) Point2D(javafx.geometry.Point2D) ContainerShape(org.osate.ge.gef.ContainerShape) ConfigureSize(org.osate.ge.gef.ConfigureSize) Transform(javafx.scene.transform.Transform) Vector(org.eclipse.gef.geometry.euclidean.Vector)

Example 7 with ContainerShape

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());
    });
}
Also used : LabelNode(org.osate.ge.gef.LabelNode) LabelNode(org.osate.ge.gef.LabelNode) BaseConnectionNode(org.osate.ge.gef.BaseConnectionNode) Node(javafx.scene.Node) FlowIndicatorNode(org.osate.ge.gef.FlowIndicatorNode) DockedShape(org.osate.ge.gef.DockedShape) ImmutableMap(com.google.common.collect.ImmutableMap) Point(org.eclipse.gef.geometry.planar.Point) DiagramElement(org.osate.ge.internal.diagram.runtime.DiagramElement) ContainerShape(org.osate.ge.gef.ContainerShape) BaseConnectionNode(org.osate.ge.gef.BaseConnectionNode)

Aggregations

Node (javafx.scene.Node)7 ContainerShape (org.osate.ge.gef.ContainerShape)7 DockedShape (org.osate.ge.gef.DockedShape)6 FlowIndicatorNode (org.osate.ge.gef.FlowIndicatorNode)6 LabelNode (org.osate.ge.gef.LabelNode)6 BaseConnectionNode (org.osate.ge.gef.BaseConnectionNode)5 ConnectionNode (org.osate.ge.gef.ConnectionNode)5 DiagramElement (org.osate.ge.internal.diagram.runtime.DiagramElement)5 DockSide (org.osate.ge.gef.DockSide)4 DiagramNode (org.osate.ge.internal.diagram.runtime.DiagramNode)4 Bounds (javafx.geometry.Bounds)3 Point2D (javafx.geometry.Point2D)3 DiagramRootNode (org.osate.ge.gef.DiagramRootNode)3 FeatureGroupNode (org.osate.ge.gef.FeatureGroupNode)3 Transform (javafx.scene.transform.Transform)2 Dimension (org.osate.ge.graphics.Dimension)2 Point (org.osate.ge.graphics.Point)2 DockArea (org.osate.ge.internal.diagram.runtime.DockArea)2 ImmutableMap (com.google.common.collect.ImmutableMap)1 Arrays (java.util.Arrays)1