Search in sources :

Example 1 with ConfigureSize

use of org.osate.ge.gef.ConfigureSize 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)

Aggregations

Bounds (javafx.geometry.Bounds)1 Point2D (javafx.geometry.Point2D)1 Node (javafx.scene.Node)1 Transform (javafx.scene.transform.Transform)1 Vector (org.eclipse.gef.geometry.euclidean.Vector)1 ConfigureSize (org.osate.ge.gef.ConfigureSize)1 ContainerShape (org.osate.ge.gef.ContainerShape)1 DockSide (org.osate.ge.gef.DockSide)1 DockedShape (org.osate.ge.gef.DockedShape)1 FlowIndicatorNode (org.osate.ge.gef.FlowIndicatorNode)1 DiagramElement (org.osate.ge.internal.diagram.runtime.DiagramElement)1