From a38b17a294432f8dc5825acd86b21925b83d1ed2 Mon Sep 17 00:00:00 2001 From: Laurent Redor Date: Mon, 27 May 2024 16:38:57 +0200 Subject: [PATCH] [396] Adapt NodeCreationEditPolicy to compute the target location - Constructors of CreationUtil have been improved to directly have LayoutData as parameter instead of location and size. Indeed, the location is relative to the parent edit part and for border nodes, the parent edit part is not systematically the "host" of the called policy. - In NodeCreationEditPolicy, in case of border nodes, the "host edit part" is not systematically considered (to compute the RootLayoutData for example). The correct edit part, a parent of the host, is computed according to the mapping defined in the used tool. Bug: https://github.com/eclipse-sirius/sirius-desktop/issues/396 --- .../SequenceContainerCreationPolicy.java | 8 +- .../policy/SequenceNodeCreationPolicy.java | 13 ++- .../graphical/edit/policies/CreationUtil.java | 54 +++++---- .../edit/policies/NodeCreationEditPolicy.java | 106 ++++++++++++++---- 4 files changed, 123 insertions(+), 58 deletions(-) diff --git a/plugins/org.eclipse.sirius.diagram.sequence.ui/src/org/eclipse/sirius/diagram/sequence/ui/tool/internal/edit/policy/SequenceContainerCreationPolicy.java b/plugins/org.eclipse.sirius.diagram.sequence.ui/src/org/eclipse/sirius/diagram/sequence/ui/tool/internal/edit/policy/SequenceContainerCreationPolicy.java index 3972dcf652..9b9eea3731 100644 --- a/plugins/org.eclipse.sirius.diagram.sequence.ui/src/org/eclipse/sirius/diagram/sequence/ui/tool/internal/edit/policy/SequenceContainerCreationPolicy.java +++ b/plugins/org.eclipse.sirius.diagram.sequence.ui/src/org/eclipse/sirius/diagram/sequence/ui/tool/internal/edit/policy/SequenceContainerCreationPolicy.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010, 2021 THALES GLOBAL SERVICES and others. + * Copyright (c) 2010, 2024 THALES GLOBAL SERVICES and others. * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 * which accompanies this distribution, and is available at @@ -101,7 +101,7 @@ protected Command getCreateNodeOnDiagramCommand(CreateRequest request, NodeCreat finishingEndEndPredecessor = SequenceGraphicalHelper.getEndBefore(diag, location.y + size.height); } - CreationUtil creationUtil = new CreationUtil(request, getDiagramCommandFactory(startingEndPredecessor, finishingEndEndPredecessor, location), getRealLocation(request), request.getSize(), + CreationUtil creationUtil = new CreationUtil(getDiagramCommandFactory(startingEndPredecessor, finishingEndEndPredecessor, location), getRealLocation(request), request.getSize(), getHost()); result = creationUtil.getNodeCreationCommand(diagram, tool); } else if (tool instanceof InstanceRoleCreationTool && diagram instanceof SequenceDDiagram) { @@ -110,7 +110,7 @@ protected Command getCreateNodeOnDiagramCommand(CreateRequest request, NodeCreat GraphicalHelper.screen2logical(location, (IGraphicalEditPart) getHost()); EObject predecessor = SequenceGraphicalHelper.getInstanceRoleBefore(diag, location.x); - CreationUtil creationUtil = new CreationUtil(request, getDiagramCommandFactory(predecessor, location), getRealLocation(request), request.getSize(), getHost()); + CreationUtil creationUtil = new CreationUtil(getDiagramCommandFactory(predecessor, location), getRealLocation(request), request.getSize(), getHost()); result = creationUtil.getNodeCreationCommand(diagram, tool); } else { result = super.getCreateNodeOnDiagramCommand(request, tool, diagram); @@ -140,7 +140,7 @@ protected Command getCreateContainerOnDiagramCommand(CreateRequest request, Cont List coverage = creationValidator.getCoverage(); Range expansionZone = creationValidator.getExpansionZone(); - CreationUtil creationUtil = new CreationUtil(request, getDiagramCommandFactory(startingEndPredecessor, finishingEndPredecessor, coverage, getCreationRange(request)), + CreationUtil creationUtil = new CreationUtil(getDiagramCommandFactory(startingEndPredecessor, finishingEndPredecessor, coverage, getCreationRange(request)), getRealLocation(request), getRealSize(ccdTool, request), getHost()); result = creationUtil.getContainerCreationDescription(diagram, ccdTool); diff --git a/plugins/org.eclipse.sirius.diagram.sequence.ui/src/org/eclipse/sirius/diagram/sequence/ui/tool/internal/edit/policy/SequenceNodeCreationPolicy.java b/plugins/org.eclipse.sirius.diagram.sequence.ui/src/org/eclipse/sirius/diagram/sequence/ui/tool/internal/edit/policy/SequenceNodeCreationPolicy.java index b6556720bc..f4930400bd 100644 --- a/plugins/org.eclipse.sirius.diagram.sequence.ui/src/org/eclipse/sirius/diagram/sequence/ui/tool/internal/edit/policy/SequenceNodeCreationPolicy.java +++ b/plugins/org.eclipse.sirius.diagram.sequence.ui/src/org/eclipse/sirius/diagram/sequence/ui/tool/internal/edit/policy/SequenceNodeCreationPolicy.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010, 2013 THALES GLOBAL SERVICES. + * Copyright (c) 2010, 2024 THALES GLOBAL SERVICES. * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 * which accompanies this distribution, and is available at @@ -148,7 +148,7 @@ public void eraseTargetFeedback(Request request) { * {@inheritDoc} */ @Override - protected Command getCreateNodeOnNodeCommand(CreateRequest request, NodeCreationDescription tool, DNode viewnode) { + protected Command getCreateNodeOnNodeCommand(CreateRequest request, NodeCreationDescription tool, DNode viewnode, EditPart parentEditPartToUse) { if (tool instanceof ExecutionCreationTool || tool instanceof StateCreationTool || tool instanceof ObservationPointCreationTool) { SequenceDiagram sequenceDiagram = EditPartsHelper.getSequenceDiagram(getHost()); SequenceDDiagram diagram = sequenceDiagram.getSequenceDDiagram(); @@ -163,11 +163,11 @@ protected Command getCreateNodeOnNodeCommand(CreateRequest request, NodeCreation GraphicalHelper.logical2screen(bottomRight, (IGraphicalEditPart) getHost()); request.setSize(new Dimension(LayoutConstants.DEFAULT_EXECUTION_WIDTH, LayoutConstants.DEFAULT_EXECUTION_HEIGHT)); } - CreationUtil creationUtil = new CreationUtil(request, getDiagramCommandFactory(startingEndPredecessor, startingEndPredecessor, location), getRealLocation(request), request.getSize(), - getHost()); + CreationUtil creationUtil = new CreationUtil(getDiagramCommandFactory(startingEndPredecessor, startingEndPredecessor, location), getRealLocation(request, parentEditPartToUse), + request.getSize(), getHost()); return creationUtil.getNodeCreationCommand(viewnode, tool); } else { - return super.getCreateNodeOnNodeCommand(request, tool, viewnode); + return super.getCreateNodeOnNodeCommand(request, tool, viewnode, parentEditPartToUse); } } @@ -190,7 +190,8 @@ protected Command getCreateContainerInContainerCommand(CreateRequest request, Co Point location = request.getLocation().getCopy(); GraphicalHelper.screen2logical(location, (IGraphicalEditPart) getHost()); - CreationUtil creationUtil = new CreationUtil(request, getDiagramCommandFactory(startingEndPredecessor, startingEndPredecessor, location), getRealLocation(request), getHost()); + CreationUtil creationUtil = new CreationUtil(request, getDiagramCommandFactory(startingEndPredecessor, startingEndPredecessor, location), getRealLocation(request, getHost()), + getHost()); result = creationUtil.getContainerCreationDescription((DDiagramElementContainer) viewNodeContainer.eContainer(), tool); } else { result = UnexecutableCommand.INSTANCE; diff --git a/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/graphical/edit/policies/CreationUtil.java b/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/graphical/edit/policies/CreationUtil.java index 0c8caca00f..d76768e5bf 100644 --- a/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/graphical/edit/policies/CreationUtil.java +++ b/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/graphical/edit/policies/CreationUtil.java @@ -66,19 +66,13 @@ */ public class CreationUtil { - /** The location of the clicked point. */ - private final Point realLocation; - - /** The computed size of the element to create. */ - private final Dimension realSize; + /** The location of the clicked point, the size and the parent edit part of the element to create. */ + private final RootLayoutData rootLayoutData; /** The EMF Command Factory. */ private final IDiagramCommandFactory emfCommandFactory; - /** The request. */ - private final CreateRequest request; - - /** The edit part. */ + /** The edit part on which the calling policy is installed. */ private final EditPart editPart; /** @@ -91,18 +85,17 @@ public class CreationUtil { * @param realLocation * the location of the clicked point. * @param editPart - * the edit part + * the edit part on which the calling policy is installed. * @since 0.9.0 */ public CreationUtil(final CreateRequest request, final IDiagramCommandFactory commandFactory, final Point realLocation, final EditPart editPart) { - this(request, commandFactory, realLocation, null, editPart); + // The size of the request take into account the zoom (got the size in 100%) + this(commandFactory, new RootLayoutData(editPart, realLocation.getCopy(), CreationUtil.adaptRequestSizeToZoomFactor(request, editPart)), editPart); } /** * Creates a new CreationUtil with the specified request and location. * - * @param request - * the request. * @param commandFactory * the emf command factory. * @param realLocation @@ -110,14 +103,27 @@ public CreationUtil(final CreateRequest request, final IDiagramCommandFactory co * @param realSize * the computed size of the element to create, null if the default size must be used * @param editPart - * the edit part + * the edit part on which the calling policy is installed. * @since 0.9.0 */ - public CreationUtil(final CreateRequest request, final IDiagramCommandFactory commandFactory, final Point realLocation, final Dimension realSize, final EditPart editPart) { - this.realLocation = realLocation; - this.realSize = realSize; - this.request = request; + public CreationUtil(final IDiagramCommandFactory commandFactory, final Point realLocation, final Dimension realSize, final EditPart editPart) { + this(commandFactory, new RootLayoutData(editPart, realLocation.getCopy(), realSize == null ? null : realSize.getCopy()), editPart); + } + + /** + * Creates a new CreationUtil with the specified request and location. + * + * @param commandFactory + * the emf command factory. + * @param rootLayoutData + * the layout data for the created element (clicked point, size and parent edit part). + * @param editPart + * the edit part on which the calling policy is installed. + * @since 0.9.0 + */ + public CreationUtil(final IDiagramCommandFactory commandFactory, final RootLayoutData rootLayoutData, final EditPart editPart) { this.emfCommandFactory = commandFactory; + this.rootLayoutData = rootLayoutData; this.editPart = editPart; } @@ -314,15 +320,7 @@ private Command createLayoutDataCommand() { return new Command() { @Override public void execute() { - // The size of the request take into account the zoom (got - // the size in 100%) - Dimension size = null; - if (realSize != null) { - size = realSize.getCopy(); - } else { - size = adaptRequestSizeToZoomFactor(); - } - SiriusLayoutDataManager.INSTANCE.addData(new RootLayoutData(editPart, realLocation.getCopy(), size)); + SiriusLayoutDataManager.INSTANCE.addData(rootLayoutData); } }; } @@ -332,7 +330,7 @@ public void execute() { * * @return A new dimension */ - private Dimension adaptRequestSizeToZoomFactor() { + public static Dimension adaptRequestSizeToZoomFactor(CreateRequest request, EditPart editPart) { if (request.getSize() == null) { return null; } diff --git a/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/graphical/edit/policies/NodeCreationEditPolicy.java b/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/graphical/edit/policies/NodeCreationEditPolicy.java index 9417512a02..55a4d5285f 100644 --- a/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/graphical/edit/policies/NodeCreationEditPolicy.java +++ b/plugins/org.eclipse.sirius.diagram.ui/src-diag/org/eclipse/sirius/diagram/ui/graphical/edit/policies/NodeCreationEditPolicy.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2009 THALES GLOBAL SERVICES. + * Copyright (c) 2007, 2024 THALES GLOBAL SERVICES. * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 * which accompanies this distribution, and is available at @@ -12,23 +12,34 @@ *******************************************************************************/ package org.eclipse.sirius.diagram.ui.graphical.edit.policies; +import java.util.Optional; + import org.eclipse.draw2d.IFigure; import org.eclipse.draw2d.geometry.Point; +import org.eclipse.emf.common.util.EList; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.transaction.TransactionalEditingDomain; import org.eclipse.emf.transaction.util.TransactionUtil; +import org.eclipse.gef.EditPart; import org.eclipse.gef.commands.Command; import org.eclipse.gef.requests.CreateRequest; import org.eclipse.gmf.runtime.diagram.ui.editparts.GraphicalEditPart; import org.eclipse.gmf.runtime.diagram.ui.figures.ResizableCompartmentFigure; import org.eclipse.gmf.runtime.notation.Node; +import org.eclipse.sirius.diagram.AbstractDNode; import org.eclipse.sirius.diagram.DDiagramElementContainer; import org.eclipse.sirius.diagram.DNode; +import org.eclipse.sirius.diagram.description.AbstractNodeMapping; +import org.eclipse.sirius.diagram.description.NodeMapping; import org.eclipse.sirius.diagram.description.tool.ContainerCreationDescription; import org.eclipse.sirius.diagram.description.tool.NodeCreationDescription; +import org.eclipse.sirius.diagram.model.business.internal.helper.MappingHelper; import org.eclipse.sirius.diagram.tools.api.command.IDiagramCommandFactory; import org.eclipse.sirius.diagram.tools.api.command.IDiagramCommandFactoryProvider; import org.eclipse.sirius.diagram.ui.business.internal.query.RequestQuery; +import org.eclipse.sirius.diagram.ui.business.internal.view.RootLayoutData; +import org.eclipse.sirius.diagram.ui.edit.api.part.AbstractDiagramContainerEditPart; +import org.eclipse.sirius.diagram.ui.internal.edit.parts.AbstractDNodeListCompartmentEditPart; import org.eclipse.sirius.diagram.ui.tools.api.draw2d.ui.figures.FigureUtilities; import org.eclipse.sirius.diagram.ui.tools.api.editor.DDiagramEditor; import org.eclipse.sirius.viewpoint.description.tool.AbstractToolDescription; @@ -44,28 +55,41 @@ public class NodeCreationEditPolicy extends SiriusContainerEditPolicy { */ @Override protected Command getCreateCommand(CreateRequest request) { - if (!(getHost().getModel() instanceof Node)) { + + AbstractToolDescription tool = getTool(request); + GraphicalEditPart hostEditPartToUse = (GraphicalEditPart) getHost(); + if (getHost() instanceof GraphicalEditPart) { + boolean isBorderNodeCreationRequest = new RequestQuery(request).isDropOrCreationOfBorderNode(); + if (tool instanceof NodeCreationDescription nodeCreationDescriptionTool && isBorderNodeCreationRequest) { + // Search the correct edit part for this tool. It can be different than the host in case of "extra + // mappings" defined in the tool. + Optional optionalEditPartToUse = getParentEditPartWithExpectedMapping((GraphicalEditPart) getHost(), nodeCreationDescriptionTool.getNodeMappings()); + if (optionalEditPartToUse.isPresent()) { + hostEditPartToUse = optionalEditPartToUse.get(); + } + } + } + if (!(hostEditPartToUse.getModel() instanceof Node)) { return null; } + EObject containerElement = ((Node) hostEditPartToUse.getModel()).getElement(); - EObject containerElement = ((Node) getHost().getModel()).getElement(); - AbstractToolDescription tool = getTool(request); /* - * Dispatch to the appropriate specialized command depending on the type - * of the container element and the nature of the tool. + * Dispatch to the appropriate specialized command depending on the type of the container element and the nature + * of the tool. */ Command result = null; if (containerElement instanceof DDiagramElementContainer) { DDiagramElementContainer viewNodeContainer = (DDiagramElementContainer) containerElement; if (tool instanceof NodeCreationDescription) { - result = getCreateNodeInContainerCommand(request, (NodeCreationDescription) tool, viewNodeContainer); + result = getCreateNodeInContainerCommand(request, (NodeCreationDescription) tool, viewNodeContainer, hostEditPartToUse); } else if (tool instanceof ContainerCreationDescription) { result = getCreateContainerInContainerCommand(request, (ContainerCreationDescription) tool, viewNodeContainer); } } else if (containerElement instanceof DNode) { DNode viewNode = (DNode) containerElement; if (tool instanceof NodeCreationDescription) { - result = getCreateNodeOnNodeCommand(request, (NodeCreationDescription) tool, viewNode); + result = getCreateNodeOnNodeCommand(request, (NodeCreationDescription) tool, viewNode, hostEditPartToUse); } } return result; @@ -82,8 +106,8 @@ protected Command getCreateCommand(CreateRequest request) { * the node on which to create the new (bordered) node. * @return a command to create the new node. */ - protected Command getCreateNodeOnNodeCommand(CreateRequest request, NodeCreationDescription tool, DNode viewnode) { - CreationUtil creationUtil = new CreationUtil(request, getDiagramCommandFactory(), getRealLocation(request), getHost()); + protected Command getCreateNodeOnNodeCommand(CreateRequest request, NodeCreationDescription tool, DNode viewnode, EditPart parentEditPartToUse) { + CreationUtil creationUtil = new CreationUtil(getDiagramCommandFactory(), getRealLayoutData(request, parentEditPartToUse), parentEditPartToUse); return creationUtil.getNodeCreationCommand(viewnode, tool); } @@ -99,7 +123,7 @@ protected Command getCreateNodeOnNodeCommand(CreateRequest request, NodeCreation * @return a command to create the new container. */ protected Command getCreateContainerInContainerCommand(CreateRequest request, ContainerCreationDescription tool, DDiagramElementContainer viewNodeContainer) { - CreationUtil creationUtil = new CreationUtil(request, getDiagramCommandFactory(), getRealLocation(request), getHost()); + CreationUtil creationUtil = new CreationUtil(request, getDiagramCommandFactory(), getRealLocation(request, getHost()), getHost()); return creationUtil.getContainerCreationDescription(viewNodeContainer, tool); } @@ -112,10 +136,13 @@ protected Command getCreateContainerInContainerCommand(CreateRequest request, Co * the node creation tool description. * @param viewNodeContainer * the container on which to create the new (bordered) node. + * @param parentEditPartToUse + * parent EditPart to retrieve layout data (can be same as getHost(), but can also be another edit part + * according to extra mapping defined in tool, for border nodes for example). * @return a command to create the new node. */ - protected Command getCreateNodeInContainerCommand(CreateRequest request, NodeCreationDescription tool, DDiagramElementContainer viewNodeContainer) { - CreationUtil creationUtil = new CreationUtil(request, getDiagramCommandFactory(), getRealLocation(request), getHost()); + protected Command getCreateNodeInContainerCommand(CreateRequest request, NodeCreationDescription tool, DDiagramElementContainer viewNodeContainer, EditPart parentEditPartToUse) { + CreationUtil creationUtil = new CreationUtil(getDiagramCommandFactory(), getRealLayoutData(request, parentEditPartToUse), parentEditPartToUse); return creationUtil.getNodeCreationCommand(viewNodeContainer, tool); } @@ -135,18 +162,34 @@ protected AbstractToolDescription getTool(CreateRequest request) { } /** - * Computes the real location where the element must be created from the raw - * information passed in the request. + * Computes the real location where the element must be created from the raw information passed in the request. * * @param request * the creation request. + * @param parentEditPartToUse + * parent EditPart to retrieve layout data (can be same as getHost(), but can also be another edit part + * according to extra mapping defined in tool, for border nodes for example). * @return the real location where the element must be created. */ - protected Point getRealLocation(final CreateRequest request) { + protected Point getRealLocation(final CreateRequest request, EditPart parentEditPartToUse) { + return getRealLayoutData(request, parentEditPartToUse).getLocation(); + } + + /** + * Computes the real location where the element must be created from the raw information passed in the request. + * + * @param request + * the creation request. + * @param parentEditPartToUse + * parent EditPart to retrieve layout data (can be same as getHost(), but can also be another edit part + * according to extra mapping defined in tool, for border nodes for example). + * @return the real location where the element must be created. + */ + protected RootLayoutData getRealLayoutData(final CreateRequest request, EditPart parentEditPartToUse) { Point location = request.getLocation().getCopy(); final Point realLocation; - if (location != null && getHost() instanceof GraphicalEditPart) { - final IFigure fig = ((GraphicalEditPart) getHost()).getFigure(); + if (location != null && parentEditPartToUse instanceof GraphicalEditPart graphicalParentEditPart) { + final IFigure fig = graphicalParentEditPart.getFigure(); fig.translateToRelative(location); final Point containerLocation = fig.getBounds().getLocation(); location = new Point(location.x - containerLocation.x, location.y - containerLocation.y); @@ -160,7 +203,7 @@ protected Point getRealLocation(final CreateRequest request) { } else { scrollOffset = ((ResizableCompartmentFigure) fig).getScrollPane().getViewport().getViewLocation(); } - final Point shiftFromMarginOffset = FigureUtilities.getShiftFromMarginOffset((ResizableCompartmentFigure) fig, isBorderNodeCreationRequest, getHost()); + final Point shiftFromMarginOffset = FigureUtilities.getShiftFromMarginOffset((ResizableCompartmentFigure) fig, isBorderNodeCreationRequest, parentEditPartToUse); realLocation = new Point(location.x + scrollOffset.x - shiftFromMarginOffset.x, location.y + scrollOffset.y - shiftFromMarginOffset.y); } else { @@ -169,7 +212,30 @@ protected Point getRealLocation(final CreateRequest request) { } else { realLocation = location; } - return realLocation; + return new RootLayoutData(parentEditPartToUse, realLocation.getCopy(), CreationUtil.adaptRequestSizeToZoomFactor(request, parentEditPartToUse)); + } + + private Optional getParentEditPartWithExpectedMapping(GraphicalEditPart editPart, EList nodeMappings) { + Optional result = Optional.empty(); + if (editPart instanceof AbstractDNodeListCompartmentEditPart) { + result = getParentEditPartWithExpectedMapping((GraphicalEditPart) editPart.getParent(), nodeMappings); + } else if (editPart.getParent() instanceof AbstractDiagramContainerEditPart && ((AbstractDiagramContainerEditPart) editPart.getParent()).isRegionContainer()) { + result = getParentEditPartWithExpectedMapping((AbstractDiagramContainerEditPart) editPart.getParent(), nodeMappings); + } else { + for (NodeMapping nodeMapping : nodeMappings) { + if (editPart != null && editPart.getModel() instanceof Node node && node.getElement() instanceof AbstractDNode abstractDNode + && abstractDNode.getMapping() instanceof AbstractNodeMapping abstractNodegetMapping) { + if (MappingHelper.getAllBorderedNodeMappings(abstractNodegetMapping).contains(nodeMapping)) { + result = Optional.of(editPart); + break; + } + } + } + } + if (result.isEmpty() && editPart.getParent() instanceof GraphicalEditPart graphicalEditPart) { + result = getParentEditPartWithExpectedMapping(graphicalEditPart, nodeMappings); + } + return result; } /**