From 521915eacc30587475d302159f82872bbf71c476 Mon Sep 17 00:00:00 2001 From: Florian Barbin Date: Tue, 18 Jun 2024 11:20:36 +0200 Subject: [PATCH] [2759] Reactivate the SelectionDialog In addition, this commit introduces the generic concept of Dialog to make it possible to define any kind of dialog for diagram node tools. Bug: https://github.com/eclipse-sirius/sirius-web/issues/2759 Signed-off-by: Florian Barbin --- CHANGELOG.adoc | 1 + doc/reference/variables.adoc | 13 + package-lock.json | 3 + .../CompatibilityPaletteProvider.java | 4 +- .../services/diagrams/ToolProvider.java | 14 +- ...eSingleClickOnDiagramElementToolInput.java | 5 +- .../dto/SingleClickOnDiagramElementTool.java | 12 +- .../diagrams/dto/ToolVariable.java | 21 + .../diagrams/dto/ToolVariableType.java | 33 + ...ClickOnDiagramElementToolEventHandler.java | 50 +- .../main/resources/schema/diagram.graphqls | 41 +- ...OnDiagramElementToolEventHandlerTests.java | 115 +- ...ramToolReferencePositionProviderTests.java | 6 +- .../tests/graphql/PaletteQueryRunner.java | 4 +- .../SingleClickOnDiagramElementTool.java | 16 +- .../src/dialog/DialogContext.tsx | 79 ++ .../src/dialog/DialogContext.types.ts | 33 + .../src/dialog/diagramDialogExtensionPoint.ts | 19 + .../diagramDialogExtensionPoint.types.ts | 26 + .../src/dialog/useDialog.tsx | 22 + .../src/dialog/useDialog.types.ts | 22 + .../sirius-components-diagrams/src/index.ts | 4 + .../src/renderer/DiagramRenderer.tsx | 5 +- .../src/renderer/edge/MultiLabelEdge.tsx | 10 +- .../src/renderer/node/FreeFormNode.tsx | 8 +- .../src/renderer/node/IconLabelNode.tsx | 8 +- .../src/renderer/node/ListNode.tsx | 6 +- .../palette/DiagramElementPalette.tsx | 64 +- .../palette/DiagramElementPalette.types.ts | 1 + .../src/renderer/palette/DiagramPalette.tsx | 10 +- .../renderer/palette/DiagramPalette.types.ts | 1 + .../src/renderer/palette/Palette.tsx | 31 +- .../src/renderer/palette/Palette.types.ts | 16 +- .../representation/DiagramRepresentation.tsx | 11 +- .../sirius-components-selection/package.json | 2 + .../src/SelectionDialog.tsx | 16 +- .../view/ViewDiagramIntegrationTests.java | 3 +- ...tElementLabelProviderIntegrationTests.java | 3 +- .../ExpandCollapseDiagramControllerTests.java | 5 +- .../ModelOperationDiagramControllerTests.java | 3 +- .../UnsynchronizedDiagramControllerTests.java | 2 +- .../VisibilityDiagramControllerTests.java | 16 +- .../extension/DefaultExtensionRegistry.tsx | 29 +- .../sirius-web/src/nodes/EllipseNode.tsx | 6 +- .../builder/generated/DiagramBuilders.java | 6 +- .../generated/DialogDescriptionBuilder.java | 31 + .../builder/generated/NodeToolBuilder.java | 8 +- ...=> SelectionDialogDescriptionBuilder.java} | 30 +- .../DiagramItemProviderAdapterFactory.java | 32 +- .../DialogDescriptionItemProvider.java | 115 ++ .../provider/NodeToolItemProvider.java | 8 +- ...lectionDialogDescriptionItemProvider.java} | 57 +- .../full/obj16/SelectionDialogDescription.svg | 1 + .../src/main/resources/plugin.properties | 416 +++--- .../view/diagram/ArrangeLayoutDirection.java | 30 +- .../view/diagram/DiagramDescription.java | 30 +- .../view/diagram/DiagramFactory.java | 7 +- .../view/diagram/DiagramPackage.java | 1163 +++++++++-------- .../view/diagram/DialogDescription.java | 27 + .../view/diagram/InsideLabelPosition.java | 48 +- .../view/diagram/LabelDescription.java | 24 +- .../view/diagram/LabelOverflowStrategy.java | 22 +- .../view/diagram/LabelTextAlign.java | 26 +- .../components/view/diagram/NodeTool.java | 27 +- ...n.java => SelectionDialogDescription.java} | 27 +- .../diagram/impl/DiagramDescriptionImpl.java | 49 +- .../view/diagram/impl/DiagramFactoryImpl.java | 14 +- .../view/diagram/impl/DiagramPackageImpl.java | 65 +- .../diagram/impl/DialogDescriptionImpl.java | 46 + .../diagram/impl/LabelDescriptionImpl.java | 58 +- .../view/diagram/impl/NodeToolImpl.java | 62 +- ...va => SelectionDialogDescriptionImpl.java} | 43 +- .../diagram/util/DiagramAdapterFactory.java | 36 +- .../view/diagram/util/DiagramSwitch.java | 193 +-- .../src/main/resources/model/diagram.ecore | 5 +- .../src/main/resources/model/diagram.genmodel | 9 +- .../components/view/emf/ViewConverter.java | 6 +- .../view/emf/diagram/ToolConverter.java | 2 +- .../view/emf/diagram/ViewPaletteProvider.java | 8 +- 79 files changed, 2239 insertions(+), 1291 deletions(-) create mode 100644 packages/diagrams/backend/sirius-components-collaborative-diagrams/src/main/java/org/eclipse/sirius/components/collaborative/diagrams/dto/ToolVariable.java create mode 100644 packages/diagrams/backend/sirius-components-collaborative-diagrams/src/main/java/org/eclipse/sirius/components/collaborative/diagrams/dto/ToolVariableType.java create mode 100644 packages/diagrams/frontend/sirius-components-diagrams/src/dialog/DialogContext.tsx create mode 100644 packages/diagrams/frontend/sirius-components-diagrams/src/dialog/DialogContext.types.ts create mode 100644 packages/diagrams/frontend/sirius-components-diagrams/src/dialog/diagramDialogExtensionPoint.ts create mode 100644 packages/diagrams/frontend/sirius-components-diagrams/src/dialog/diagramDialogExtensionPoint.types.ts create mode 100644 packages/diagrams/frontend/sirius-components-diagrams/src/dialog/useDialog.tsx create mode 100644 packages/diagrams/frontend/sirius-components-diagrams/src/dialog/useDialog.types.ts create mode 100644 packages/view/backend/sirius-components-view-builder/src/main/java/org/eclipse/sirius/components/view/builder/generated/DialogDescriptionBuilder.java rename packages/view/backend/sirius-components-view-builder/src/main/java/org/eclipse/sirius/components/view/builder/generated/{SelectionDescriptionBuilder.java => SelectionDialogDescriptionBuilder.java} (59%) create mode 100644 packages/view/backend/sirius-components-view-diagram-edit/src/main/java/org/eclipse/sirius/components/view/diagram/provider/DialogDescriptionItemProvider.java rename packages/view/backend/sirius-components-view-diagram-edit/src/main/java/org/eclipse/sirius/components/view/diagram/provider/{SelectionDescriptionItemProvider.java => SelectionDialogDescriptionItemProvider.java} (64%) create mode 100644 packages/view/backend/sirius-components-view-diagram-edit/src/main/resources/icons/full/obj16/SelectionDialogDescription.svg create mode 100644 packages/view/backend/sirius-components-view-diagram/src/main/java/org/eclipse/sirius/components/view/diagram/DialogDescription.java rename packages/view/backend/sirius-components-view-diagram/src/main/java/org/eclipse/sirius/components/view/diagram/{SelectionDescription.java => SelectionDialogDescription.java} (78%) create mode 100644 packages/view/backend/sirius-components-view-diagram/src/main/java/org/eclipse/sirius/components/view/diagram/impl/DialogDescriptionImpl.java rename packages/view/backend/sirius-components-view-diagram/src/main/java/org/eclipse/sirius/components/view/diagram/impl/{SelectionDescriptionImpl.java => SelectionDialogDescriptionImpl.java} (79%) diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index 48d6f2f381a..1df07ecf725 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -71,6 +71,7 @@ More existing APIs will be migrated to this new common pattern. - https://github.com/eclipse-sirius/sirius-web/issues/3666[#3666] [core] Enable EMF's intrinsicIDToEObjectMap for JSON resources to support languages which use modeled identifiers (e.g. SysMLv2). - https://github.com/eclipse-sirius/sirius-web/issues/3664[#3664] [core] The Default.svg image is no longer displayed with the new architecture. - https://github.com/eclipse-sirius/sirius-web/issues/3693[#3693] [view] Fix the computation of the candidates for the ReferenceWidget. +- https://github.com/eclipse-sirius/sirius-web/issues/2759[#2759] [diagram] Reactivate the Selection Dialog === New Features diff --git a/doc/reference/variables.adoc b/doc/reference/variables.adoc index e15d175a9a5..d20541f31ed 100644 --- a/doc/reference/variables.adoc +++ b/doc/reference/variables.adoc @@ -145,3 +145,16 @@ Used to compute the nodes which should be considered as target of the edge - `self`: The current element on which the operation is performed - `editingContext`: The editing context is an abstraction used to access all the semantic data - `environment`: The environment may contain some information on the application currently running + +== NodeTool + +=== SelectionDialogDescription + +If a `SelectionDialogDescription` is defined on the `NodeTool`, the following variable becomes available: +- `selectedObject`: own the semantic element selected by the user in the selection dialog. + +=== SelectionDialogDescription#SelectionCandidatesExpression + +Used to compute the list of elements that should be displayed in the selection dialog +- `self`: The current diagram element on which the tool is currently applied. +- `targetElement` The semantic target element of the diagram element in the `self` variable. diff --git a/package-lock.json b/package-lock.json index 86563b2e71c..86cc8b0ae41 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15216,6 +15216,7 @@ "devDependencies": { "@apollo/client": "3.10.4", "@eclipse-sirius/sirius-components-core": "*", + "@eclipse-sirius/sirius-components-diagrams": "*", "@eclipse-sirius/sirius-components-tsconfig": "*", "@material-ui/core": "4.12.4", "@material-ui/icons": "4.11.3", @@ -15233,6 +15234,7 @@ "peerDependencies": { "@apollo/client": "3.10.4", "@eclipse-sirius/sirius-components-core": "*", + "@eclipse-sirius/sirius-components-diagrams": "*", "@material-ui/core": "4.12.4", "@material-ui/icons": "4.11.3", "@xstate/react": "1.6.3", @@ -24909,6 +24911,7 @@ "requires": { "@apollo/client": "3.10.4", "@eclipse-sirius/sirius-components-core": "*", + "@eclipse-sirius/sirius-components-diagrams": "*", "@eclipse-sirius/sirius-components-tsconfig": "*", "@material-ui/core": "4.12.4", "@material-ui/icons": "4.11.3", diff --git a/packages/compatibility/backend/sirius-components-compatibility/src/main/java/org/eclipse/sirius/components/compatibility/services/diagrams/CompatibilityPaletteProvider.java b/packages/compatibility/backend/sirius-components-compatibility/src/main/java/org/eclipse/sirius/components/compatibility/services/diagrams/CompatibilityPaletteProvider.java index 5206e49c133..19fcb5a100f 100644 --- a/packages/compatibility/backend/sirius-components-compatibility/src/main/java/org/eclipse/sirius/components/compatibility/services/diagrams/CompatibilityPaletteProvider.java +++ b/packages/compatibility/backend/sirius-components-compatibility/src/main/java/org/eclipse/sirius/components/compatibility/services/diagrams/CompatibilityPaletteProvider.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2022, 2023 Obeo. + * Copyright (c) 2022, 2024 Obeo. * This program and the accompanying materials * are made available under the terms of the Eclipse Public License v2.0 * which accompanies this distribution, and is available at @@ -133,7 +133,7 @@ private ITool convertTool(org.eclipse.sirius.components.diagrams.tools.ITool too if (tool instanceof org.eclipse.sirius.components.diagrams.tools.SingleClickOnDiagramElementTool singleClickOnDiagramElementTool) { convertedTool = new SingleClickOnDiagramElementTool(singleClickOnDiagramElementTool.getId(), singleClickOnDiagramElementTool.getLabel(), singleClickOnDiagramElementTool.getIconURL(), singleClickOnDiagramElementTool.getTargetDescriptions(), - singleClickOnDiagramElementTool.getSelectionDescriptionId(), singleClickOnDiagramElementTool.isAppliesToDiagramRoot()); + singleClickOnDiagramElementTool.getDialogDescriptionId(), singleClickOnDiagramElementTool.isAppliesToDiagramRoot()); } if (tool instanceof org.eclipse.sirius.components.diagrams.tools.SingleClickOnTwoDiagramElementsTool singleClickOnTwoDiagramElementsTool) { List candidates = new ArrayList<>(); diff --git a/packages/compatibility/backend/sirius-components-compatibility/src/main/java/org/eclipse/sirius/components/compatibility/services/diagrams/ToolProvider.java b/packages/compatibility/backend/sirius-components-compatibility/src/main/java/org/eclipse/sirius/components/compatibility/services/diagrams/ToolProvider.java index 50fe33c0cc5..b6c7a80046b 100644 --- a/packages/compatibility/backend/sirius-components-compatibility/src/main/java/org/eclipse/sirius/components/compatibility/services/diagrams/ToolProvider.java +++ b/packages/compatibility/backend/sirius-components-compatibility/src/main/java/org/eclipse/sirius/components/compatibility/services/diagrams/ToolProvider.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2019, 2023 Obeo. + * Copyright (c) 2019, 2024 Obeo. * This program and the accompanying materials * are made available under the terms of the Eclipse Public License v2.0 * which accompanies this distribution, and is available at @@ -234,9 +234,9 @@ private SingleClickOnDiagramElementTool convertNodeCreationDescription(Map imagePath = this.toolImageProvider.getIcon(nodeCreationTool); List targetDescriptions = this.getParentNodeDescriptions(nodeCreationTool.getNodeMappings(), id2NodeDescriptions); var selectModelElementVariableOpt = new SelectModelElementVariableProvider().getSelectModelElementVariable(nodeCreationTool.getVariable()); - String selectionDescriptionId = null; + String dialogDescriptionId = null; if (selectModelElementVariableOpt.isPresent()) { - selectionDescriptionId = this.identifierProvider.getIdentifier(selectModelElementVariableOpt.get()); + dialogDescriptionId = this.identifierProvider.getIdentifier(selectModelElementVariableOpt.get()); } // @formatter:off return SingleClickOnDiagramElementTool.newSingleClickOnDiagramElementTool(id) @@ -245,7 +245,7 @@ private SingleClickOnDiagramElementTool convertNodeCreationDescription(Map imagePath = this.toolImageProvider.getIcon(containerCreationDescription); List targetDescriptions = this.getParentNodeDescriptions(containerCreationDescription.getContainerMappings(), id2NodeDescriptions); var selectModelElementVariableOpt = new SelectModelElementVariableProvider().getSelectModelElementVariable(containerCreationDescription.getVariable()); - String selectionDescriptionId = null; + String dialogDescriptionId = null; if (selectModelElementVariableOpt.isPresent()) { - selectionDescriptionId = this.identifierProvider.getIdentifier(selectModelElementVariableOpt.get()); + dialogDescriptionId = this.identifierProvider.getIdentifier(selectModelElementVariableOpt.get()); } // @formatter:off return SingleClickOnDiagramElementTool.newSingleClickOnDiagramElementTool(id) @@ -268,7 +268,7 @@ private SingleClickOnDiagramElementTool convertContainerCreationDescription(Map< .handler(this.createContainerCreationHandler(interpreter, containerCreationDescription)) .targetDescriptions(targetDescriptions) .appliesToDiagramRoot(this.atLeastOneRootMapping(containerCreationDescription.getContainerMappings())) - .selectionDescriptionId(selectionDescriptionId) + .dialogDescriptionId(dialogDescriptionId) .build(); // @formatter:on } diff --git a/packages/diagrams/backend/sirius-components-collaborative-diagrams/src/main/java/org/eclipse/sirius/components/collaborative/diagrams/dto/InvokeSingleClickOnDiagramElementToolInput.java b/packages/diagrams/backend/sirius-components-collaborative-diagrams/src/main/java/org/eclipse/sirius/components/collaborative/diagrams/dto/InvokeSingleClickOnDiagramElementToolInput.java index 00118815ab9..eb53994fe3a 100644 --- a/packages/diagrams/backend/sirius-components-collaborative-diagrams/src/main/java/org/eclipse/sirius/components/collaborative/diagrams/dto/InvokeSingleClickOnDiagramElementToolInput.java +++ b/packages/diagrams/backend/sirius-components-collaborative-diagrams/src/main/java/org/eclipse/sirius/components/collaborative/diagrams/dto/InvokeSingleClickOnDiagramElementToolInput.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2019, 2023 Obeo and others. + * Copyright (c) 2019, 2024 Obeo and others. * This program and the accompanying materials * are made available under the terms of the Eclipse Public License v2.0 * which accompanies this distribution, and is available at @@ -12,6 +12,7 @@ *******************************************************************************/ package org.eclipse.sirius.components.collaborative.diagrams.dto; +import java.util.List; import java.util.UUID; import org.eclipse.sirius.components.collaborative.diagrams.api.IDiagramInput; @@ -22,5 +23,5 @@ * @author pcdavid */ public record InvokeSingleClickOnDiagramElementToolInput(UUID id, String editingContextId, String representationId, String diagramElementId, String toolId, double startingPositionX, - double startingPositionY, String selectedObjectId) implements IDiagramInput { + double startingPositionY, List variables) implements IDiagramInput { } diff --git a/packages/diagrams/backend/sirius-components-collaborative-diagrams/src/main/java/org/eclipse/sirius/components/collaborative/diagrams/dto/SingleClickOnDiagramElementTool.java b/packages/diagrams/backend/sirius-components-collaborative-diagrams/src/main/java/org/eclipse/sirius/components/collaborative/diagrams/dto/SingleClickOnDiagramElementTool.java index 8897ec94994..790ebcb032e 100644 --- a/packages/diagrams/backend/sirius-components-collaborative-diagrams/src/main/java/org/eclipse/sirius/components/collaborative/diagrams/dto/SingleClickOnDiagramElementTool.java +++ b/packages/diagrams/backend/sirius-components-collaborative-diagrams/src/main/java/org/eclipse/sirius/components/collaborative/diagrams/dto/SingleClickOnDiagramElementTool.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2023 Obeo. + * Copyright (c) 2023, 2024 Obeo. * This program and the accompanying materials * are made available under the terms of the Eclipse Public License v2.0 * which accompanies this distribution, and is available at @@ -22,7 +22,7 @@ * * @author mcharfadi */ -public record SingleClickOnDiagramElementTool(String id, String label, List iconURL, List targetDescriptions, String selectionDescriptionId, +public record SingleClickOnDiagramElementTool(String id, String label, List iconURL, List targetDescriptions, String dialogDescriptionId, boolean appliesToDiagramRoot) implements ITool { public SingleClickOnDiagramElementTool { @@ -53,7 +53,7 @@ public static final class Builder { private List targetDescriptions; - private String selectionDescriptionId; + private String dialogDescriptionId; private boolean appliesToDiagramRoot; @@ -81,13 +81,13 @@ public Builder appliesToDiagramRoot(boolean appliesToDiagramRoot) { return this; } - public Builder selectionDescriptionId(String selectionDescriptionId) { - this.selectionDescriptionId = selectionDescriptionId; + public Builder dialogDescriptionId(String dialogDescriptionId) { + this.dialogDescriptionId = dialogDescriptionId; return this; } public SingleClickOnDiagramElementTool build() { - return new SingleClickOnDiagramElementTool(this.id, this.label, this.iconURL, this.targetDescriptions, this.selectionDescriptionId, this.appliesToDiagramRoot); + return new SingleClickOnDiagramElementTool(this.id, this.label, this.iconURL, this.targetDescriptions, this.dialogDescriptionId, this.appliesToDiagramRoot); } } diff --git a/packages/diagrams/backend/sirius-components-collaborative-diagrams/src/main/java/org/eclipse/sirius/components/collaborative/diagrams/dto/ToolVariable.java b/packages/diagrams/backend/sirius-components-collaborative-diagrams/src/main/java/org/eclipse/sirius/components/collaborative/diagrams/dto/ToolVariable.java new file mode 100644 index 00000000000..c150712e80c --- /dev/null +++ b/packages/diagrams/backend/sirius-components-collaborative-diagrams/src/main/java/org/eclipse/sirius/components/collaborative/diagrams/dto/ToolVariable.java @@ -0,0 +1,21 @@ +/******************************************************************************* + * Copyright (c) 2024 Obeo. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ +package org.eclipse.sirius.components.collaborative.diagrams.dto; + +/** + * Represents a ToolVariable entry. + * @author fbarbin + */ +public record ToolVariable(String name, String value, ToolVariableType type) { + +} diff --git a/packages/diagrams/backend/sirius-components-collaborative-diagrams/src/main/java/org/eclipse/sirius/components/collaborative/diagrams/dto/ToolVariableType.java b/packages/diagrams/backend/sirius-components-collaborative-diagrams/src/main/java/org/eclipse/sirius/components/collaborative/diagrams/dto/ToolVariableType.java new file mode 100644 index 00000000000..255c3b93f6f --- /dev/null +++ b/packages/diagrams/backend/sirius-components-collaborative-diagrams/src/main/java/org/eclipse/sirius/components/collaborative/diagrams/dto/ToolVariableType.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2024 Obeo. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ +package org.eclipse.sirius.components.collaborative.diagrams.dto; + +/** + * Represent the Type of the Tool Variable. + * + * @author fbarbin + */ +public enum ToolVariableType { + /** + * The Value is a simple string. + */ + STRING, + /** + * The value represents an Object ID. + */ + OBJECT_ID, + /** + * The value represent an Array of Object IDs, separated by a ",". + */ + OBJECT_ID_ARRAY +} diff --git a/packages/diagrams/backend/sirius-components-collaborative-diagrams/src/main/java/org/eclipse/sirius/components/collaborative/diagrams/handlers/InvokeSingleClickOnDiagramElementToolEventHandler.java b/packages/diagrams/backend/sirius-components-collaborative-diagrams/src/main/java/org/eclipse/sirius/components/collaborative/diagrams/handlers/InvokeSingleClickOnDiagramElementToolEventHandler.java index cff192b79b1..15c951b5c25 100644 --- a/packages/diagrams/backend/sirius-components-collaborative-diagrams/src/main/java/org/eclipse/sirius/components/collaborative/diagrams/handlers/InvokeSingleClickOnDiagramElementToolEventHandler.java +++ b/packages/diagrams/backend/sirius-components-collaborative-diagrams/src/main/java/org/eclipse/sirius/components/collaborative/diagrams/handlers/InvokeSingleClickOnDiagramElementToolEventHandler.java @@ -12,6 +12,7 @@ *******************************************************************************/ package org.eclipse.sirius.components.collaborative.diagrams.handlers; +import java.util.List; import java.util.Objects; import java.util.Optional; @@ -27,6 +28,7 @@ import org.eclipse.sirius.components.collaborative.diagrams.api.IToolService; import org.eclipse.sirius.components.collaborative.diagrams.dto.InvokeSingleClickOnDiagramElementToolInput; import org.eclipse.sirius.components.collaborative.diagrams.dto.InvokeSingleClickOnDiagramElementToolSuccessPayload; +import org.eclipse.sirius.components.collaborative.diagrams.dto.ToolVariable; import org.eclipse.sirius.components.collaborative.diagrams.messages.ICollaborativeDiagramMessageService; import org.eclipse.sirius.components.core.api.Environment; import org.eclipse.sirius.components.core.api.ErrorPayload; @@ -62,6 +64,8 @@ @Service public class InvokeSingleClickOnDiagramElementToolEventHandler implements IDiagramEventHandler { + private static final String OBJECT_ID_ARRAY_SEPARATOR = ","; + private final Logger logger = LoggerFactory.getLogger(InvokeSingleClickOnDiagramElementToolEventHandler.class); private final IObjectService objectService; @@ -76,6 +80,7 @@ public class InvokeSingleClickOnDiagramElementToolEventHandler implements IDiagr private final IRepresentationDescriptionSearchService representationDescriptionSearchService; + public InvokeSingleClickOnDiagramElementToolEventHandler(IObjectService objectService, IDiagramQueryService diagramQueryService, IToolService toolService, ICollaborativeDiagramMessageService messageService, MeterRegistry meterRegistry, IRepresentationDescriptionSearchService representationDescriptionSearchService) { this.objectService = Objects.requireNonNull(objectService); @@ -114,7 +119,7 @@ public void handle(One payloadSink, Many changeDesc // @formatter:on if (optionalTool.isPresent()) { IStatus status = this.executeTool(editingContext, diagramContext, input.diagramElementId(), optionalTool.get(), input.startingPositionX(), input.startingPositionY(), - input.selectedObjectId()); + input.variables()); if (status instanceof Success success) { WorkbenchSelection newSelection = null; Object newSelectionParameter = success.getParameters().get(Success.NEW_SELECTION); @@ -134,7 +139,7 @@ public void handle(One payloadSink, Many changeDesc } private IStatus executeTool(IEditingContext editingContext, IDiagramContext diagramContext, String diagramElementId, SingleClickOnDiagramElementTool tool, double startingPositionX, - double startingPositionY, String selectedObjectId) { + double startingPositionY, List variables) { IStatus result = new Failure(""); Diagram diagram = diagramContext.getDiagram(); Optional node = this.diagramQueryService.findNodeById(diagram, diagramElementId); @@ -149,24 +154,47 @@ private IStatus executeTool(IEditingContext editingContext, IDiagramContext diag if (self.isPresent()) { VariableManager variableManager = this.populateVariableManager(editingContext, diagramContext, node, edge, self); - String selectionDescriptionId = tool.getSelectionDescriptionId(); - if (selectionDescriptionId != null && selectedObjectId != null) { - var selectionDescriptionOpt = this.representationDescriptionSearchService.findById(editingContext, selectionDescriptionId); - var selectedObjectOpt = this.objectService.getObject(editingContext, selectedObjectId); - if (selectionDescriptionOpt.isPresent() && selectedObjectOpt.isPresent()) { - variableManager.put(SingleClickOnDiagramElementTool.SELECTED_OBJECT, selectedObjectOpt.get()); - } + String dialogDescriptionId = tool.getDialogDescriptionId(); + if (dialogDescriptionId != null && !variables.isEmpty()) { + this.handleDialogVariables(editingContext, variableManager, variables); } - if (selectionDescriptionId == null || selectedObjectId != null) { + + //We do not apply the tool if a dialog is defined but no variables have been provided + if (dialogDescriptionId == null || !variables.isEmpty()) { result = tool.getHandler().apply(variableManager); Position newPosition = Position.at(startingPositionX, startingPositionY); - diagramContext.getDiagramEvents().add(new SinglePositionEvent(diagramElementId, newPosition)); } } return result; } + private void handleDialogVariables(IEditingContext editingContext, VariableManager variableManager, List variables) { + variables.forEach(toolVariable -> { + this.handleToolVariable(toolVariable, editingContext, variableManager); + }); + } + + private void handleToolVariable(ToolVariable toolvariable, IEditingContext editingContext, VariableManager variableManager) { + switch (toolvariable.type()) { + case STRING -> variableManager.put(toolvariable.name(), toolvariable.value()); + case OBJECT_ID -> { + var optionalObject = this.objectService.getObject(editingContext, toolvariable.value()); + variableManager.put(toolvariable.name(), optionalObject.orElse(null)); + } + case OBJECT_ID_ARRAY -> { + String value = toolvariable.value(); + List objectsIds = List.of(value.split(OBJECT_ID_ARRAY_SEPARATOR)); + List objects = objectsIds.stream() + .map(objectId -> this.objectService.getObject(editingContext, objectId)) + .map(optionalObject -> optionalObject.orElse(null)) + .toList(); + variableManager.put(toolvariable.name(), objects); + } + default -> this.logger.warn("Unexpected value: " + toolvariable.type()); + } + } + private Optional getCurrentContext(IEditingContext editingContext, String diagramElementId, SingleClickOnDiagramElementTool tool, Diagram diagram, Optional node, Optional edge) { Optional self = Optional.empty(); diff --git a/packages/diagrams/backend/sirius-components-collaborative-diagrams/src/main/resources/schema/diagram.graphqls b/packages/diagrams/backend/sirius-components-collaborative-diagrams/src/main/resources/schema/diagram.graphqls index aec8a8da320..9a33c3817f5 100644 --- a/packages/diagrams/backend/sirius-components-collaborative-diagrams/src/main/resources/schema/diagram.graphqls +++ b/packages/diagrams/backend/sirius-components-collaborative-diagrams/src/main/resources/schema/diagram.graphqls @@ -8,9 +8,7 @@ input DiagramEventInput { diagramId: ID! } -union DiagramEventPayload = - ErrorPayload - | DiagramRefreshedEventPayload +union DiagramEventPayload = ErrorPayload | DiagramRefreshedEventPayload type DiagramRefreshedEventPayload { id: ID! @@ -224,7 +222,7 @@ type Edge { routingPoints: [Position]! sourceAnchorRelativePosition: Ratio! targetAnchorRelativePosition: Ratio! - centerLabelEditable : Boolean! + centerLabelEditable: Boolean! } type EdgeStyle { @@ -293,7 +291,7 @@ type SingleClickOnDiagramElementTool implements Tool { label: String! iconURL: [String!]! appliesToDiagramRoot: Boolean! - selectionDescriptionId: String + dialogDescriptionId: String targetDescriptions: [DiagramElementDescription!]! } @@ -368,8 +366,12 @@ extend type Mutation { arrangeAll(input: ArrangeAllInput!): ArrangeAllPayload! deleteFromDiagram(input: DeleteFromDiagramInput!): DeleteFromDiagramPayload! editLabel(input: EditLabelInput!): EditLabelPayload! - invokeSingleClickOnDiagramElementTool(input: InvokeSingleClickOnDiagramElementToolInput!): InvokeSingleClickOnDiagramElementToolPayload! - invokeSingleClickOnTwoDiagramElementsTool(input: InvokeSingleClickOnTwoDiagramElementsToolInput!): InvokeSingleClickOnTwoDiagramElementsToolPayload! + invokeSingleClickOnDiagramElementTool( + input: InvokeSingleClickOnDiagramElementToolInput! + ): InvokeSingleClickOnDiagramElementToolPayload! + invokeSingleClickOnTwoDiagramElementsTool( + input: InvokeSingleClickOnTwoDiagramElementsToolInput! + ): InvokeSingleClickOnTwoDiagramElementsToolPayload! updateNodeBounds(input: UpdateNodeBoundsInput!): UpdateNodeBoundsPayload! updateNodePosition(input: UpdateNodePositionInput!): UpdateNodePositionPayload! dropOnDiagram(input: DropOnDiagramInput!): DropOnDiagramPayload! @@ -453,7 +455,7 @@ input InvokeSingleClickOnTwoDiagramElementsToolInput { } union InvokeSingleClickOnTwoDiagramElementsToolPayload = - ErrorPayload + ErrorPayload | InvokeSingleClickOnTwoDiagramElementsToolSuccessPayload type InvokeSingleClickOnTwoDiagramElementsToolSuccessPayload { @@ -466,16 +468,26 @@ input InvokeSingleClickOnDiagramElementToolInput { id: ID! editingContextId: ID! representationId: ID! - selectedObjectId: String + variables: [ToolVariable!]! diagramElementId: ID! startingPositionX: Float! startingPositionY: Float! toolId: ID! } -union InvokeSingleClickOnDiagramElementToolPayload = - ErrorPayload - | InvokeSingleClickOnDiagramElementToolSuccessPayload +input ToolVariable { + name: String! + value: String! + type: ToolVariableType! +} + +enum ToolVariableType { + STRING + OBJECT_ID + OBJECT_ID_ARRAY +} + +union InvokeSingleClickOnDiagramElementToolPayload = ErrorPayload | InvokeSingleClickOnDiagramElementToolSuccessPayload type InvokeSingleClickOnDiagramElementToolSuccessPayload { id: ID! @@ -510,9 +522,7 @@ input UpdateNodePositionInput { newPositionY: Float! } -union UpdateNodePositionPayload = - ErrorPayload - | UpdateNodePositionSuccessPayload +union UpdateNodePositionPayload = ErrorPayload | UpdateNodePositionSuccessPayload type UpdateNodePositionSuccessPayload { id: ID! @@ -599,7 +609,6 @@ input PinDiagramElementInput { pinned: Boolean! } - union PinDiagramElementPayload = ErrorPayload | SuccessPayload input UpdateCollapsingStateInput { diff --git a/packages/diagrams/backend/sirius-components-collaborative-diagrams/src/test/java/org/eclipse/sirius/components/collaborative/diagrams/handlers/InvokeSingleClickOnDiagramElementToolEventHandlerTests.java b/packages/diagrams/backend/sirius-components-collaborative-diagrams/src/test/java/org/eclipse/sirius/components/collaborative/diagrams/handlers/InvokeSingleClickOnDiagramElementToolEventHandlerTests.java index 24e2ab4c346..0cb22b9f016 100644 --- a/packages/diagrams/backend/sirius-components-collaborative-diagrams/src/test/java/org/eclipse/sirius/components/collaborative/diagrams/handlers/InvokeSingleClickOnDiagramElementToolEventHandlerTests.java +++ b/packages/diagrams/backend/sirius-components-collaborative-diagrams/src/test/java/org/eclipse/sirius/components/collaborative/diagrams/handlers/InvokeSingleClickOnDiagramElementToolEventHandlerTests.java @@ -14,11 +14,13 @@ import static org.assertj.core.api.Assertions.assertThat; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.UUID; +import java.util.function.Function; import org.eclipse.sirius.components.collaborative.api.ChangeDescription; import org.eclipse.sirius.components.collaborative.api.ChangeKind; @@ -28,6 +30,8 @@ import org.eclipse.sirius.components.collaborative.diagrams.api.IToolService; import org.eclipse.sirius.components.collaborative.diagrams.dto.InvokeSingleClickOnDiagramElementToolInput; import org.eclipse.sirius.components.collaborative.diagrams.dto.InvokeSingleClickOnDiagramElementToolSuccessPayload; +import org.eclipse.sirius.components.collaborative.diagrams.dto.ToolVariable; +import org.eclipse.sirius.components.collaborative.diagrams.dto.ToolVariableType; import org.eclipse.sirius.components.collaborative.diagrams.messages.ICollaborativeDiagramMessageService; import org.eclipse.sirius.components.core.api.ErrorPayload; import org.eclipse.sirius.components.core.api.IEditingContext; @@ -60,7 +64,9 @@ import org.eclipse.sirius.components.diagrams.description.NodeDescription; import org.eclipse.sirius.components.diagrams.tools.ITool; import org.eclipse.sirius.components.diagrams.tools.SingleClickOnDiagramElementTool; +import org.eclipse.sirius.components.representations.IStatus; import org.eclipse.sirius.components.representations.Success; +import org.eclipse.sirius.components.representations.VariableManager; import org.junit.jupiter.api.Test; import io.micrometer.core.instrument.simple.SimpleMeterRegistry; @@ -75,6 +81,16 @@ */ public class InvokeSingleClickOnDiagramElementToolEventHandlerTests { + private static final String NAME_VARIABLE_VALUE = "nameVariableValue"; + + private static final String NAME_VARIABLE = "name"; + + private static final String SELECTED_OBJECTS = "selectedObjects"; + + private static final String SELECTED_OBJECT = "selectedObject"; + + private static final String DIALOG_DESCRIPTION_ID = "dialogDescriptionId"; + private static final String DIAGRAM_ID = "diagramId"; private static final String EDGE_1_ID = "edge1"; private static final String EDGE_DESCRIPTION_ID = "edgeDescriptionId"; @@ -82,9 +98,16 @@ public class InvokeSingleClickOnDiagramElementToolEventHandlerTests { private static final String NODE_DESCRIPTION_ID = "nodeDescriptionId"; private static final String NODE_1_ID = "node1"; private static final String OBJECT_1_ID = "object1"; + + private static final String OBJECT_2_ID = "object2"; + + private static final String OBJECT_3_ID = "object3"; + private static final String LINK_1_ID = "link1"; private static final String REPRESENTATION_ID = "representationId"; - private static final String SELECTED_OBJECT_ID = "selectedObjectId"; + + private static final List VARIABLES = List.of(); + private static final String TOOL_ID = "toolId"; private static final String TOOL_IMAGE_URL = "imageURL"; private static final String TOOL_LABEL = "label"; @@ -115,7 +138,7 @@ public Optional findToolById(IEditingContext editingContext, Diagram diag var handler = new InvokeSingleClickOnDiagramElementToolEventHandler(objectService, diagramQueryService, toolService, new ICollaborativeDiagramMessageService.NoOp(), new SimpleMeterRegistry(), representationDescriptionSearchService); - var input = new InvokeSingleClickOnDiagramElementToolInput(UUID.randomUUID(), EDITING_CONTEXT_ID, REPRESENTATION_ID, DIAGRAM_ID, TOOL_ID, 5.0, 8.0, SELECTED_OBJECT_ID); + var input = new InvokeSingleClickOnDiagramElementToolInput(UUID.randomUUID(), EDITING_CONTEXT_ID, REPRESENTATION_ID, DIAGRAM_ID, TOOL_ID, 5.0, 8.0, VARIABLES); IEditingContext editingContext = () -> EDITING_CONTEXT_ID; @@ -168,7 +191,7 @@ public Optional findToolById(IEditingContext editingContext, Diagram diag var handler = new InvokeSingleClickOnDiagramElementToolEventHandler(objectService, diagramQueryService, toolService, new ICollaborativeDiagramMessageService.NoOp(), new SimpleMeterRegistry(), representationDescriptionSearchService); - var input = new InvokeSingleClickOnDiagramElementToolInput(UUID.randomUUID(), EDITING_CONTEXT_ID, REPRESENTATION_ID, NODE_1_ID, TOOL_ID, 5.0, 8.0, SELECTED_OBJECT_ID); + var input = new InvokeSingleClickOnDiagramElementToolInput(UUID.randomUUID(), EDITING_CONTEXT_ID, REPRESENTATION_ID, NODE_1_ID, TOOL_ID, 5.0, 8.0, VARIABLES); IEditingContext editingContext = () -> EDITING_CONTEXT_ID; @@ -187,6 +210,78 @@ public Optional findToolById(IEditingContext editingContext, Diagram diag assertThat(payload).isInstanceOf(InvokeSingleClickOnDiagramElementToolSuccessPayload.class); } + @Test + public void testInvokeToolOnNodeWithDialogDescription() { + var object1 = new Object(); + var object2 = new Object(); + var object3 = new Object(); + + var objectService = new IObjectService.NoOp() { + @Override + public Optional getObject(IEditingContext editingContext, String objectId) { + Object object = switch (objectId) { + case OBJECT_1_ID -> object1; + case OBJECT_2_ID -> object2; + case OBJECT_3_ID -> object3; + default -> null; + }; + return Optional.of(object); + } + }; + + var nodeDescription = this.createNodeDescription(NODE_DESCRIPTION_ID); + var node1 = this.createNode(NODE_1_ID, NODE_DESCRIPTION_ID, OBJECT_1_ID); + + var diagramQueryService = new IDiagramQueryService.NoOp() { + @Override + public Optional findNodeById(Diagram diagram, String nodeId) { + return Optional.of(node1); + } + }; + + final Map computedVariables = new HashMap<>(); + + Function toolHandler = variableManager -> { + computedVariables.putAll(variableManager.getVariables()); + return new Success(ChangeKind.SEMANTIC_CHANGE, Map.of()); + }; + + var tool = this.createTool(TOOL_ID, false, List.of(nodeDescription), DIALOG_DESCRIPTION_ID, toolHandler); + + var toolService = new IToolService.NoOp() { + @Override + public Optional findToolById(IEditingContext editingContext, Diagram diagram, String toolId) { + return Optional.of(tool); + } + }; + var representationDescriptionSearchService = new IRepresentationDescriptionSearchService.NoOp(); + + var handler = new InvokeSingleClickOnDiagramElementToolEventHandler(objectService, diagramQueryService, toolService, new ICollaborativeDiagramMessageService.NoOp(), new SimpleMeterRegistry(), + representationDescriptionSearchService); + + var variables = List.of(new ToolVariable(SELECTED_OBJECT, OBJECT_2_ID, ToolVariableType.OBJECT_ID), new ToolVariable(NAME_VARIABLE, NAME_VARIABLE_VALUE, ToolVariableType.STRING), + new ToolVariable(SELECTED_OBJECTS, OBJECT_1_ID + "," + OBJECT_2_ID + "," + OBJECT_3_ID, ToolVariableType.OBJECT_ID_ARRAY)); + + var input = new InvokeSingleClickOnDiagramElementToolInput(UUID.randomUUID(), EDITING_CONTEXT_ID, REPRESENTATION_ID, NODE_1_ID, TOOL_ID, 5.0, 8.0, variables); + + IEditingContext editingContext = () -> EDITING_CONTEXT_ID; + + assertThat(handler.canHandle(input)).isTrue(); + + Many changeDescriptionSink = Sinks.many().unicast().onBackpressureBuffer(); + One payloadSink = Sinks.one(); + + IDiagramContext diagramContext = new DiagramContext(new TestDiagramBuilder().getDiagram(DIAGRAM_ID)); + handler.handle(payloadSink, changeDescriptionSink, editingContext, diagramContext, input); + + ChangeDescription changeDescription = changeDescriptionSink.asFlux().blockFirst(); + assertThat(changeDescription.getKind()).isEqualTo(ChangeKind.SEMANTIC_CHANGE); + + IPayload payload = payloadSink.asMono().block(); + assertThat(payload).isInstanceOf(InvokeSingleClickOnDiagramElementToolSuccessPayload.class); + assertThat(computedVariables).containsEntry(SELECTED_OBJECT, object2).containsEntry(NAME_VARIABLE, NAME_VARIABLE_VALUE).containsEntry(SELECTED_OBJECTS, List.of(object1, object2, object3)); + } + @Test public void testInvokeToolOnWrongNode() { var object1 = new Object(); @@ -224,7 +319,7 @@ public Optional findToolById(IEditingContext editingContext, Diagram diag var handler = new InvokeSingleClickOnDiagramElementToolEventHandler(objectService, diagramQueryService, toolService, new ICollaborativeDiagramMessageService.NoOp(), new SimpleMeterRegistry(), representationDescriptionSearchService); - var input = new InvokeSingleClickOnDiagramElementToolInput(UUID.randomUUID(), EDITING_CONTEXT_ID, REPRESENTATION_ID, "anotherNodeId", TOOL_ID, 5.0, 8.0, SELECTED_OBJECT_ID); + var input = new InvokeSingleClickOnDiagramElementToolInput(UUID.randomUUID(), EDITING_CONTEXT_ID, REPRESENTATION_ID, "anotherNodeId", TOOL_ID, 5.0, 8.0, VARIABLES); IEditingContext editingContext = () -> EDITING_CONTEXT_ID; @@ -280,7 +375,7 @@ public Optional findToolById(IEditingContext editingContext, Diagram diag var handler = new InvokeSingleClickOnDiagramElementToolEventHandler(objectService, diagramQueryService, toolService, new ICollaborativeDiagramMessageService.NoOp(), new SimpleMeterRegistry(), representationDescriptionSearchService); - var input = new InvokeSingleClickOnDiagramElementToolInput(UUID.randomUUID(), EDITING_CONTEXT_ID, REPRESENTATION_ID, EDGE_1_ID, TOOL_ID, 5.0, 8.0, SELECTED_OBJECT_ID); + var input = new InvokeSingleClickOnDiagramElementToolInput(UUID.randomUUID(), EDITING_CONTEXT_ID, REPRESENTATION_ID, EDGE_1_ID, TOOL_ID, 5.0, 8.0, VARIABLES); IEditingContext editingContext = () -> EDITING_CONTEXT_ID; @@ -336,7 +431,7 @@ public Optional findToolById(IEditingContext editingContext, Diagram diag var handler = new InvokeSingleClickOnDiagramElementToolEventHandler(objectService, diagramQueryService, toolService, new ICollaborativeDiagramMessageService.NoOp(), new SimpleMeterRegistry(), representationDescriptionSearchService); - var input = new InvokeSingleClickOnDiagramElementToolInput(UUID.randomUUID(), EDITING_CONTEXT_ID, REPRESENTATION_ID, "anotherEdgeId", TOOL_ID, 5.0, 8.0, SELECTED_OBJECT_ID); + var input = new InvokeSingleClickOnDiagramElementToolInput(UUID.randomUUID(), EDITING_CONTEXT_ID, REPRESENTATION_ID, "anotherEdgeId", TOOL_ID, 5.0, 8.0, VARIABLES); IEditingContext editingContext = () -> EDITING_CONTEXT_ID; @@ -356,12 +451,16 @@ public Optional findToolById(IEditingContext editingContext, Diagram diag } private SingleClickOnDiagramElementTool createTool(String toolId, boolean appliesToDiagramRoot, List diagramElementsDescriptions) { + return this.createTool(toolId, appliesToDiagramRoot, diagramElementsDescriptions, null, variableManager -> new Success(ChangeKind.SEMANTIC_CHANGE, Map.of())); + } + + private SingleClickOnDiagramElementTool createTool(String toolId, boolean appliesToDiagramRoot, List diagramElementsDescriptions, String dialogDescriptionId, Function handler) { return SingleClickOnDiagramElementTool.newSingleClickOnDiagramElementTool(toolId) .label(TOOL_LABEL) .iconURL(List.of(TOOL_IMAGE_URL)) .targetDescriptions(diagramElementsDescriptions) - .selectionDescriptionId(null) - .handler(variableManager -> new Success(ChangeKind.SEMANTIC_CHANGE, Map.of())) + .dialogDescriptionId(dialogDescriptionId) + .handler(handler) .appliesToDiagramRoot(appliesToDiagramRoot) .build(); } diff --git a/packages/diagrams/backend/sirius-components-collaborative-diagrams/src/test/java/org/eclipse/sirius/components/collaborative/diagrams/providers/GenericDiagramToolReferencePositionProviderTests.java b/packages/diagrams/backend/sirius-components-collaborative-diagrams/src/test/java/org/eclipse/sirius/components/collaborative/diagrams/providers/GenericDiagramToolReferencePositionProviderTests.java index b990fbe31bb..664de00e5c0 100644 --- a/packages/diagrams/backend/sirius-components-collaborative-diagrams/src/test/java/org/eclipse/sirius/components/collaborative/diagrams/providers/GenericDiagramToolReferencePositionProviderTests.java +++ b/packages/diagrams/backend/sirius-components-collaborative-diagrams/src/test/java/org/eclipse/sirius/components/collaborative/diagrams/providers/GenericDiagramToolReferencePositionProviderTests.java @@ -42,7 +42,7 @@ public void canHandle() { var diagramToolReferencePositionProvider = new GenericDiagramToolReferencePositionProvider(); InvokeSingleClickOnDiagramElementToolInput inputInvokeSingleClick = new InvokeSingleClickOnDiagramElementToolInput(UUID.randomUUID(), "", "", - "", "", 0, 0, ""); + "", "", 0, 0, List.of()); assertThat(diagramToolReferencePositionProvider.canHandle(inputInvokeSingleClick)).isTrue(); DropNodeInput inputDropNode = new DropNodeInput(UUID.randomUUID(), "", "", "", "", 0, 0); assertThat(diagramToolReferencePositionProvider.canHandle(inputDropNode)).isTrue(); @@ -60,12 +60,12 @@ public void getReferencePositionInvokeSingleClickOnDiagramElementTool() { IDiagramContext diagramContext = new DiagramContext(new TestDiagramBuilder().getDiagram(diagramId)); // Test click on diagram InvokeSingleClickOnDiagramElementToolInput inputInvokeSingleClickOnDiagram = new InvokeSingleClickOnDiagramElementToolInput(UUID.randomUUID(), "", "", - diagramId, "", 3, 2, ""); + diagramId, "", 3, 2, List.of()); var result = diagramToolReferencePositionProvider.getReferencePosition(inputInvokeSingleClickOnDiagram, diagramContext); this.assertResult(result, null, new Position(3, 2)); // Test click on container InvokeSingleClickOnDiagramElementToolInput inputInvokeSingleClickOnContainer = new InvokeSingleClickOnDiagramElementToolInput(UUID.randomUUID(), "", "", - CONTAINER_ID, "", 3, 2, ""); + CONTAINER_ID, "", 3, 2, List.of()); result = diagramToolReferencePositionProvider.getReferencePosition(inputInvokeSingleClickOnContainer, diagramContext); this.assertResult(result, CONTAINER_ID, new Position(3, 2)); } diff --git a/packages/diagrams/backend/sirius-components-diagrams-tests/src/main/java/org/eclipse/sirius/components/diagrams/tests/graphql/PaletteQueryRunner.java b/packages/diagrams/backend/sirius-components-diagrams-tests/src/main/java/org/eclipse/sirius/components/diagrams/tests/graphql/PaletteQueryRunner.java index 4e40b973527..798a8b58693 100644 --- a/packages/diagrams/backend/sirius-components-diagrams-tests/src/main/java/org/eclipse/sirius/components/diagrams/tests/graphql/PaletteQueryRunner.java +++ b/packages/diagrams/backend/sirius-components-diagrams-tests/src/main/java/org/eclipse/sirius/components/diagrams/tests/graphql/PaletteQueryRunner.java @@ -54,7 +54,7 @@ query getPalette($editingContextId: ID!, $representationId: ID!, $diagramElement } } } - + fragment ToolFields on Tool { __typename id @@ -65,7 +65,7 @@ query getPalette($editingContextId: ID!, $representationId: ID!, $diagramElement id } appliesToDiagramRoot - selectionDescriptionId + dialogDescriptionId } } """; diff --git a/packages/diagrams/backend/sirius-components-diagrams/src/main/java/org/eclipse/sirius/components/diagrams/tools/SingleClickOnDiagramElementTool.java b/packages/diagrams/backend/sirius-components-diagrams/src/main/java/org/eclipse/sirius/components/diagrams/tools/SingleClickOnDiagramElementTool.java index f51e7cc5ab2..570b757d87d 100644 --- a/packages/diagrams/backend/sirius-components-diagrams/src/main/java/org/eclipse/sirius/components/diagrams/tools/SingleClickOnDiagramElementTool.java +++ b/packages/diagrams/backend/sirius-components-diagrams/src/main/java/org/eclipse/sirius/components/diagrams/tools/SingleClickOnDiagramElementTool.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2019, 2023 Obeo. + * Copyright (c) 2019, 2024 Obeo. * This program and the accompanying materials * are made available under the terms of the Eclipse Public License v2.0 * which accompanies this distribution, and is available at @@ -45,7 +45,7 @@ public final class SingleClickOnDiagramElementTool implements ITool { private boolean appliesToDiagramRoot; - private String selectionDescriptionId; + private String dialogDescriptionId; private SingleClickOnDiagramElementTool() { // Prevent instantiation @@ -78,8 +78,8 @@ public String getLabel() { return this.label; } - public String getSelectionDescriptionId() { - return this.selectionDescriptionId; + public String getDialogDescriptionId() { + return this.dialogDescriptionId; } @Override @@ -113,7 +113,7 @@ public static final class Builder { private boolean appliesToDiagramRoot; - private String selectionDescriptionId; + private String dialogDescriptionId; private Builder(String id) { this.id = Objects.requireNonNull(id); @@ -144,8 +144,8 @@ public Builder handler(Function handler) { return this; } - public Builder selectionDescriptionId(String selectionDescriptionId) { - this.selectionDescriptionId = selectionDescriptionId; + public Builder dialogDescriptionId(String dialogDescriptionId) { + this.dialogDescriptionId = dialogDescriptionId; return this; } @@ -157,7 +157,7 @@ public SingleClickOnDiagramElementTool build() { tool.handler = Objects.requireNonNull(this.handler); tool.targetDescriptions = Objects.requireNonNull(this.targetDescriptions); tool.appliesToDiagramRoot = this.appliesToDiagramRoot; - tool.selectionDescriptionId = this.selectionDescriptionId; + tool.dialogDescriptionId = this.dialogDescriptionId; return tool; } } diff --git a/packages/diagrams/frontend/sirius-components-diagrams/src/dialog/DialogContext.tsx b/packages/diagrams/frontend/sirius-components-diagrams/src/dialog/DialogContext.tsx new file mode 100644 index 00000000000..99f321335d5 --- /dev/null +++ b/packages/diagrams/frontend/sirius-components-diagrams/src/dialog/DialogContext.tsx @@ -0,0 +1,79 @@ +/******************************************************************************* + * Copyright (c) 2024 Obeo and others. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ + +import { useData } from '@eclipse-sirius/sirius-components-core'; +import React, { useState } from 'react'; +import { GQLToolVariable } from '../renderer/palette/Palette.types'; +import { DialogContextProviderState, DialogContextValue } from './DialogContext.types'; +import { diagramDialogContributionExtensionPoint } from './diagramDialogExtensionPoint'; +import { DiagramDialogContribution, DialogComponentProps } from './diagramDialogExtensionPoint.types'; + +const defaultValue: DialogContextValue = { + showDialog: () => {}, +}; + +export const DialogContext = React.createContext(defaultValue); + +export const DialogContextProvider = ({ children }) => { + const [state, setState] = useState({ + dialogDescriptionId: undefined, + dialogKindId: undefined, + editingContextId: undefined, + targetObjectId: undefined, + onConfirm: () => {}, + open: false, + }); + + const { data: dialogContributions } = useData(diagramDialogContributionExtensionPoint); + const showDialog = ( + dialogKindId: string, + editingContextId: string, + dialogDescriptionId, + targetObjectId, + onConfirm: (variables: GQLToolVariable[]) => void + ) => { + setState({ open: true, dialogKindId, editingContextId, dialogDescriptionId, targetObjectId, onConfirm }); + }; + + const onFinish = (toolVariables: GQLToolVariable[]) => { + state.onConfirm(toolVariables); + setState((prevState) => ({ ...prevState, open: false, dialogKindId: undefined })); + }; + + const onClose = () => { + setState((prevState) => ({ ...prevState, open: false, dialogKindId: undefined })); + }; + + let DialogComponent: React.ComponentType | undefined; + const dialogComponentProps: DialogComponentProps = { + dialogDescriptionId: state.dialogDescriptionId ?? '', + editingContextId: state.editingContextId ?? '', + targetObjectId: state.targetObjectId ?? '', + onFinish, + onClose, + }; + if (state.open && state.dialogKindId) { + const dialogContribution: DiagramDialogContribution | undefined = dialogContributions.find((dialogContribution) => + dialogContribution.canHandle(state.dialogKindId as string) + ); + if (dialogContribution) { + DialogComponent = dialogContribution.component; + } + } + return ( + + {children} + {state.open && DialogComponent && } + + ); +}; diff --git a/packages/diagrams/frontend/sirius-components-diagrams/src/dialog/DialogContext.types.ts b/packages/diagrams/frontend/sirius-components-diagrams/src/dialog/DialogContext.types.ts new file mode 100644 index 00000000000..39dd0130f5b --- /dev/null +++ b/packages/diagrams/frontend/sirius-components-diagrams/src/dialog/DialogContext.types.ts @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2024 Obeo and others. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ + +import { GQLToolVariable } from '../renderer/palette/Palette.types'; + +export interface DialogContextValue { + showDialog: ( + dialogKindId: string, + editingContextId: string, + dialogDescriptionId: string, + targetObjectId: string, + onConfirm: (variables: GQLToolVariable[]) => void + ) => void; +} + +export interface DialogContextProviderState { + open: boolean; + dialogKindId: string | undefined; + editingContextId: string | undefined; + dialogDescriptionId: string | undefined; + targetObjectId: string | undefined; + onConfirm: (variables: GQLToolVariable[]) => void; +} diff --git a/packages/diagrams/frontend/sirius-components-diagrams/src/dialog/diagramDialogExtensionPoint.ts b/packages/diagrams/frontend/sirius-components-diagrams/src/dialog/diagramDialogExtensionPoint.ts new file mode 100644 index 00000000000..39845b80d80 --- /dev/null +++ b/packages/diagrams/frontend/sirius-components-diagrams/src/dialog/diagramDialogExtensionPoint.ts @@ -0,0 +1,19 @@ +/******************************************************************************* + * Copyright (c) 2024 Obeo. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ +import { DataExtensionPoint } from '@eclipse-sirius/sirius-components-core'; +import { DiagramDialogContribution } from './diagramDialogExtensionPoint.types'; + +export const diagramDialogContributionExtensionPoint: DataExtensionPoint> = { + identifier: 'diagram#diagramDialogContribution', + fallback: [], +}; diff --git a/packages/diagrams/frontend/sirius-components-diagrams/src/dialog/diagramDialogExtensionPoint.types.ts b/packages/diagrams/frontend/sirius-components-diagrams/src/dialog/diagramDialogExtensionPoint.types.ts new file mode 100644 index 00000000000..64083f7f1e1 --- /dev/null +++ b/packages/diagrams/frontend/sirius-components-diagrams/src/dialog/diagramDialogExtensionPoint.types.ts @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2024 Obeo. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ + +import { GQLToolVariable } from '../renderer/palette/Palette.types'; +export interface DiagramDialogContribution { + canHandle: (dialogKindId: string) => boolean; + component: React.ComponentType; +} + +export interface DialogComponentProps { + editingContextId: string; + dialogDescriptionId: string; + targetObjectId: string; + onClose: () => void; + onFinish: (variables: GQLToolVariable[]) => void; +} diff --git a/packages/diagrams/frontend/sirius-components-diagrams/src/dialog/useDialog.tsx b/packages/diagrams/frontend/sirius-components-diagrams/src/dialog/useDialog.tsx new file mode 100644 index 00000000000..1d422c4bd6b --- /dev/null +++ b/packages/diagrams/frontend/sirius-components-diagrams/src/dialog/useDialog.tsx @@ -0,0 +1,22 @@ +/******************************************************************************* + * Copyright (c) 2024 Obeo and others. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ + +import { useContext } from 'react'; +import { DialogContext } from './DialogContext'; +import { UseDialogValue } from './useDialog.types'; + +export const useDialog = (): UseDialogValue => { + const { showDialog } = useContext(DialogContext); + + return { showDialog }; +}; diff --git a/packages/diagrams/frontend/sirius-components-diagrams/src/dialog/useDialog.types.ts b/packages/diagrams/frontend/sirius-components-diagrams/src/dialog/useDialog.types.ts new file mode 100644 index 00000000000..789f91a1539 --- /dev/null +++ b/packages/diagrams/frontend/sirius-components-diagrams/src/dialog/useDialog.types.ts @@ -0,0 +1,22 @@ +/******************************************************************************* + * Copyright (c) 2024 Obeo and others. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ +import { GQLToolVariable } from '../renderer/palette/Palette.types'; +export interface UseDialogValue { + showDialog: ( + dialogKindId: string, + editingContextID: string, + dialogDescriptionId: string, + targetObjectId: string, + onConfirm: (variables: GQLToolVariable[]) => void + ) => void; +} diff --git a/packages/diagrams/frontend/sirius-components-diagrams/src/index.ts b/packages/diagrams/frontend/sirius-components-diagrams/src/index.ts index 599fa9d20e6..592c62a9031 100644 --- a/packages/diagrams/frontend/sirius-components-diagrams/src/index.ts +++ b/packages/diagrams/frontend/sirius-components-diagrams/src/index.ts @@ -20,6 +20,8 @@ export { convertLineStyle, isListLayoutStrategy } from './converter/convertDiagr export { AlignmentMap } from './converter/convertDiagram.types'; export { convertHandles } from './converter/convertHandles'; export { convertInsideLabel, convertLabelStyle, convertOutsideLabels } from './converter/convertLabel'; +export { diagramDialogContributionExtensionPoint } from './dialog/diagramDialogExtensionPoint'; +export type { DiagramDialogContribution, DialogComponentProps } from './dialog/diagramDialogExtensionPoint.types'; export type { GQLNodeDescription } from './graphql/query/nodeDescriptionFragment.types'; export type { GQLDiagram, GQLNodeLayoutData } from './graphql/subscription/diagramFragment.types'; export type { GQLEdge } from './graphql/subscription/edgeFragment.types'; @@ -53,6 +55,8 @@ export type { DiagramPaletteToolContextValue } from './renderer/palette/DiagramP export { DiagramPaletteToolContext } from './renderer/palette/DiagramPaletteToolContext'; export { DiagramPaletteToolContribution } from './renderer/palette/DiagramPaletteToolContribution'; export type { DiagramPaletteToolContributionComponentProps } from './renderer/palette/DiagramPaletteToolContribution.types'; +export { GQLToolVariableType } from './renderer/palette/Palette.types'; +export type { GQLToolVariable } from './renderer/palette/Palette.types'; export type { DiagramPanelActionProps } from './renderer/panel/DiagramPanel.types'; export { diagramPanelActionExtensionPoint } from './renderer/panel/DiagramPanelExtensionPoints'; export { DiagramRepresentation } from './representation/DiagramRepresentation'; diff --git a/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/DiagramRenderer.tsx b/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/DiagramRenderer.tsx index d0bbe4c2ef6..a73464928ee 100644 --- a/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/DiagramRenderer.tsx +++ b/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/DiagramRenderer.tsx @@ -361,7 +361,10 @@ export const DiagramRenderer = memo(({ diagramRefreshedEventPayload }: DiagramRe refElementId={groupPaletteRefElementId} hidePalette={hideGroupPalette} /> - + {diagramDescription.debug ? : null} {helperLinesEnabled ? : null} diff --git a/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/edge/MultiLabelEdge.tsx b/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/edge/MultiLabelEdge.tsx index 5b87e67d93b..d87bb94d635 100644 --- a/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/edge/MultiLabelEdge.tsx +++ b/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/edge/MultiLabelEdge.tsx @@ -79,7 +79,7 @@ export const MultiLabelEdge = memo( sourceHandleId, targetHandleId, }: EdgeProps) => { - const { beginLabel, endLabel, label, faded } = data || {}; + const { beginLabel, endLabel, label, faded, targetObjectId } = data || {}; const theme = useTheme(); const { nodeLayoutHandlers } = useContext(NodeTypeContext); @@ -169,7 +169,13 @@ export const MultiLabelEdge = memo( markerEnd={selected ? `${markerEnd?.slice(0, markerEnd.length - 1)}--selected)` : markerEnd} markerStart={selected ? `${markerStart?.slice(0, markerStart.length - 1)}--selected)` : markerStart} /> - {selected ? : null} + {selected ? ( + + ) : null} {beginLabel && (
diff --git a/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/node/FreeFormNode.tsx b/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/node/FreeFormNode.tsx index d30aa69d98b..e72a7b6f641 100644 --- a/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/node/FreeFormNode.tsx +++ b/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/node/FreeFormNode.tsx @@ -145,7 +145,13 @@ export const FreeFormNode = memo(({ data, id, selected, dragging }: NodeProps
{data.insideLabel &&
); diff --git a/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/node/ListNode.tsx b/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/node/ListNode.tsx index 7cf7be71830..c39c4a804ec 100644 --- a/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/node/ListNode.tsx +++ b/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/node/ListNode.tsx @@ -81,7 +81,11 @@ export const ListNode = memo(({ data, id, selected, dragging }: NodeProps {data.insideLabel ?