From f2be467f3e8310b551808911c13284038d15f86a Mon Sep 17 00:00:00 2001 From: Florian Barbin Date: Wed, 21 Aug 2024 19:15:10 +0200 Subject: [PATCH] [3873] Add the SelectionDialog on the EdgeTool Bug: https://github.com/eclipse-sirius/sirius-web/issues/3873 Signed-off-by: Florian Barbin --- CHANGELOG.adoc | 2 + .../CompatibilityPaletteProvider.java | 2 +- .../collaborative/diagrams/ToolService.java | 39 +++++++- .../diagrams/api/IToolService.java | 14 ++- ...gleClickOnTwoDiagramElementsToolInput.java | 4 +- .../SingleClickOnTwoDiagramElementsTool.java | 13 ++- ...ClickOnDiagramElementToolEventHandler.java | 25 +----- ...kOnTwoDiagramElementsToolEventHandler.java | 7 +- .../main/resources/schema/diagram.graphqls | 2 + ...OnDiagramElementToolEventHandlerTests.java | 4 +- .../SingleClickOnTwoDiagramElementsTool.java | 17 +++- .../src/dialog/DialogContext.tsx | 33 ++++--- .../src/dialog/DialogContext.types.ts | 21 +++-- .../DialogContextExtensionPoints.types.ts | 11 ++- .../src/dialog/useDialog.tsx | 4 +- .../src/dialog/useDialog.types.ts | 10 ++- .../sirius-components-diagrams/src/index.ts | 1 + .../connector/ConnectorContextualMenu.tsx | 50 +++++++++++ .../ConnectorContextualMenu.types.ts | 29 ++++-- .../renderer/connector/useConnector.types.ts | 23 +++-- .../handles/useConnectionCandidatesQuery.ts | 44 +++++---- .../src/renderer/palette/Palette.tsx | 14 +-- .../src/renderer/palette/Palette.types.ts | 29 +++--- .../GetSelectionDescriptionMessageInput.java | 5 +- .../dto/SelectionDialogVariable.java | 26 ++++++ ...lectionDescriptionMessageEventHandler.java | 22 +++-- .../main/resources/schema/selection.graphqls | 7 +- ...electionDescriptionMessageDataFetcher.java | 18 +++- .../src/SelectionDialog.tsx | 6 +- .../src/SelectionDialogTreeView.tsx | 17 ++-- .../src/SelectionDialogTreeView.types.ts | 4 +- .../src/useSelectionDescription.ts | 12 ++- .../src/useSelectionDescription.types.ts | 6 +- .../diagrams/EdgeControllerTests.java | 3 +- .../SelectionControllerIntegrationTests.java | 36 +++++--- .../SelectionDescriptionProvider.java | 43 ++++++++- .../generated/diagram/EdgeToolBuilder.java | 10 +++ .../provider/EdgeToolItemProvider.java | 45 +++++++++- .../src/main/resources/plugin.properties | 1 + .../view/diagram/DiagramPackage.java | 31 ++++++- .../components/view/diagram/EdgeTool.java | 26 +++++- .../view/diagram/impl/DiagramPackageImpl.java | 13 +++ .../view/diagram/impl/EdgeToolImpl.java | 89 ++++++++++++++++++- .../src/main/resources/model/diagram.ecore | 2 + .../src/main/resources/model/diagram.genmodel | 1 + .../SelectionDialogDescriptionConverter.java | 43 +++++++-- .../view/emf/diagram/ToolConverter.java | 1 + .../view/emf/diagram/ViewPaletteProvider.java | 25 ++++-- 48 files changed, 705 insertions(+), 185 deletions(-) create mode 100644 packages/selection/backend/sirius-components-collaborative-selection/src/main/java/org/eclipse/sirius/components/collaborative/selection/dto/SelectionDialogVariable.java diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index 73ca51da9e..3ce95d96bb 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -68,6 +68,7 @@ The new endpoints are: description (optional). ** deleteProject (`POST /api/rest/projects/{projectId}`): Delete the project with the given id (projectId). ** updateProject (`PUT /projects/{projectId}`): Update the project with the given id (projectId). +- https://github.com/eclipse-sirius/sirius-web/issues/3873[#3873] [diagram] Make the Selection Dialog available for the EdgeTool === Improvements @@ -200,6 +201,7 @@ Introduce new `IRewriteProxiesResourceFilter` interface, to register resource fi image:doc/screenshots/treeItemLabelStyled.jpg[StyledString, 70%] - https://github.com/eclipse-sirius/sirius-web/issues/3963[#3963] [core] Add support for optional GraphQLCodeRegistry post-processing/transformation. + === Improvements - https://github.com/eclipse-sirius/sirius-web/issues/3744[#3744] [diagram] Add support for helper lines during multi selection move 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 92e8796a7d..6641939176 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 @@ -141,7 +141,7 @@ private ITool convertTool(org.eclipse.sirius.components.diagrams.tools.ITool too candidates.add(convertedCandidate); }); convertedTool = new SingleClickOnTwoDiagramElementsTool(singleClickOnTwoDiagramElementsTool.getId(), singleClickOnTwoDiagramElementsTool.getLabel(), - singleClickOnTwoDiagramElementsTool.getIconURL(), candidates); + singleClickOnTwoDiagramElementsTool.getIconURL(), candidates, null); } return convertedTool; } diff --git a/packages/diagrams/backend/sirius-components-collaborative-diagrams/src/main/java/org/eclipse/sirius/components/collaborative/diagrams/ToolService.java b/packages/diagrams/backend/sirius-components-collaborative-diagrams/src/main/java/org/eclipse/sirius/components/collaborative/diagrams/ToolService.java index 359312e948..c64f872354 100644 --- a/packages/diagrams/backend/sirius-components-collaborative-diagrams/src/main/java/org/eclipse/sirius/components/collaborative/diagrams/ToolService.java +++ b/packages/diagrams/backend/sirius-components-collaborative-diagrams/src/main/java/org/eclipse/sirius/components/collaborative/diagrams/ToolService.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 @@ -18,12 +18,15 @@ import java.util.stream.Stream; import org.eclipse.sirius.components.collaborative.diagrams.api.IToolService; +import org.eclipse.sirius.components.collaborative.diagrams.dto.ToolVariable; import org.eclipse.sirius.components.core.api.IEditingContext; +import org.eclipse.sirius.components.core.api.IObjectService; import org.eclipse.sirius.components.core.api.IRepresentationDescriptionSearchService; import org.eclipse.sirius.components.diagrams.Diagram; import org.eclipse.sirius.components.diagrams.description.DiagramDescription; import org.eclipse.sirius.components.diagrams.tools.ITool; import org.eclipse.sirius.components.diagrams.tools.Palette; +import org.eclipse.sirius.components.representations.VariableManager; import org.springframework.stereotype.Service; /** @@ -34,10 +37,15 @@ @Service public class ToolService implements IToolService { + private static final String OBJECT_ID_ARRAY_SEPARATOR = ","; + private final IRepresentationDescriptionSearchService representationDescriptionSearchService; - public ToolService(IRepresentationDescriptionSearchService representationDescriptionSearchService) { + private final IObjectService objectService; + + public ToolService(IRepresentationDescriptionSearchService representationDescriptionSearchService, IObjectService objectService) { this.representationDescriptionSearchService = Objects.requireNonNull(representationDescriptionSearchService); + this.objectService = Objects.requireNonNull(objectService); } private List getPalettes(IEditingContext editingContext, Diagram diagram) { @@ -61,4 +69,31 @@ public Optional findToolById(IEditingContext editingContext, Diagram diag .findFirst(); } + @Override + public void addToolVariablesInVariableManager(List toolvariables, IEditingContext editingContext, VariableManager variableManager) { + toolvariables.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 -> { + //We do nothing, the variable type is not supported + } + } + } + } diff --git a/packages/diagrams/backend/sirius-components-collaborative-diagrams/src/main/java/org/eclipse/sirius/components/collaborative/diagrams/api/IToolService.java b/packages/diagrams/backend/sirius-components-collaborative-diagrams/src/main/java/org/eclipse/sirius/components/collaborative/diagrams/api/IToolService.java index f91f9a8f66..a251479279 100644 --- a/packages/diagrams/backend/sirius-components-collaborative-diagrams/src/main/java/org/eclipse/sirius/components/collaborative/diagrams/api/IToolService.java +++ b/packages/diagrams/backend/sirius-components-collaborative-diagrams/src/main/java/org/eclipse/sirius/components/collaborative/diagrams/api/IToolService.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2019, 2022 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 @@ -12,11 +12,14 @@ *******************************************************************************/ package org.eclipse.sirius.components.collaborative.diagrams.api; +import java.util.List; import java.util.Optional; +import org.eclipse.sirius.components.collaborative.diagrams.dto.ToolVariable; import org.eclipse.sirius.components.core.api.IEditingContext; import org.eclipse.sirius.components.diagrams.Diagram; import org.eclipse.sirius.components.diagrams.tools.ITool; +import org.eclipse.sirius.components.representations.VariableManager; /** * Interface used to manipulate tools. @@ -27,6 +30,11 @@ public interface IToolService { Optional findToolById(IEditingContext editingContext, Diagram diagram, String toolId); + /** + * Used to compute and add variables providing by the tool from the graphQL API to the {@link VariableManager}. + */ + void addToolVariablesInVariableManager(List toolvariables, IEditingContext editingContext, VariableManager variableManager); + /** * Implementation which does nothing, used for mocks in unit tests. * @@ -37,5 +45,9 @@ class NoOp implements IToolService { public Optional findToolById(IEditingContext editingContext, Diagram diagram, String toolId) { return Optional.empty(); } + + @Override + public void addToolVariablesInVariableManager(List toolvariables, IEditingContext editingContext, VariableManager variableManager) { + } } } diff --git a/packages/diagrams/backend/sirius-components-collaborative-diagrams/src/main/java/org/eclipse/sirius/components/collaborative/diagrams/dto/InvokeSingleClickOnTwoDiagramElementsToolInput.java b/packages/diagrams/backend/sirius-components-collaborative-diagrams/src/main/java/org/eclipse/sirius/components/collaborative/diagrams/dto/InvokeSingleClickOnTwoDiagramElementsToolInput.java index ac4998fdbb..3749c9703f 100644 --- a/packages/diagrams/backend/sirius-components-collaborative-diagrams/src/main/java/org/eclipse/sirius/components/collaborative/diagrams/dto/InvokeSingleClickOnTwoDiagramElementsToolInput.java +++ b/packages/diagrams/backend/sirius-components-collaborative-diagrams/src/main/java/org/eclipse/sirius/components/collaborative/diagrams/dto/InvokeSingleClickOnTwoDiagramElementsToolInput.java @@ -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; @@ -32,5 +33,6 @@ public record InvokeSingleClickOnTwoDiagramElementsToolInput( double sourcePositionY, double targetPositionX, double targetPositionY, - String toolId) implements IDiagramInput { + String toolId, + List variables) implements IDiagramInput { } diff --git a/packages/diagrams/backend/sirius-components-collaborative-diagrams/src/main/java/org/eclipse/sirius/components/collaborative/diagrams/dto/SingleClickOnTwoDiagramElementsTool.java b/packages/diagrams/backend/sirius-components-collaborative-diagrams/src/main/java/org/eclipse/sirius/components/collaborative/diagrams/dto/SingleClickOnTwoDiagramElementsTool.java index 5a2d96c069..cdb8352342 100644 --- a/packages/diagrams/backend/sirius-components-collaborative-diagrams/src/main/java/org/eclipse/sirius/components/collaborative/diagrams/dto/SingleClickOnTwoDiagramElementsTool.java +++ b/packages/diagrams/backend/sirius-components-collaborative-diagrams/src/main/java/org/eclipse/sirius/components/collaborative/diagrams/dto/SingleClickOnTwoDiagramElementsTool.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 @@ -20,7 +20,7 @@ * * @author mcharfadi */ -public record SingleClickOnTwoDiagramElementsTool(String id, String label, List iconURL, List candidates) implements ITool { +public record SingleClickOnTwoDiagramElementsTool(String id, String label, List iconURL, List candidates, String dialogDescriptionId) implements ITool { public SingleClickOnTwoDiagramElementsTool { Objects.requireNonNull(id); @@ -50,6 +50,8 @@ public static final class Builder { private List candidates; + private String dialogDescriptionId; + private Builder(String id) { this.id = Objects.requireNonNull(id); } @@ -69,8 +71,13 @@ public SingleClickOnTwoDiagramElementsTool.Builder candidates(List this.handleToolVariable(toolVariable, editingContext, variableManager)); - } + this.toolService.addToolVariablesInVariableManager(variables, editingContext, variableManager); //We do not apply the tool if a dialog is defined but no variables have been provided if (dialogDescriptionId == null || !variables.isEmpty()) { @@ -154,26 +151,6 @@ private IStatus executeTool(IEditingContext editingContext, IDiagramContext diag return result; } - 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/java/org/eclipse/sirius/components/collaborative/diagrams/handlers/InvokeSingleClickOnTwoDiagramElementsToolEventHandler.java b/packages/diagrams/backend/sirius-components-collaborative-diagrams/src/main/java/org/eclipse/sirius/components/collaborative/diagrams/handlers/InvokeSingleClickOnTwoDiagramElementsToolEventHandler.java index f94d290087..5960d880d7 100644 --- a/packages/diagrams/backend/sirius-components-collaborative-diagrams/src/main/java/org/eclipse/sirius/components/collaborative/diagrams/handlers/InvokeSingleClickOnTwoDiagramElementsToolEventHandler.java +++ b/packages/diagrams/backend/sirius-components-collaborative-diagrams/src/main/java/org/eclipse/sirius/components/collaborative/diagrams/handlers/InvokeSingleClickOnTwoDiagramElementsToolEventHandler.java @@ -112,7 +112,7 @@ public void handle(One payloadSink, Many changeDesc .map(SingleClickOnTwoDiagramElementsTool.class::cast) .or(this.findConnectorToolById(input.diagramSourceElementId(), input.diagramTargetElementId(), editingContext, diagram, input.toolId())); if (optionalTool.isPresent()) { - IStatus status = this.executeTool(editingContext, diagramContext, input.diagramSourceElementId(), input.diagramTargetElementId(), optionalTool.get()); + IStatus status = this.executeTool(editingContext, diagramContext, input, optionalTool.get()); if (status instanceof Success success) { WorkbenchSelection newSelection = null; Object newSelectionParameter = success.getParameters().get(Success.NEW_SELECTION); @@ -131,7 +131,9 @@ public void handle(One payloadSink, Many changeDesc changeDescriptionSink.tryEmitNext(changeDescription); } - private IStatus executeTool(IEditingContext editingContext, IDiagramContext diagramContext, String sourceNodeId, String targetNodeId, SingleClickOnTwoDiagramElementsTool tool) { + private IStatus executeTool(IEditingContext editingContext, IDiagramContext diagramContext, InvokeSingleClickOnTwoDiagramElementsToolInput input, SingleClickOnTwoDiagramElementsTool tool) { + String sourceNodeId = input.diagramSourceElementId(); + String targetNodeId = input.diagramTargetElementId(); IStatus result = new Failure(""); Diagram diagram = diagramContext.getDiagram(); Optional sourceNode = this.diagramQueryService.findNodeById(diagram, sourceNodeId); @@ -157,6 +159,7 @@ private IStatus executeTool(IEditingContext editingContext, IDiagramContext diag variableManager.put(EdgeDescription.SEMANTIC_EDGE_TARGET, target.get()); variableManager.put(EdgeDescription.EDGE_SOURCE, sourceView); variableManager.put(EdgeDescription.EDGE_TARGET, targetView); + this.toolService.addToolVariablesInVariableManager(input.variables(), editingContext, variableManager); result = tool.getHandler().apply(variableManager); } 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 0cd366eefa..fd3cf38fa5 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 @@ -290,6 +290,7 @@ type SingleClickOnTwoDiagramElementsTool implements Tool { id: ID! label: String! iconURL: [String!]! + dialogDescriptionId: String candidates: [SingleClickOnTwoDiagramElementsCandidate]! } @@ -436,6 +437,7 @@ input InvokeSingleClickOnTwoDiagramElementsToolInput { sourcePositionY: Float! targetPositionX: Float! targetPositionY: Float! + variables: [ToolVariable!]! } union InvokeSingleClickOnTwoDiagramElementsToolPayload = ErrorPayload | InvokeSingleClickOnTwoDiagramElementsToolSuccessPayload 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 f487bf9ba6..56dda10896 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 @@ -25,6 +25,7 @@ import org.eclipse.sirius.components.collaborative.api.ChangeDescription; import org.eclipse.sirius.components.collaborative.api.ChangeKind; import org.eclipse.sirius.components.collaborative.diagrams.DiagramContext; +import org.eclipse.sirius.components.collaborative.diagrams.ToolService; import org.eclipse.sirius.components.collaborative.diagrams.api.IDiagramContext; import org.eclipse.sirius.components.collaborative.diagrams.api.IDiagramQueryService; import org.eclipse.sirius.components.collaborative.diagrams.api.IToolService; @@ -37,6 +38,7 @@ import org.eclipse.sirius.components.core.api.IEditingContext; import org.eclipse.sirius.components.core.api.IObjectService; import org.eclipse.sirius.components.core.api.IPayload; +import org.eclipse.sirius.components.core.api.IRepresentationDescriptionSearchService; import org.eclipse.sirius.components.diagrams.ArrowStyle; import org.eclipse.sirius.components.diagrams.CollapsingState; import org.eclipse.sirius.components.diagrams.Diagram; @@ -241,7 +243,7 @@ public Optional findNodeById(Diagram diagram, String nodeId) { var tool = this.createTool(TOOL_ID, false, List.of(nodeDescription), DIALOG_DESCRIPTION_ID, toolHandler); - var toolService = new IToolService.NoOp() { + var toolService = new ToolService(new IRepresentationDescriptionSearchService.NoOp(), objectService) { @Override public Optional findToolById(IEditingContext editingContext, Diagram diagram, String toolId) { return Optional.of(tool); diff --git a/packages/diagrams/backend/sirius-components-diagrams/src/main/java/org/eclipse/sirius/components/diagrams/tools/SingleClickOnTwoDiagramElementsTool.java b/packages/diagrams/backend/sirius-components-diagrams/src/main/java/org/eclipse/sirius/components/diagrams/tools/SingleClickOnTwoDiagramElementsTool.java index 4c957a902f..bfcee6ba63 100644 --- a/packages/diagrams/backend/sirius-components-diagrams/src/main/java/org/eclipse/sirius/components/diagrams/tools/SingleClickOnTwoDiagramElementsTool.java +++ b/packages/diagrams/backend/sirius-components-diagrams/src/main/java/org/eclipse/sirius/components/diagrams/tools/SingleClickOnTwoDiagramElementsTool.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 @@ -40,6 +40,8 @@ public final class SingleClickOnTwoDiagramElementsTool implements ITool { private List candidates; + private String dialogDescriptionId; + private SingleClickOnTwoDiagramElementsTool() { // Prevent instantiation } @@ -72,6 +74,10 @@ public Function getHandler() { return this.handler; } + public String getDialogDescriptionId() { + return this.dialogDescriptionId; + } + @Override public String toString() { String pattern = "{0} '{'id: {1}, label: {2}'}'"; @@ -96,6 +102,8 @@ public static final class Builder { private List candidates; + private String dialogDescriptionId; + private Builder(String id) { this.id = Objects.requireNonNull(id); } @@ -120,6 +128,11 @@ public Builder handler(Function handler) { return this; } + public Builder dialogDescriptionId(String dialogDescriptionId) { + this.dialogDescriptionId = dialogDescriptionId; + return this; + } + public SingleClickOnTwoDiagramElementsTool build() { SingleClickOnTwoDiagramElementsTool tool = new SingleClickOnTwoDiagramElementsTool(); tool.id = Objects.requireNonNull(this.id); @@ -127,6 +140,8 @@ public SingleClickOnTwoDiagramElementsTool build() { tool.label = Objects.requireNonNull(this.label); tool.handler = Objects.requireNonNull(this.handler); tool.candidates = Objects.requireNonNull(this.candidates); + //The dialog description id can be null. + 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 index 420a15820d..153e0e434e 100644 --- a/packages/diagrams/frontend/sirius-components-diagrams/src/dialog/DialogContext.tsx +++ b/packages/diagrams/frontend/sirius-components-diagrams/src/dialog/DialogContext.tsx @@ -15,13 +15,17 @@ import { useData } from '@eclipse-sirius/sirius-components-core'; import React, { useContext, useState } from 'react'; import { DiagramContext } from '../contexts/DiagramContext'; import { DiagramContextValue } from '../contexts/DiagramContext.types'; -import { GQLToolVariable } from '../renderer/palette/Palette.types'; -import { DialogContextProviderState, DialogContextValue } from './DialogContext.types'; +import { DialogContextProviderState, DialogContextValue, ToolVariable } from './DialogContext.types'; import { diagramDialogContributionExtensionPoint } from './DialogContextExtensionPoints'; -import { DiagramDialogComponentProps, DiagramDialogContribution } from './DialogContextExtensionPoints.types'; +import { + DiagramDialogComponentProps, + DiagramDialogContribution, + DiagramDialogVariable, +} from './DialogContextExtensionPoints.types'; const defaultValue: DialogContextValue = { showDialog: () => {}, + isOpened: false, }; export const DialogContext = React.createContext(defaultValue); @@ -29,8 +33,9 @@ export const DialogContext = React.createContext(defaultValu export const DialogContextProvider = ({ children }) => { const [state, setState] = useState({ dialogDescriptionId: null, - targetObjectId: null, + variables: [], onConfirm: () => {}, + onClose: () => {}, open: false, }); @@ -38,18 +43,22 @@ export const DialogContextProvider = ({ children }) => { const showDialog = ( dialogDescriptionId: string, - targetObjectId: string, - onConfirm: (variables: GQLToolVariable[]) => void + variables: DiagramDialogVariable[], + onConfirm: (variables: ToolVariable[]) => void, + onClose: () => void ) => { - setState({ open: true, dialogDescriptionId, targetObjectId, onConfirm }); + if (!state.open) { + setState({ open: true, dialogDescriptionId, variables, onConfirm, onClose }); + } }; - const onFinish = (toolVariables: GQLToolVariable[]) => { + const onFinish = (toolVariables: ToolVariable[]) => { state.onConfirm(toolVariables); setState((prevState) => ({ ...prevState, open: false, dialogTypeId: undefined })); }; - const onClose = () => { + const internalClose = () => { + state.onClose(); setState((prevState) => ({ ...prevState, open: false, dialogTypeId: undefined })); }; @@ -59,9 +68,9 @@ export const DialogContextProvider = ({ children }) => { const dialogComponentProps: DiagramDialogComponentProps = { editingContextId, dialogDescriptionId: state.dialogDescriptionId ?? '', - targetObjectId: state.targetObjectId ?? '', + variables: state.variables ?? '', onFinish, - onClose, + onClose: internalClose, }; if (state.open && state.dialogDescriptionId) { const dialogDescriptionId: string = state.dialogDescriptionId; @@ -73,7 +82,7 @@ export const DialogContextProvider = ({ children }) => { } } 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 index 565f6165dd..700af021f4 100644 --- a/packages/diagrams/frontend/sirius-components-diagrams/src/dialog/DialogContext.types.ts +++ b/packages/diagrams/frontend/sirius-components-diagrams/src/dialog/DialogContext.types.ts @@ -11,19 +11,30 @@ * Obeo - initial API and implementation *******************************************************************************/ -import { GQLToolVariable } from '../renderer/palette/Palette.types'; +import { DiagramDialogVariable } from './DialogContextExtensionPoints.types'; export interface DialogContextValue { showDialog: ( dialogDescriptionId: string, - targetObjectId: string, - onConfirm: (variables: GQLToolVariable[]) => void + variables: DiagramDialogVariable[], + onConfirm: (variables: ToolVariable[]) => void, + onClose: () => void ) => void; + isOpened: boolean; } export interface DialogContextProviderState { open: boolean; dialogDescriptionId: string | null; - targetObjectId: string | null; - onConfirm: (variables: GQLToolVariable[]) => void; + variables: DiagramDialogVariable[]; + onConfirm: (variables: ToolVariable[]) => void; + onClose: () => void; } + +export interface ToolVariable { + name: string; + value: string; + type: ToolVariableType; +} + +export type ToolVariableType = 'STRING' | 'OBJECT_ID' | 'OBJECT_ID_ARRAY'; diff --git a/packages/diagrams/frontend/sirius-components-diagrams/src/dialog/DialogContextExtensionPoints.types.ts b/packages/diagrams/frontend/sirius-components-diagrams/src/dialog/DialogContextExtensionPoints.types.ts index c8a76b8fea..9a7ef1027b 100644 --- a/packages/diagrams/frontend/sirius-components-diagrams/src/dialog/DialogContextExtensionPoints.types.ts +++ b/packages/diagrams/frontend/sirius-components-diagrams/src/dialog/DialogContextExtensionPoints.types.ts @@ -11,7 +11,7 @@ * Obeo - initial API and implementation *******************************************************************************/ -import { GQLToolVariable } from '../renderer/palette/Palette.types'; +import { ToolVariable } from './DialogContext.types'; export interface DiagramDialogContribution { canHandle: (dialogDescriptionId: string) => boolean; @@ -21,7 +21,12 @@ export interface DiagramDialogContribution { export interface DiagramDialogComponentProps { editingContextId: string; dialogDescriptionId: string; - targetObjectId: string; + variables: DiagramDialogVariable[]; onClose: () => void; - onFinish: (variables: GQLToolVariable[]) => void; + onFinish: (variables: ToolVariable[]) => void; +} + +export interface DiagramDialogVariable { + name: string; + value: string; } diff --git a/packages/diagrams/frontend/sirius-components-diagrams/src/dialog/useDialog.tsx b/packages/diagrams/frontend/sirius-components-diagrams/src/dialog/useDialog.tsx index b716da29ab..d0632caa08 100644 --- a/packages/diagrams/frontend/sirius-components-diagrams/src/dialog/useDialog.tsx +++ b/packages/diagrams/frontend/sirius-components-diagrams/src/dialog/useDialog.tsx @@ -17,7 +17,7 @@ import { DialogContextValue } from './DialogContext.types'; import { UseDialogValue } from './useDialog.types'; export const useDialog = (): UseDialogValue => { - const { showDialog } = useContext(DialogContext); + const { showDialog, isOpened } = useContext(DialogContext); - return { showDialog }; + return { showDialog, isOpened }; }; 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 index f48dce3b7a..2cdb498120 100644 --- a/packages/diagrams/frontend/sirius-components-diagrams/src/dialog/useDialog.types.ts +++ b/packages/diagrams/frontend/sirius-components-diagrams/src/dialog/useDialog.types.ts @@ -10,12 +10,16 @@ * Contributors: * Obeo - initial API and implementation *******************************************************************************/ -import { GQLToolVariable } from '../renderer/palette/Palette.types'; + +import { ToolVariable } from './DialogContext.types'; +import { DiagramDialogVariable } from './DialogContextExtensionPoints.types'; export interface UseDialogValue { showDialog: ( dialogDescriptionId: string, - targetObjectId: string, - onConfirm: (variables: GQLToolVariable[]) => void + variables: DiagramDialogVariable[], + onConfirm: (variables: ToolVariable[]) => void, + onClose: () => void ) => void; + isOpened: boolean; } diff --git a/packages/diagrams/frontend/sirius-components-diagrams/src/index.ts b/packages/diagrams/frontend/sirius-components-diagrams/src/index.ts index 69430711bf..e6cc73cce0 100644 --- a/packages/diagrams/frontend/sirius-components-diagrams/src/index.ts +++ b/packages/diagrams/frontend/sirius-components-diagrams/src/index.ts @@ -24,6 +24,7 @@ export { diagramDialogContributionExtensionPoint } from './dialog/DialogContextE export type { DiagramDialogComponentProps, DiagramDialogContribution, + DiagramDialogVariable, } from './dialog/DialogContextExtensionPoints.types'; export { useDialog } from './dialog/useDialog'; export type { UseDialogValue } from './dialog/useDialog.types'; diff --git a/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/connector/ConnectorContextualMenu.tsx b/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/connector/ConnectorContextualMenu.tsx index ad2ee4434b..19c5170c7d 100644 --- a/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/connector/ConnectorContextualMenu.tsx +++ b/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/connector/ConnectorContextualMenu.tsx @@ -18,8 +18,12 @@ import Menu from '@mui/material/Menu'; import MenuItem from '@mui/material/MenuItem'; import Typography from '@mui/material/Typography'; import { memo, useContext, useEffect } from 'react'; +import { useReactFlow } from 'reactflow'; import { DiagramContext } from '../../contexts/DiagramContext'; import { DiagramContextValue } from '../../contexts/DiagramContext.types'; +import { DiagramDialogVariable } from '../../dialog/DialogContextExtensionPoints.types'; +import { useDialog } from '../../dialog/useDialog'; +import { EdgeData, NodeData } from '../DiagramRenderer.types'; import { ConnectorContextualMenuProps, GQLDiagramDescription, @@ -31,10 +35,12 @@ import { GQLRepresentationDescription, GQLSuccessPayload, GQLTool, + GQLToolVariable, GetConnectorToolsData, GetConnectorToolsVariables, } from './ConnectorContextualMenu.types'; import { useConnector } from './useConnector'; +import { GQLSingleClickOnTwoDiagramElementsTool } from './useConnector.types'; export const getConnectorToolsQuery = gql` query getConnectorTools( @@ -55,6 +61,9 @@ export const getConnectorToolsQuery = gql` id label iconURL + ... on SingleClickOnTwoDiagramElementsTool { + dialogDescriptionId + } } } } @@ -100,12 +109,19 @@ const isErrorPayload = (payload: GQLInvokeSingleClickOnTwoDiagramElementsToolPay const isSuccessPayload = (payload: GQLInvokeSingleClickOnTwoDiagramElementsToolPayload): payload is GQLSuccessPayload => payload.__typename === 'InvokeSingleClickOnTwoDiagramElementsToolSuccessPayload'; +const isSingleClickOnTwoDiagramElementsTool = (tool: GQLTool): tool is GQLSingleClickOnTwoDiagramElementsTool => + tool.__typename === 'SingleClickOnTwoDiagramElementsTool'; + const ConnectorContextualMenuComponent = memo(({}: ConnectorContextualMenuProps) => { const { editingContextId, diagramId } = useContext(DiagramContext); const { connection, position, onConnectorContextualMenuClose, addTempConnectionLine, removeTempConnectionLine } = useConnector(); const { addMessages, addErrorMessage } = useMultiToast(); + const { showDialog, isOpened } = useDialog(); + + const { getNodes } = useReactFlow(); + const connectionSource: HTMLElement | null = connection ? document.querySelector(`[data-id="${connection.source}"]`) : null; @@ -128,6 +144,27 @@ const ConnectorContextualMenuComponent = memo(({}: ConnectorContextualMenuProps) skip: !connectionSource || !connectionTarget, }); + const invokeOpenSelectionDialog = (tool: GQLSingleClickOnTwoDiagramElementsTool) => { + const onConfirm = (variables: GQLToolVariable[]) => { + invokeToolMutation(tool, variables); + }; + + const onClose = () => { + onShouldConnectorContextualMenuClose(); + }; + + const sourceNode = getNodes().find((node) => node.id === sourceDiagramElementId); + const targetNode = getNodes().find((node) => node.id === targetDiagramElementId); + if (sourceNode && targetNode) { + const variables: DiagramDialogVariable[] = [ + { name: 'targetObjectId', value: sourceNode.data.targetObjectId }, + { name: 'sourceDiagramElementTargetObjectId', value: sourceNode.data.targetObjectId }, + { name: 'targetDiagramElementTargetObjectId', value: targetNode.data.targetObjectId }, + ]; + showDialog(tool.dialogDescriptionId, variables, onConfirm, onClose); + } + }; + useEffect(() => { if (error) { addErrorMessage(error.message); @@ -148,6 +185,18 @@ const ConnectorContextualMenuComponent = memo(({}: ConnectorContextualMenuProps) >(invokeSingleClickOnTwoDiagramElementsToolMutation); const invokeTool = (tool: GQLTool) => { + if (isSingleClickOnTwoDiagramElementsTool(tool)) { + if (tool.dialogDescriptionId) { + if (!isOpened) { + invokeOpenSelectionDialog(tool); + } + } else { + invokeToolMutation(tool, []); + } + } + }; + + const invokeToolMutation = (tool: GQLTool, variables: GQLToolVariable[]) => { const input: GQLInvokeSingleClickOnTwoDiagramElementsToolInput = { id: crypto.randomUUID(), editingContextId, @@ -159,6 +208,7 @@ const ConnectorContextualMenuComponent = memo(({}: ConnectorContextualMenuProps) sourcePositionY: 0, targetPositionX: 0, targetPositionY: 0, + variables, }; invokeSingleClickOnTwoDiagramElementsTool({ variables: { input } }); }; diff --git a/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/connector/ConnectorContextualMenu.types.ts b/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/connector/ConnectorContextualMenu.types.ts index 526751c1ec..ed4e8ac17a 100644 --- a/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/connector/ConnectorContextualMenu.types.ts +++ b/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/connector/ConnectorContextualMenu.types.ts @@ -11,9 +11,14 @@ * Obeo - initial API and implementation *******************************************************************************/ +import { GQLSingleClickOnTwoDiagramElementsTool } from './useConnector.types'; + export interface ConnectorContextualMenuProps {} -export interface ConnectorContextualMenuState {} +export interface ConnectorContextualMenuState { + openDialogInvoked: boolean; + tool: GQLSingleClickOnTwoDiagramElementsTool | null; +} export interface GetConnectorToolsVariables { editingContextId: string; @@ -22,6 +27,20 @@ export interface GetConnectorToolsVariables { targetDiagramElementId: string; } +export interface GQLTool { + id: string; + label: string; + iconURL: string[]; + __typename: string; +} + +export interface GQLToolVariable { + name: string; + value: string; + type: GQLToolVariableType; +} + +export type GQLToolVariableType = 'STRING' | 'OBJECT_ID' | 'OBJECT_ID_ARRAY'; export interface GetConnectorToolsData { viewer: GQLViewer; } @@ -46,16 +65,9 @@ export interface GQLDiagramDescription extends GQLRepresentationDescription { connectorTools: GQLTool[]; } -export interface GQLTool { - id: string; - label: string; - iconURL: string[]; -} - export interface GQLInvokeSingleClickOnTwoDiagramElementsToolVariables { input: GQLInvokeSingleClickOnTwoDiagramElementsToolInput; } - export interface GQLInvokeSingleClickOnTwoDiagramElementsToolInput { id: string; editingContextId: string; @@ -67,6 +79,7 @@ export interface GQLInvokeSingleClickOnTwoDiagramElementsToolInput { targetPositionX: number; targetPositionY: number; toolId: string; + variables: GQLToolVariable[]; } export interface GQLInvokeSingleClickOnTwoDiagramElementsToolData { diff --git a/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/connector/useConnector.types.ts b/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/connector/useConnector.types.ts index 4f2011ff68..20ee003ac3 100644 --- a/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/connector/useConnector.types.ts +++ b/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/connector/useConnector.types.ts @@ -28,6 +28,21 @@ export interface UseConnectorValue { candidates: GQLNodeDescription[]; } +export interface GQLTool { + id: string; + label: string; + iconURL: string[]; + __typename: string; +} + +export interface GQLToolVariable { + name: string; + value: string; + type: GQLToolVariableType; +} + +export type GQLToolVariableType = 'STRING' | 'OBJECT_ID' | 'OBJECT_ID_ARRAY'; + export interface GQLGetToolSectionsData { viewer: GQLViewer; } @@ -70,15 +85,9 @@ export interface GQLToolSection { tools: GQLTool[]; __typename: string; } - -export interface GQLTool { - id: string; - label: string; - imageURL: string; - __typename: string; -} export interface GQLSingleClickOnTwoDiagramElementsTool extends GQLTool { candidates: GQLSingleClickOnTwoDiagramElementsCandidate[]; + dialogDescriptionId: string; } export interface GQLSingleClickOnTwoDiagramElementsCandidate { sources: GQLNodeDescription[]; diff --git a/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/handles/useConnectionCandidatesQuery.ts b/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/handles/useConnectionCandidatesQuery.ts index dd8789e896..8e05623956 100644 --- a/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/handles/useConnectionCandidatesQuery.ts +++ b/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/handles/useConnectionCandidatesQuery.ts @@ -11,9 +11,9 @@ * Obeo - initial API and implementation *******************************************************************************/ import { gql, useQuery } from '@apollo/client'; -import { useNodes } from 'reactflow'; import { useMultiToast } from '@eclipse-sirius/sirius-components-core'; import { useEffect, useMemo } from 'react'; +import { useNodes } from 'reactflow'; import { GQLDiagramDescription, GQLGetToolSectionsData, @@ -25,7 +25,25 @@ import { } from '../connector/useConnector.types'; import { NodeData } from '../DiagramRenderer.types'; +const ToolFields = gql` + fragment ToolFields on Tool { + __typename + ... on SingleClickOnTwoDiagramElementsTool { + candidates { + sources { + id + } + targets { + id + } + } + dialogDescriptionId + } + } +`; + const getToolSectionsQuery = gql` + ${ToolFields} query getToolSections($editingContextId: ID!, $diagramId: ID!, $diagramElementId: ID!) { viewer { editingContext(editingContextId: $editingContextId) { @@ -34,31 +52,11 @@ const getToolSectionsQuery = gql` ... on DiagramDescription { palette(diagramElementId: $diagramElementId) { tools { - __typename - ... on SingleClickOnTwoDiagramElementsTool { - candidates { - sources { - id - } - targets { - id - } - } - } + ...ToolFields } toolSections { tools { - __typename - ... on SingleClickOnTwoDiagramElementsTool { - candidates { - sources { - id - } - targets { - id - } - } - } + ...ToolFields } } } diff --git a/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/palette/Palette.tsx b/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/palette/Palette.tsx index 6e6bfe42f9..8f9140e9f0 100644 --- a/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/palette/Palette.tsx +++ b/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/palette/Palette.tsx @@ -13,19 +13,19 @@ import { gql, useMutation, useQuery } from '@apollo/client'; import { + ComponentExtension, + useComponents, useDeletionConfirmationDialog, useMultiToast, - useComponents, - ComponentExtension, } from '@eclipse-sirius/sirius-components-core'; +import AdjustIcon from '@mui/icons-material/Adjust'; +import TonalityIcon from '@mui/icons-material/Tonality'; import IconButton from '@mui/material/IconButton'; import Paper from '@mui/material/Paper'; import Tooltip from '@mui/material/Tooltip'; -import { makeStyles } from 'tss-react/mui'; -import AdjustIcon from '@mui/icons-material/Adjust'; -import TonalityIcon from '@mui/icons-material/Tonality'; import { useCallback, useContext, useEffect, useState } from 'react'; import { useReactFlow, useViewport } from 'reactflow'; +import { makeStyles } from 'tss-react/mui'; import { DiagramContext } from '../../contexts/DiagramContext'; import { DiagramContextValue } from '../../contexts/DiagramContext.types'; import { useDialog } from '../../dialog/useDialog'; @@ -65,8 +65,8 @@ import { PaletteState, } from './Palette.types'; import { ToolSection } from './tool-section/ToolSection'; -import { diagramPaletteToolExtensionPoint } from './tool/DiagramPaletteToolExtensionPoints'; import { DiagramPaletteToolComponentProps } from './tool/DiagramPaletteTool.types'; +import { diagramPaletteToolExtensionPoint } from './tool/DiagramPaletteToolExtensionPoints'; const usePaletteStyle = makeStyles()((theme) => ({ palette: { @@ -421,7 +421,7 @@ export const Palette = ({ const onConfirm = (variables: GQLToolVariable[]) => { invokeSingleClickTool(tool, variables); }; - showDialog(tool.dialogDescriptionId, targetObjectId, onConfirm); + showDialog(tool.dialogDescriptionId, [{ name: 'targetObjectId', value: targetObjectId }], onConfirm, () => {}); }; const handleToolClick = (tool: GQLTool) => { diff --git a/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/palette/Palette.types.ts b/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/palette/Palette.types.ts index b21236ea66..e62621e79d 100644 --- a/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/palette/Palette.types.ts +++ b/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/palette/Palette.types.ts @@ -16,6 +16,21 @@ export interface ContextualPaletteStyleProps { toolCount: number; } +export interface GQLTool { + id: string; + label: string; + iconURL: string[]; + __typename: string; +} + +export interface GQLToolVariable { + name: string; + value: string; + type: GQLToolVariableType; +} + +export type GQLToolVariableType = 'STRING' | 'OBJECT_ID' | 'OBJECT_ID_ARRAY'; + export interface PaletteProps { x: number; y: number; @@ -76,20 +91,6 @@ export interface GQLInvokeSingleClickOnDiagramElementToolInput { startingPositionY: number; variables: GQLToolVariable[]; } -export interface GQLToolVariable { - name: string; - value: string; - type: GQLToolVariableType; -} - -export type GQLToolVariableType = 'STRING' | 'OBJECT_ID' | 'OBJECT_ID_ARRAY'; - -export interface GQLTool { - id: string; - label: string; - iconURL: string[]; - __typename: string; -} export interface GQLSingleClickOnDiagramElementTool extends GQLTool { appliesToDiagramRoot: boolean; diff --git a/packages/selection/backend/sirius-components-collaborative-selection/src/main/java/org/eclipse/sirius/components/collaborative/selection/dto/GetSelectionDescriptionMessageInput.java b/packages/selection/backend/sirius-components-collaborative-selection/src/main/java/org/eclipse/sirius/components/collaborative/selection/dto/GetSelectionDescriptionMessageInput.java index 63d9487a5a..b36749d019 100644 --- a/packages/selection/backend/sirius-components-collaborative-selection/src/main/java/org/eclipse/sirius/components/collaborative/selection/dto/GetSelectionDescriptionMessageInput.java +++ b/packages/selection/backend/sirius-components-collaborative-selection/src/main/java/org/eclipse/sirius/components/collaborative/selection/dto/GetSelectionDescriptionMessageInput.java @@ -12,6 +12,7 @@ *******************************************************************************/ package org.eclipse.sirius.components.collaborative.selection.dto; +import java.util.List; import java.util.Objects; import java.util.UUID; @@ -23,10 +24,10 @@ * * @author fbarbin */ -public record GetSelectionDescriptionMessageInput(UUID id, String targetObjectId, SelectionDescription selectionDescription) implements IInput { +public record GetSelectionDescriptionMessageInput(UUID id, List variables, SelectionDescription selectionDescription) implements IInput { public GetSelectionDescriptionMessageInput { Objects.requireNonNull(id); - Objects.requireNonNull(targetObjectId); + Objects.requireNonNull(variables); Objects.requireNonNull(selectionDescription); } } diff --git a/packages/selection/backend/sirius-components-collaborative-selection/src/main/java/org/eclipse/sirius/components/collaborative/selection/dto/SelectionDialogVariable.java b/packages/selection/backend/sirius-components-collaborative-selection/src/main/java/org/eclipse/sirius/components/collaborative/selection/dto/SelectionDialogVariable.java new file mode 100644 index 0000000000..721756edde --- /dev/null +++ b/packages/selection/backend/sirius-components-collaborative-selection/src/main/java/org/eclipse/sirius/components/collaborative/selection/dto/SelectionDialogVariable.java @@ -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 + *******************************************************************************/ +package org.eclipse.sirius.components.collaborative.selection.dto; + +import java.util.Objects; + +/** + * Represent a variable coming from the frontend selection dialog. + * @author fbarbin + */ +public record SelectionDialogVariable(String name, String value) { + public SelectionDialogVariable { + Objects.requireNonNull(name); + Objects.requireNonNull(value); + } +} diff --git a/packages/selection/backend/sirius-components-collaborative-selection/src/main/java/org/eclipse/sirius/components/collaborative/selection/handlers/SelectionDescriptionMessageEventHandler.java b/packages/selection/backend/sirius-components-collaborative-selection/src/main/java/org/eclipse/sirius/components/collaborative/selection/handlers/SelectionDescriptionMessageEventHandler.java index 782116d89a..934e64219a 100644 --- a/packages/selection/backend/sirius-components-collaborative-selection/src/main/java/org/eclipse/sirius/components/collaborative/selection/handlers/SelectionDescriptionMessageEventHandler.java +++ b/packages/selection/backend/sirius-components-collaborative-selection/src/main/java/org/eclipse/sirius/components/collaborative/selection/handlers/SelectionDescriptionMessageEventHandler.java @@ -20,6 +20,7 @@ import org.eclipse.sirius.components.collaborative.messages.ICollaborativeMessageService; import org.eclipse.sirius.components.collaborative.selection.dto.GetSelectionDescriptionMessageInput; import org.eclipse.sirius.components.collaborative.selection.dto.GetSelectionDescriptionMessagePayload; +import org.eclipse.sirius.components.collaborative.selection.dto.SelectionDialogVariable; import org.eclipse.sirius.components.core.api.ErrorPayload; import org.eclipse.sirius.components.core.api.IEditingContext; import org.eclipse.sirius.components.core.api.IInput; @@ -40,6 +41,8 @@ @Service public class SelectionDescriptionMessageEventHandler implements IEditingContextEventHandler { + private static final String TARGET_OBJECT_ID = "targetObjectId"; + private final ICollaborativeMessageService messageService; private final IObjectService objectService; @@ -57,12 +60,8 @@ public boolean canHandle(IEditingContext editingContext, IInput input) { @Override public void handle(One payloadSink, Many changeDescriptionSink, IEditingContext editingContext, IInput input) { if (input instanceof GetSelectionDescriptionMessageInput getSelectionDescriptionMessageInput) { - String targetObjectId = getSelectionDescriptionMessageInput.targetObjectId(); - Optional optionalTargetObject = this.objectService.getObject(editingContext, targetObjectId); VariableManager variableManager = new VariableManager(); - if (optionalTargetObject.isPresent()) { - variableManager.put(VariableManager.SELF, optionalTargetObject.get()); - } + getSelectionDescriptionMessageInput.variables().forEach(variable -> this.addToVariableManager(editingContext, variable, variableManager)); SelectionDescription selectionDescription = getSelectionDescriptionMessageInput.selectionDescription(); String message = selectionDescription.getMessageProvider().apply(variableManager); payloadSink.tryEmitValue(new GetSelectionDescriptionMessagePayload(input.id(), message)); @@ -71,4 +70,17 @@ public void handle(One payloadSink, Many changeDesc payloadSink.tryEmitValue(new ErrorPayload(input.id(), message)); } } + + private void addToVariableManager(IEditingContext editingContext, SelectionDialogVariable variable, VariableManager variableManager) { + Optional optionalObject = this.objectService.getObject(editingContext, variable.value()); + if (optionalObject.isPresent()) { + String variableName; + if (TARGET_OBJECT_ID.equals(variable.name())) { + variableName = VariableManager.SELF; + } else { + variableName = variable.name(); + } + variableManager.put(variableName, optionalObject.get()); + } + } } diff --git a/packages/selection/backend/sirius-components-collaborative-selection/src/main/resources/schema/selection.graphqls b/packages/selection/backend/sirius-components-collaborative-selection/src/main/resources/schema/selection.graphqls index b20181ccf5..bdbdae9e9a 100644 --- a/packages/selection/backend/sirius-components-collaborative-selection/src/main/resources/schema/selection.graphqls +++ b/packages/selection/backend/sirius-components-collaborative-selection/src/main/resources/schema/selection.graphqls @@ -11,6 +11,11 @@ input SelectionDialogTreeEventInput { type SelectionDescription implements RepresentationDescription { id: ID! label: String! - message(targetObjectId: ID!): String! + message(variables: [SelectionDialogVariable!]!): String! treeDescription: TreeDescription! } + +input SelectionDialogVariable { + name: String! + value: String! +} diff --git a/packages/selection/backend/sirius-components-selection-graphql/src/main/java/org/eclipse/sirius/components/selection/graphql/datafetchers/selection/SelectionDescriptionMessageDataFetcher.java b/packages/selection/backend/sirius-components-selection-graphql/src/main/java/org/eclipse/sirius/components/selection/graphql/datafetchers/selection/SelectionDescriptionMessageDataFetcher.java index 0ae1ba0e92..62fd3f87cd 100644 --- a/packages/selection/backend/sirius-components-selection-graphql/src/main/java/org/eclipse/sirius/components/selection/graphql/datafetchers/selection/SelectionDescriptionMessageDataFetcher.java +++ b/packages/selection/backend/sirius-components-selection-graphql/src/main/java/org/eclipse/sirius/components/selection/graphql/datafetchers/selection/SelectionDescriptionMessageDataFetcher.java @@ -12,6 +12,9 @@ *******************************************************************************/ package org.eclipse.sirius.components.selection.graphql.datafetchers.selection; +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; @@ -22,6 +25,7 @@ import org.eclipse.sirius.components.collaborative.api.IEditingContextEventProcessorRegistry; import org.eclipse.sirius.components.collaborative.selection.dto.GetSelectionDescriptionMessageInput; import org.eclipse.sirius.components.collaborative.selection.dto.GetSelectionDescriptionMessagePayload; +import org.eclipse.sirius.components.collaborative.selection.dto.SelectionDialogVariable; import org.eclipse.sirius.components.graphql.api.IDataFetcherWithFieldCoordinates; import org.eclipse.sirius.components.graphql.api.LocalContextConstants; import org.eclipse.sirius.components.selection.description.SelectionDescription; @@ -35,11 +39,14 @@ @QueryDataFetcher(type = "SelectionDescription", field = "message") public class SelectionDescriptionMessageDataFetcher implements IDataFetcherWithFieldCoordinates> { - private static final String TARGET_OBJECT_ID = "targetObjectId"; + private static final String VARIABLES = "variables"; private final IEditingContextEventProcessorRegistry editingContextEventProcessorRegistry; - public SelectionDescriptionMessageDataFetcher(IEditingContextEventProcessorRegistry editingContextEventProcessorRegistry) { + private final ObjectMapper objectMapper; + + public SelectionDescriptionMessageDataFetcher(ObjectMapper objectMapper, IEditingContextEventProcessorRegistry editingContextEventProcessorRegistry) { + this.objectMapper = Objects.requireNonNull(objectMapper); this.editingContextEventProcessorRegistry = Objects.requireNonNull(editingContextEventProcessorRegistry); } @@ -49,9 +56,12 @@ public CompletableFuture get(DataFetchingEnvironment environment) throws Map localContext = environment.getLocalContext(); var editingContextId = Optional.of(localContext.get(LocalContextConstants.EDITING_CONTEXT_ID)).map(Object::toString); - String targetObjectId = environment.getArgument(TARGET_OBJECT_ID); + List variablesObject = environment.getArgument(VARIABLES); + List variables = variablesObject.stream() + .map(object -> this.objectMapper.convertValue(object, SelectionDialogVariable.class)) + .toList(); - var input = new GetSelectionDescriptionMessageInput(UUID.randomUUID(), targetObjectId, selectionDescription); + var input = new GetSelectionDescriptionMessageInput(UUID.randomUUID(), variables, selectionDescription); return this.editingContextEventProcessorRegistry.dispatchEvent(editingContextId.get(), input) .filter(GetSelectionDescriptionMessagePayload.class::isInstance) .map(GetSelectionDescriptionMessagePayload.class::cast) diff --git a/packages/selection/frontend/sirius-components-selection/src/SelectionDialog.tsx b/packages/selection/frontend/sirius-components-selection/src/SelectionDialog.tsx index a1a99aa53a..ed3b184596 100644 --- a/packages/selection/frontend/sirius-components-selection/src/SelectionDialog.tsx +++ b/packages/selection/frontend/sirius-components-selection/src/SelectionDialog.tsx @@ -28,7 +28,7 @@ export const SELECTION_DIALOG_TYPE: string = 'selectionDialogDescription'; export const SelectionDialog = ({ editingContextId, dialogDescriptionId, - targetObjectId, + variables, onClose, onFinish, }: DiagramDialogComponentProps) => { @@ -39,7 +39,7 @@ export const SelectionDialog = ({ const { selectionDescription } = useSelectionDescription({ editingContextId, selectionDescriptionId: dialogDescriptionId, - targetObjectId, + variables, }); const message: string = selectionDescription?.message ?? ''; @@ -61,7 +61,7 @@ export const SelectionDialog = ({ content = ( ); diff --git a/packages/selection/frontend/sirius-components-selection/src/SelectionDialogTreeView.tsx b/packages/selection/frontend/sirius-components-selection/src/SelectionDialogTreeView.tsx index e99f773a9a..8e2b96db8b 100644 --- a/packages/selection/frontend/sirius-components-selection/src/SelectionDialogTreeView.tsx +++ b/packages/selection/frontend/sirius-components-selection/src/SelectionDialogTreeView.tsx @@ -10,6 +10,7 @@ * Contributors: * Obeo - initial API and implementation *******************************************************************************/ +import { DiagramDialogVariable } from '@eclipse-sirius/sirius-components-diagrams'; import { TreeItemActionProps, TreeView } from '@eclipse-sirius/sirius-components-trees'; import UnfoldMoreIcon from '@mui/icons-material/UnfoldMore'; import IconButton from '@mui/material/IconButton'; @@ -37,15 +38,12 @@ const initialState: SelectionDialogTreeViewState = { export const SelectionDialogTreeView = ({ editingContextId, treeDescriptionId, - targetObjectId, + variables, }: SelectionDialogTreeViewProps) => { const { classes } = useTreeStyle(); const [state, setState] = useState(initialState); - const treeId = `selection://?treeDescriptionId=${encodeURIComponent( - treeDescriptionId - )}&targetObjectId=${encodeURIComponent(targetObjectId)}`; - + const treeId = `selection://?treeDescriptionId=${encodeURIComponent(treeDescriptionId)}${encodeVariables(variables)}`; const { tree } = useSelectionDialogTreeSubscription(editingContextId, treeId, state.expanded, state.maxDepth); const onExpandedElementChange = (expanded: string[], maxDepth: number) => { @@ -90,3 +88,12 @@ const SelectionDialogTreeItemAction = ({ onExpandAll, item, isHovered }: TreeIte ); }; + +const encodeVariables = (variables: DiagramDialogVariable[]): string => { + let encodedVariables = ''; + if (variables.length > 0) { + encodedVariables = + '&' + variables.map((variable) => variable.name + '=' + encodeURIComponent(variable.value)).join('&'); + } + return encodedVariables; +}; diff --git a/packages/selection/frontend/sirius-components-selection/src/SelectionDialogTreeView.types.ts b/packages/selection/frontend/sirius-components-selection/src/SelectionDialogTreeView.types.ts index aba103cf1b..48f265e865 100644 --- a/packages/selection/frontend/sirius-components-selection/src/SelectionDialogTreeView.types.ts +++ b/packages/selection/frontend/sirius-components-selection/src/SelectionDialogTreeView.types.ts @@ -10,11 +10,11 @@ * Contributors: * Obeo - initial API and implementation *******************************************************************************/ - +import { DiagramDialogVariable } from '@eclipse-sirius/sirius-components-diagrams'; export interface SelectionDialogTreeViewProps { editingContextId: string; treeDescriptionId: string; - targetObjectId: string; + variables: DiagramDialogVariable[]; } export interface SelectionDialogTreeViewState { diff --git a/packages/selection/frontend/sirius-components-selection/src/useSelectionDescription.ts b/packages/selection/frontend/sirius-components-selection/src/useSelectionDescription.ts index e3fa0a578c..528562939f 100644 --- a/packages/selection/frontend/sirius-components-selection/src/useSelectionDescription.ts +++ b/packages/selection/frontend/sirius-components-selection/src/useSelectionDescription.ts @@ -21,13 +21,17 @@ import { UseSelectionDescriptionValue, } from './useSelectionDescription.types'; const getSelectionDescription = gql` - query getSelectionDescription($editingContextId: ID!, $representationId: ID!, $targetObjectId: ID!) { + query getSelectionDescription( + $editingContextId: ID! + $representationId: ID! + $variables: [SelectionDialogVariable!]! + ) { viewer { editingContext(editingContextId: $editingContextId) { representation(representationId: $representationId) { description { ... on SelectionDescription { - message(targetObjectId: $targetObjectId) + message(variables: $variables) treeDescription { id } @@ -42,7 +46,7 @@ const getSelectionDescription = gql` export const useSelectionDescription = ({ editingContextId, selectionDescriptionId, - targetObjectId, + variables, }: UseSelectionDescriptionProps): UseSelectionDescriptionValue => { //Since the SelectionDialogRepresentation does not really exist, the representationId just contains the description id const representationId = `selectionDialog://?representationDescription=${encodeURIComponent(selectionDescriptionId)}`; @@ -52,7 +56,7 @@ export const useSelectionDescription = ({ variables: { editingContextId, representationId, - targetObjectId, + variables, }, } ); diff --git a/packages/selection/frontend/sirius-components-selection/src/useSelectionDescription.types.ts b/packages/selection/frontend/sirius-components-selection/src/useSelectionDescription.types.ts index 2889d150d8..a3aadc822d 100644 --- a/packages/selection/frontend/sirius-components-selection/src/useSelectionDescription.types.ts +++ b/packages/selection/frontend/sirius-components-selection/src/useSelectionDescription.types.ts @@ -11,10 +11,12 @@ * Obeo - initial API and implementation *******************************************************************************/ +import { DiagramDialogVariable } from '@eclipse-sirius/sirius-components-diagrams'; + export interface UseSelectionDescriptionProps { editingContextId: string; selectionDescriptionId: string; - targetObjectId: string; + variables: DiagramDialogVariable[]; } export interface UseSelectionDescriptionValue { @@ -25,7 +27,7 @@ export interface UseSelectionDescriptionValue { export interface GetSelectionDescriptionVariables { editingContextId: string; representationId: string; - targetObjectId: string; + variables: DiagramDialogVariable[]; } export interface GQLSelectionDescription { diff --git a/packages/sirius-web/backend/sirius-web/src/test/java/org/eclipse/sirius/web/application/controllers/diagrams/EdgeControllerTests.java b/packages/sirius-web/backend/sirius-web/src/test/java/org/eclipse/sirius/web/application/controllers/diagrams/EdgeControllerTests.java index b34c65502e..c616b28d8d 100644 --- a/packages/sirius-web/backend/sirius-web/src/test/java/org/eclipse/sirius/web/application/controllers/diagrams/EdgeControllerTests.java +++ b/packages/sirius-web/backend/sirius-web/src/test/java/org/eclipse/sirius/web/application/controllers/diagrams/EdgeControllerTests.java @@ -185,7 +185,8 @@ public void givenDiagramWithSomeNodesWhenTheCreationOfAnEdgeIsRequestedThenTheEd 0, 0, 0, - this.edgeDiagramDescriptionProvider.getNewDependencyToolId() + this.edgeDiagramDescriptionProvider.getNewDependencyToolId(), + List.of() ); var result = this.invokeSingleClickOnTwoDiagramElementsToolMutationRunner.run(input); String payloadTypeName = JsonPath.read(result, "$.data.invokeSingleClickOnTwoDiagramElementsTool.__typename"); diff --git a/packages/sirius-web/backend/sirius-web/src/test/java/org/eclipse/sirius/web/application/controllers/selection/SelectionControllerIntegrationTests.java b/packages/sirius-web/backend/sirius-web/src/test/java/org/eclipse/sirius/web/application/controllers/selection/SelectionControllerIntegrationTests.java index 73321a0e62..f5e04f9bcd 100644 --- a/packages/sirius-web/backend/sirius-web/src/test/java/org/eclipse/sirius/web/application/controllers/selection/SelectionControllerIntegrationTests.java +++ b/packages/sirius-web/backend/sirius-web/src/test/java/org/eclipse/sirius/web/application/controllers/selection/SelectionControllerIntegrationTests.java @@ -15,6 +15,8 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.fail; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; import com.jayway.jsonpath.JsonPath; import java.net.URLEncoder; @@ -29,6 +31,7 @@ import java.util.function.Predicate; import org.eclipse.sirius.components.collaborative.selection.dto.SelectionDialogTreeEventInput; +import org.eclipse.sirius.components.collaborative.selection.dto.SelectionDialogVariable; import org.eclipse.sirius.components.collaborative.trees.dto.TreeRefreshedEventPayload; import org.eclipse.sirius.components.graphql.api.URLConstants; import org.eclipse.sirius.components.graphql.tests.api.IGraphQLRequestor; @@ -37,9 +40,9 @@ import org.eclipse.sirius.components.trees.tests.graphql.ExpandAllTreePathQueryRunner; import org.eclipse.sirius.web.AbstractIntegrationTests; import org.eclipse.sirius.web.data.PapayaIdentifiers; -import org.eclipse.sirius.web.tests.services.representation.RepresentationIdBuilder; import org.eclipse.sirius.web.services.selection.SelectionDescriptionProvider; import org.eclipse.sirius.web.tests.services.api.IGivenInitialServerState; +import org.eclipse.sirius.web.tests.services.representation.RepresentationIdBuilder; import org.eclipse.sirius.web.tests.services.selection.SelectionDialogTreeEventSubscriptionRunner; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; @@ -64,13 +67,13 @@ public class SelectionControllerIntegrationTests extends AbstractIntegrationTests { private static final String GET_SELECTION_DESCRIPTION = """ - query getSelectionDescription($editingContextId: ID!, $representationId: ID!, $targetObjectId: ID!) { + query getSelectionDescription($editingContextId: ID!, $representationId: ID!, $variables: [SelectionDialogVariable!]!) { viewer { editingContext(editingContextId: $editingContextId) { representation(representationId: $representationId) { description { ... on SelectionDescription { - message(targetObjectId: $targetObjectId) + message(variables: $variables) treeDescription { id } @@ -118,6 +121,9 @@ subscription selectionDialogTreeEvent($input: SelectionDialogTreeEventInput!) { @Autowired private RepresentationIdBuilder representationIdBuilder; + @Autowired + private ObjectMapper objectMapper; + @BeforeEach public void beforeEach() { this.givenInitialServerState.initialize(); @@ -129,8 +135,10 @@ public void beforeEach() { @Sql(scripts = { "/scripts/cleanup.sql" }, executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD, config = @SqlConfig(transactionMode = SqlConfig.TransactionMode.ISOLATED)) public void givenSemanticObjectWhenRequestingSelectionDescriptionThenTheSelectionDescriptionIsSent() { String representationId = "selectionDialog://?representationDescription=" + URLEncoder.encode(this.selectionDescriptionProvider.getSelectionDialogDescriptionId(), StandardCharsets.UTF_8); - Map variables = Map.of("editingContextId", PapayaIdentifiers.PAPAYA_PROJECT.toString(), "representationId", representationId, "targetObjectId", - PapayaIdentifiers.PROJECT_OBJECT.toString()); + List selectionDialogVariables = List.of(new SelectionDialogVariable("targetObjectId", PapayaIdentifiers.PROJECT_OBJECT.toString()), + new SelectionDialogVariable("sourceDiagramElementTargetObjectId", PapayaIdentifiers.FIRST_TASK_OBJECT.toString())); + List> variablesParameter = this.objectMapper.convertValue(selectionDialogVariables, new TypeReference>>() { }); + Map variables = Map.of("editingContextId", PapayaIdentifiers.PAPAYA_PROJECT.toString(), "representationId", representationId, "variables", variablesParameter); var result = this.graphQLRequestor.execute(GET_SELECTION_DESCRIPTION, variables); String message = JsonPath.read(result, "$.data.viewer.editingContext.representation.description.message"); String treeDescriptionId = JsonPath.read(result, "$.data.viewer.editingContext.representation.description.treeDescription.id"); @@ -144,7 +152,7 @@ public void givenSemanticObjectWhenRequestingSelectionDescriptionThenTheSelectio @Sql(scripts = {"/scripts/papaya.sql"}, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) @Sql(scripts = {"/scripts/cleanup.sql"}, executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD, config = @SqlConfig(transactionMode = SqlConfig.TransactionMode.ISOLATED)) public void givenSemanticObjectWhenWeSubscribeToItsSelectionEventsThenTheSelectionIsSent() { - var representationId = representationIdBuilder.buildSelectionRepresentationId(this.selectionDescriptionProvider.getSelectionDialogTreeDescriptionId(), PapayaIdentifiers.PROJECT_OBJECT.toString(), List.of()); + var representationId = this.representationIdBuilder.buildSelectionRepresentationId(this.selectionDescriptionProvider.getSelectionDialogTreeDescriptionId(), PapayaIdentifiers.PROJECT_OBJECT.toString(), List.of()); var input = new SelectionDialogTreeEventInput(UUID.randomUUID(), PapayaIdentifiers.PAPAYA_PROJECT.toString(), representationId); var flux = this.selectionDialogTreeEventSubscriptionRunner.run(input); var hasResourceRootContent = this.getTreeRefreshedEventPayloadMatcher(); @@ -159,7 +167,7 @@ public void givenSemanticObjectWhenWeSubscribeToItsSelectionEventsThenTheSelecti @Sql(scripts = {"/scripts/papaya.sql"}, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) @Sql(scripts = {"/scripts/cleanup.sql"}, executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD, config = @SqlConfig(transactionMode = SqlConfig.TransactionMode.ISOLATED)) public void givenSelectionDialogTreeWhenWeExpandTheFirstItemThenChildrenAreSent() { - var representationId = representationIdBuilder.buildSelectionRepresentationId(this.selectionDescriptionProvider.getSelectionDialogTreeDescriptionId(), PapayaIdentifiers.PROJECT_OBJECT.toString(), List.of()); + var representationId = this.representationIdBuilder.buildSelectionRepresentationId(this.selectionDescriptionProvider.getSelectionDialogTreeDescriptionId(), PapayaIdentifiers.PROJECT_OBJECT.toString(), List.of()); var input = new SelectionDialogTreeEventInput(UUID.randomUUID(), PapayaIdentifiers.PAPAYA_PROJECT.toString(), representationId); var flux = this.selectionDialogTreeEventSubscriptionRunner.run(input); @@ -178,7 +186,7 @@ public void givenSelectionDialogTreeWhenWeExpandTheFirstItemThenChildrenAreSent( .thenCancel() .verify(); - var representationIdExpanded = representationIdBuilder.buildSelectionRepresentationId(this.selectionDescriptionProvider.getSelectionDialogTreeDescriptionId(), PapayaIdentifiers.PROJECT_OBJECT.toString(), List.of(treeItemId.get())); + var representationIdExpanded = this.representationIdBuilder.buildSelectionRepresentationId(this.selectionDescriptionProvider.getSelectionDialogTreeDescriptionId(), PapayaIdentifiers.PROJECT_OBJECT.toString(), List.of(treeItemId.get())); var expandedTreeInput = new SelectionDialogTreeEventInput(UUID.randomUUID(), PapayaIdentifiers.PAPAYA_PROJECT.toString(), representationIdExpanded); var expandedTreeFlux = this.selectionDialogTreeEventSubscriptionRunner.run(expandedTreeInput); var treeRefreshedEventPayloadExpandMatcher = this.getTreeRefreshedEventPayloadExpandMatcher(); @@ -194,7 +202,7 @@ public void givenSelectionDialogTreeWhenWeExpandTheFirstItemThenChildrenAreSent( @Sql(scripts = {"/scripts/papaya.sql"}, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) @Sql(scripts = {"/scripts/cleanup.sql"}, executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD, config = @SqlConfig(transactionMode = SqlConfig.TransactionMode.ISOLATED)) public void givenSelectionDialogTreeWhenWePerformExpandAllOnTheFirstItemThenChildrenAreSent() { - var representationId = representationIdBuilder.buildSelectionRepresentationId(this.selectionDescriptionProvider.getSelectionDialogTreeDescriptionId(), PapayaIdentifiers.PROJECT_OBJECT.toString(), List.of()); + var representationId = this.representationIdBuilder.buildSelectionRepresentationId(this.selectionDescriptionProvider.getSelectionDialogTreeDescriptionId(), PapayaIdentifiers.PROJECT_OBJECT.toString(), List.of()); var input = new SelectionDialogTreeEventInput(UUID.randomUUID(), PapayaIdentifiers.PAPAYA_PROJECT.toString(), representationId); var flux = this.selectionDialogTreeEventSubscriptionRunner.run(input); @@ -237,7 +245,7 @@ public void givenSelectionDialogTreeWhenWePerformExpandAllOnTheFirstItemThenChil }); - var representationIdExpanded = representationIdBuilder.buildSelectionRepresentationId(this.selectionDescriptionProvider.getSelectionDialogTreeDescriptionId(), PapayaIdentifiers.PROJECT_OBJECT.toString(), treeItemIds.get()); + var representationIdExpanded = this.representationIdBuilder.buildSelectionRepresentationId(this.selectionDescriptionProvider.getSelectionDialogTreeDescriptionId(), PapayaIdentifiers.PROJECT_OBJECT.toString(), treeItemIds.get()); var expandedTreeInput = new SelectionDialogTreeEventInput(UUID.randomUUID(), PapayaIdentifiers.PAPAYA_PROJECT.toString(), representationIdExpanded); var expandedTreeFlux = this.selectionDialogTreeEventSubscriptionRunner.run(expandedTreeInput); @@ -252,7 +260,7 @@ public void givenSelectionDialogTreeWhenWePerformExpandAllOnTheFirstItemThenChil @Sql(scripts = {"/scripts/papaya.sql"}, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) @Sql(scripts = {"/scripts/cleanup.sql"}, executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD, config = @SqlConfig(transactionMode = SqlConfig.TransactionMode.ISOLATED)) public void givenSelectionDialogTreeWhenWePerformExpandAllOnTheSecondItemThenChildrenAreSent() { - var representationId = representationIdBuilder.buildSelectionRepresentationId(this.selectionDescriptionProvider.getSelectionDialogTreeDescriptionId(), PapayaIdentifiers.PROJECT_OBJECT.toString(), List.of()); + var representationId = this.representationIdBuilder.buildSelectionRepresentationId(this.selectionDescriptionProvider.getSelectionDialogTreeDescriptionId(), PapayaIdentifiers.PROJECT_OBJECT.toString(), List.of()); var input = new SelectionDialogTreeEventInput(UUID.randomUUID(), PapayaIdentifiers.PAPAYA_PROJECT.toString(), representationId); var flux = this.selectionDialogTreeEventSubscriptionRunner.run(input); @@ -273,7 +281,7 @@ public void givenSelectionDialogTreeWhenWePerformExpandAllOnTheSecondItemThenChi .verify(Duration.ofSeconds(10)); //We expand the first tree item (representing the resource) - var representationIdExpandedFirstTreeItem = representationIdBuilder.buildSelectionRepresentationId(this.selectionDescriptionProvider.getSelectionDialogTreeDescriptionId(), PapayaIdentifiers.PROJECT_OBJECT.toString(), List.of(rootTreeItemId.get())); + var representationIdExpandedFirstTreeItem = this.representationIdBuilder.buildSelectionRepresentationId(this.selectionDescriptionProvider.getSelectionDialogTreeDescriptionId(), PapayaIdentifiers.PROJECT_OBJECT.toString(), List.of(rootTreeItemId.get())); var expandedFirstTreeItemInput = new SelectionDialogTreeEventInput(UUID.randomUUID(), PapayaIdentifiers.PAPAYA_PROJECT.toString(), representationIdExpandedFirstTreeItem); var expandedFirstTreeItemFlux = this.selectionDialogTreeEventSubscriptionRunner.run(expandedFirstTreeItemInput); @@ -317,7 +325,7 @@ public void givenSelectionDialogTreeWhenWePerformExpandAllOnTheSecondItemThenChi assertThat(rootProjectTreeItem.getChildren()).isNotEmpty(); }); - var representationIdExpanded = representationIdBuilder.buildSelectionRepresentationId(this.selectionDescriptionProvider.getSelectionDialogTreeDescriptionId(), PapayaIdentifiers.PROJECT_OBJECT.toString(), treeItemIds.get()); + var representationIdExpanded = this.representationIdBuilder.buildSelectionRepresentationId(this.selectionDescriptionProvider.getSelectionDialogTreeDescriptionId(), PapayaIdentifiers.PROJECT_OBJECT.toString(), treeItemIds.get()); var expandedTreeInput = new SelectionDialogTreeEventInput(UUID.randomUUID(), PapayaIdentifiers.PAPAYA_PROJECT.toString(), representationIdExpanded); var expandedTreeFlux = this.selectionDialogTreeEventSubscriptionRunner.run(expandedTreeInput); // We now verify the expandAll result @@ -363,7 +371,7 @@ private Predicate getTreeRefreshedEventPayloadExpandMatcher() { @Sql(scripts = {"/scripts/papaya.sql"}, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) @Sql(scripts = {"/scripts/cleanup.sql"}, executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD, config = @SqlConfig(transactionMode = SqlConfig.TransactionMode.ISOLATED)) public void givenSemanticObjectWhenWeSubscribeToItsSelectionEventsThenTheURLOfItsObjectsIsValid() { - var representationId = representationIdBuilder.buildSelectionRepresentationId(this.selectionDescriptionProvider.getSelectionDialogTreeDescriptionId(), PapayaIdentifiers.PROJECT_OBJECT.toString(), List.of()); + var representationId = this.representationIdBuilder.buildSelectionRepresentationId(this.selectionDescriptionProvider.getSelectionDialogTreeDescriptionId(), PapayaIdentifiers.PROJECT_OBJECT.toString(), List.of()); var input = new SelectionDialogTreeEventInput(UUID.randomUUID(), PapayaIdentifiers.PAPAYA_PROJECT.toString(), representationId); var flux = this.graphQLRequestor.subscribeToSpecification(GET_TREE_EVENT_SUBSCRIPTION, input); diff --git a/packages/sirius-web/backend/sirius-web/src/test/java/org/eclipse/sirius/web/services/selection/SelectionDescriptionProvider.java b/packages/sirius-web/backend/sirius-web/src/test/java/org/eclipse/sirius/web/services/selection/SelectionDescriptionProvider.java index 9a8be5f677..0f5103087a 100644 --- a/packages/sirius-web/backend/sirius-web/src/test/java/org/eclipse/sirius/web/services/selection/SelectionDescriptionProvider.java +++ b/packages/sirius-web/backend/sirius-web/src/test/java/org/eclipse/sirius/web/services/selection/SelectionDescriptionProvider.java @@ -25,8 +25,10 @@ import org.eclipse.sirius.components.view.builder.generated.SelectionDialogTreeDescriptionBuilder; import org.eclipse.sirius.components.view.builder.generated.diagram.DiagramDescriptionBuilder; import org.eclipse.sirius.components.view.builder.generated.diagram.DiagramPaletteBuilder; +import org.eclipse.sirius.components.view.builder.generated.diagram.EdgeToolBuilder; import org.eclipse.sirius.components.view.builder.generated.diagram.InsideLabelDescriptionBuilder; import org.eclipse.sirius.components.view.builder.generated.diagram.NodeDescriptionBuilder; +import org.eclipse.sirius.components.view.builder.generated.diagram.NodePaletteBuilder; import org.eclipse.sirius.components.view.builder.generated.diagram.NodeToolBuilder; import org.eclipse.sirius.components.view.builder.generated.diagram.RectangularNodeStyleDescriptionBuilder; import org.eclipse.sirius.components.view.builder.generated.diagram.SelectionDialogDescriptionBuilder; @@ -34,6 +36,7 @@ import org.eclipse.sirius.components.view.builder.generated.view.ViewBuilder; import org.eclipse.sirius.components.view.diagram.DiagramDescription; import org.eclipse.sirius.components.view.diagram.DiagramFactory; +import org.eclipse.sirius.components.view.diagram.EdgeTool; import org.eclipse.sirius.components.view.diagram.InsideLabelPosition; import org.eclipse.sirius.components.view.diagram.NodeTool; import org.eclipse.sirius.components.view.diagram.SelectionDialogDescription; @@ -68,6 +71,8 @@ public class SelectionDescriptionProvider implements IEditingContextProcessor { private SelectionDialogDescription selectionDialog; + private EdgeTool edgeTool; + public SelectionDescriptionProvider(IDiagramIdProvider diagramIdProvider) { this.diagramIdProvider = Objects.requireNonNull(diagramIdProvider); @@ -116,6 +121,12 @@ private DiagramDescription createDiagramDescription() { .position(InsideLabelPosition.TOP_CENTER) .build(); + this.createEdgeTool(); + + var nodePalette = new NodePaletteBuilder() + .edgeTools(this.edgeTool) + .build(); + var nodeDescription = new NodeDescriptionBuilder() .name("Component") .domainType("papaya:Component") @@ -123,9 +134,11 @@ private DiagramDescription createDiagramDescription() { .insideLabel(insideLabel) .synchronizationPolicy(SynchronizationPolicy.SYNCHRONIZED) .style(nodeStyle) + .palette(nodePalette) .build(); - this.createCreateNodeTool(); + this.createNodeTool(); + var diagramPalette = new DiagramPaletteBuilder() .nodeTools(this.createNodeTool) @@ -144,7 +157,7 @@ private DiagramDescription createDiagramDescription() { return this.diagramDescription; } - private void createCreateNodeTool() { + private void createNodeTool() { this.selectionDialog = this.createSelectionDialog(); this.createNodeTool = new NodeToolBuilder() .name("Create Component") @@ -157,6 +170,19 @@ private void createCreateNodeTool() { .build(); } + private void createEdgeTool() { + var edgeSelectionDialog = this.createEdgeSelectionDialog(); + this.edgeTool = new EdgeToolBuilder() + .name("Create relation") + .body( + new ChangeContextBuilder() + .expression("aql:self") + .build() + ) + .dialogDescription(edgeSelectionDialog) + .build(); + } + private SelectionDialogDescription createSelectionDialog() { this.selectionDialogTreeDescription = new SelectionDialogTreeDescriptionBuilder() .elementsExpression("aql:self.eResource()") @@ -169,4 +195,17 @@ private SelectionDialogDescription createSelectionDialog() { .build(); } + + private SelectionDialogDescription createEdgeSelectionDialog() { + var edgeSelectionDialogTreeDescription = new SelectionDialogTreeDescriptionBuilder() + .elementsExpression("aql:self.eResource()") + .childrenExpression("aql:if self.oclIsKindOf(papaya::NamedElement) then self.eContents() else self.getContents() endif ") + .isSelectableExpression("aql:self.oclIsKindOf(papaya::Component)") + .build(); + return new SelectionDialogDescriptionBuilder() + .selectionMessage(DIALOG_MESSAGE) + .selectionDialogTreeDescription(edgeSelectionDialogTreeDescription) + .build(); + + } } diff --git a/packages/view/backend/sirius-components-view-builder/src/main/java/org/eclipse/sirius/components/view/builder/generated/diagram/EdgeToolBuilder.java b/packages/view/backend/sirius-components-view-builder/src/main/java/org/eclipse/sirius/components/view/builder/generated/diagram/EdgeToolBuilder.java index 896af5c42e..2720216992 100644 --- a/packages/view/backend/sirius-components-view-builder/src/main/java/org/eclipse/sirius/components/view/builder/generated/diagram/EdgeToolBuilder.java +++ b/packages/view/backend/sirius-components-view-builder/src/main/java/org/eclipse/sirius/components/view/builder/generated/diagram/EdgeToolBuilder.java @@ -94,5 +94,15 @@ public EdgeToolBuilder iconURLsExpression(java.lang.String value) { return this; } + /** + * Setter for DialogDescription. + * + * @generated + */ + public EdgeToolBuilder dialogDescription(org.eclipse.sirius.components.view.diagram.DialogDescription value) { + this.getEdgeTool().setDialogDescription(value); + return this; + } + } diff --git a/packages/view/backend/sirius-components-view-diagram-edit/src/main/java/org/eclipse/sirius/components/view/diagram/provider/EdgeToolItemProvider.java b/packages/view/backend/sirius-components-view-diagram-edit/src/main/java/org/eclipse/sirius/components/view/diagram/provider/EdgeToolItemProvider.java index 677cd2d662..63e57de406 100644 --- a/packages/view/backend/sirius-components-view-diagram-edit/src/main/java/org/eclipse/sirius/components/view/diagram/provider/EdgeToolItemProvider.java +++ b/packages/view/backend/sirius-components-view-diagram-edit/src/main/java/org/eclipse/sirius/components/view/diagram/provider/EdgeToolItemProvider.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2021, 2023 Obeo. + * Copyright (c) 2021, 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 @@ -17,12 +17,16 @@ import org.eclipse.emf.common.notify.AdapterFactory; import org.eclipse.emf.common.notify.Notification; +import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.emf.edit.provider.ComposeableAdapterFactory; import org.eclipse.emf.edit.provider.IItemPropertyDescriptor; import org.eclipse.emf.edit.provider.ItemPropertyDescriptor; import org.eclipse.emf.edit.provider.ViewerNotification; +import org.eclipse.sirius.components.view.diagram.DiagramFactory; import org.eclipse.sirius.components.view.diagram.DiagramPackage; import org.eclipse.sirius.components.view.diagram.EdgeTool; +import org.eclipse.sirius.components.view.diagram.SelectionDialogDescription; +import org.eclipse.sirius.components.view.diagram.SelectionDialogTreeDescription; /** * This is the item provider adapter for a {@link org.eclipse.sirius.components.view.diagram.EdgeTool} object. + * + * @generated + */ + @Override + public Collection getChildrenFeatures(Object object) { + if (this.childrenFeatures == null) { + super.getChildrenFeatures(object); + this.childrenFeatures.add(DiagramPackage.Literals.EDGE_TOOL__DIALOG_DESCRIPTION); + } + return this.childrenFeatures; + } + + /** + * + * + * @generated + */ + @Override + protected EStructuralFeature getChildFeature(Object object, Object child) { + // Check the type of the specified child object and return the proper feature to use for + // adding (see {@link AddCommand}) it as a child. + + return super.getChildFeature(object, child); + } + /** * This returns EdgeTool.gif. * @@ -127,6 +161,9 @@ public void notifyChanged(Notification notification) { case DiagramPackage.EDGE_TOOL__ICON_UR_LS_EXPRESSION: this.fireNotifyChanged(new ViewerNotification(notification, notification.getNotifier(), false, true)); return; + case DiagramPackage.EDGE_TOOL__DIALOG_DESCRIPTION: + this.fireNotifyChanged(new ViewerNotification(notification, notification.getNotifier(), true, false)); + return; } super.notifyChanged(notification); } @@ -135,11 +172,15 @@ public void notifyChanged(Notification notification) { * This adds {@link org.eclipse.emf.edit.command.CommandParameter}s describing the children that can be created * under this object. * - * @generated + * @generated NOT */ @Override protected void collectNewChildDescriptors(Collection newChildDescriptors, Object object) { super.collectNewChildDescriptors(newChildDescriptors, object); + SelectionDialogDescription selectionDialogDescription = DiagramFactory.eINSTANCE.createSelectionDialogDescription(); + SelectionDialogTreeDescription selectionDialogTreeDescription = DiagramFactory.eINSTANCE.createSelectionDialogTreeDescription(); + selectionDialogDescription.setSelectionDialogTreeDescription(selectionDialogTreeDescription); + newChildDescriptors.add(this.createChildParameter(DiagramPackage.Literals.EDGE_TOOL__DIALOG_DESCRIPTION, selectionDialogDescription)); } } diff --git a/packages/view/backend/sirius-components-view-diagram-edit/src/main/resources/plugin.properties b/packages/view/backend/sirius-components-view-diagram-edit/src/main/resources/plugin.properties index 6afa2a3173..a2eacaad99 100644 --- a/packages/view/backend/sirius-components-view-diagram-edit/src/main/resources/plugin.properties +++ b/packages/view/backend/sirius-components-view-diagram-edit/src/main/resources/plugin.properties @@ -175,6 +175,7 @@ _UI_EdgeTool_iconURLsExpression_feature=Icon URLs Expression _UI_LabelEditTool_initialDirectEditLabelExpression_feature=Initial Direct Edit Label Expression _UI_NodeTool_dialogDescription_feature=Dialog Description _UI_NodeTool_iconURLsExpression_feature=Icon URLs Expression +_UI_EdgeTool_dialogDescription_feature = Dialog Description _UI_CreateView_parentViewExpression_feature=Parent View Expression _UI_CreateView_elementDescription_feature=Element Description _UI_CreateView_semanticElementExpression_feature=Semantic Element Expression diff --git a/packages/view/backend/sirius-components-view-diagram/src/main/java/org/eclipse/sirius/components/view/diagram/DiagramPackage.java b/packages/view/backend/sirius-components-view-diagram/src/main/java/org/eclipse/sirius/components/view/diagram/DiagramPackage.java index feb2377711..5d4e043d1e 100644 --- a/packages/view/backend/sirius-components-view-diagram/src/main/java/org/eclipse/sirius/components/view/diagram/DiagramPackage.java +++ b/packages/view/backend/sirius-components-view-diagram/src/main/java/org/eclipse/sirius/components/view/diagram/DiagramPackage.java @@ -2683,6 +2683,15 @@ public interface DiagramPackage extends EPackage { */ int EDGE_TOOL__ICON_UR_LS_EXPRESSION = TOOL_FEATURE_COUNT + 1; + /** + * The feature id for the 'Dialog Description' containment reference. + * + * @generated + * @ordered + */ + int EDGE_TOOL__DIALOG_DESCRIPTION = TOOL_FEATURE_COUNT + 2; + /** * The number of structural features of the 'Edge Tool' class. @@ -2690,7 +2699,7 @@ public interface DiagramPackage extends EPackage { * @generated * @ordered */ - int EDGE_TOOL_FEATURE_COUNT = TOOL_FEATURE_COUNT + 2; + int EDGE_TOOL_FEATURE_COUNT = TOOL_FEATURE_COUNT + 3; /** * The number of operations of the 'Edge Tool' class. @@ -5081,6 +5090,18 @@ public interface DiagramPackage extends EPackage { */ EAttribute getEdgeTool_IconURLsExpression(); + /** + * Returns the meta object for the containment reference + * '{@link org.eclipse.sirius.components.view.diagram.EdgeTool#getDialogDescription Dialog Description}'. + * + * + * @return the meta object for the containment reference 'Dialog Description'. + * @see org.eclipse.sirius.components.view.diagram.EdgeTool#getDialogDescription() + * @see #getEdgeTool() + * @generated + */ + EReference getEdgeTool_DialogDescription(); + /** * Returns the meta object for class '{@link org.eclipse.sirius.components.view.diagram.EdgeReconnectionTool * Edge Reconnection Tool}'. @@ -6747,6 +6768,14 @@ interface Literals { */ EAttribute EDGE_TOOL__ICON_UR_LS_EXPRESSION = eINSTANCE.getEdgeTool_IconURLsExpression(); + /** + * The meta object literal for the 'Dialog Description' containment reference feature. + * + * @generated + */ + EReference EDGE_TOOL__DIALOG_DESCRIPTION = eINSTANCE.getEdgeTool_DialogDescription(); + /** * The meta object literal for the * '{@link org.eclipse.sirius.components.view.diagram.impl.EdgeReconnectionToolImpl Edge Reconnection diff --git a/packages/view/backend/sirius-components-view-diagram/src/main/java/org/eclipse/sirius/components/view/diagram/EdgeTool.java b/packages/view/backend/sirius-components-view-diagram/src/main/java/org/eclipse/sirius/components/view/diagram/EdgeTool.java index cf9c22207b..882ec12348 100644 --- a/packages/view/backend/sirius-components-view-diagram/src/main/java/org/eclipse/sirius/components/view/diagram/EdgeTool.java +++ b/packages/view/backend/sirius-components-view-diagram/src/main/java/org/eclipse/sirius/components/view/diagram/EdgeTool.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 @@ -25,6 +25,7 @@ * Descriptions} *
  • {@link org.eclipse.sirius.components.view.diagram.EdgeTool#getIconURLsExpression Icon UR Ls * Expression}
  • + *
  • {@link org.eclipse.sirius.components.view.diagram.EdgeTool#getDialogDescription Dialog Description}
  • * * * @see org.eclipse.sirius.components.view.diagram.DiagramPackage#getEdgeTool() @@ -67,4 +68,27 @@ public interface EdgeTool extends Tool { */ void setIconURLsExpression(String value); + /** + * Returns the value of the 'Dialog Description' containment reference. + * + * @return the value of the 'Dialog Description' containment reference. + * @see #setDialogDescription(DialogDescription) + * @see org.eclipse.sirius.components.view.diagram.DiagramPackage#getEdgeTool_DialogDescription() + * @model containment="true" + * @generated + */ + DialogDescription getDialogDescription(); + + /** + * Sets the value of the '{@link org.eclipse.sirius.components.view.diagram.EdgeTool#getDialogDescription Dialog + * Description}' containment reference. + * + * @param value + * the new value of the 'Dialog Description' containment reference. + * @see #getDialogDescription() + * @generated + */ + void setDialogDescription(DialogDescription value); + } // EdgeTool diff --git a/packages/view/backend/sirius-components-view-diagram/src/main/java/org/eclipse/sirius/components/view/diagram/impl/DiagramPackageImpl.java b/packages/view/backend/sirius-components-view-diagram/src/main/java/org/eclipse/sirius/components/view/diagram/impl/DiagramPackageImpl.java index 3b38b61989..f3894d3f07 100644 --- a/packages/view/backend/sirius-components-view-diagram/src/main/java/org/eclipse/sirius/components/view/diagram/impl/DiagramPackageImpl.java +++ b/packages/view/backend/sirius-components-view-diagram/src/main/java/org/eclipse/sirius/components/view/diagram/impl/DiagramPackageImpl.java @@ -1891,6 +1891,16 @@ public EAttribute getEdgeTool_IconURLsExpression() { return (EAttribute) this.edgeToolEClass.getEStructuralFeatures().get(1); } + /** + * + * + * @generated + */ + @Override + public EReference getEdgeTool_DialogDescription() { + return (EReference) this.edgeToolEClass.getEStructuralFeatures().get(2); + } + /** * * @@ -2545,6 +2555,7 @@ public void createPackageContents() { this.edgeToolEClass = this.createEClass(EDGE_TOOL); this.createEReference(this.edgeToolEClass, EDGE_TOOL__TARGET_ELEMENT_DESCRIPTIONS); this.createEAttribute(this.edgeToolEClass, EDGE_TOOL__ICON_UR_LS_EXPRESSION); + this.createEReference(this.edgeToolEClass, EDGE_TOOL__DIALOG_DESCRIPTION); this.edgeReconnectionToolEClass = this.createEClass(EDGE_RECONNECTION_TOOL); @@ -2951,6 +2962,8 @@ public void initializePackageContents() { !IS_VOLATILE, IS_CHANGEABLE, !IS_COMPOSITE, IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE, !IS_DERIVED, IS_ORDERED); this.initEAttribute(this.getEdgeTool_IconURLsExpression(), theViewPackage.getInterpretedExpression(), "iconURLsExpression", null, 0, 1, EdgeTool.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_UNSETTABLE, !IS_ID, IS_UNIQUE, !IS_DERIVED, IS_ORDERED); + this.initEReference(this.getEdgeTool_DialogDescription(), this.getDialogDescription(), null, "dialogDescription", null, 0, 1, EdgeTool.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, + IS_COMPOSITE, !IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE, !IS_DERIVED, IS_ORDERED); this.initEClass(this.edgeReconnectionToolEClass, EdgeReconnectionTool.class, "EdgeReconnectionTool", IS_ABSTRACT, !IS_INTERFACE, IS_GENERATED_INSTANCE_CLASS); diff --git a/packages/view/backend/sirius-components-view-diagram/src/main/java/org/eclipse/sirius/components/view/diagram/impl/EdgeToolImpl.java b/packages/view/backend/sirius-components-view-diagram/src/main/java/org/eclipse/sirius/components/view/diagram/impl/EdgeToolImpl.java index 3e835ffc3d..291023fefe 100644 --- a/packages/view/backend/sirius-components-view-diagram/src/main/java/org/eclipse/sirius/components/view/diagram/impl/EdgeToolImpl.java +++ b/packages/view/backend/sirius-components-view-diagram/src/main/java/org/eclipse/sirius/components/view/diagram/impl/EdgeToolImpl.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 @@ -15,12 +15,15 @@ import java.util.Collection; import org.eclipse.emf.common.notify.Notification; +import org.eclipse.emf.common.notify.NotificationChain; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.ecore.EClass; +import org.eclipse.emf.ecore.InternalEObject; import org.eclipse.emf.ecore.impl.ENotificationImpl; import org.eclipse.emf.ecore.util.EObjectResolvingEList; import org.eclipse.sirius.components.view.diagram.DiagramElementDescription; import org.eclipse.sirius.components.view.diagram.DiagramPackage; +import org.eclipse.sirius.components.view.diagram.DialogDescription; import org.eclipse.sirius.components.view.diagram.EdgeTool; /** @@ -33,6 +36,8 @@ * Element Descriptions} *
  • {@link org.eclipse.sirius.components.view.diagram.impl.EdgeToolImpl#getIconURLsExpression Icon UR Ls * Expression}
  • + *
  • {@link org.eclipse.sirius.components.view.diagram.impl.EdgeToolImpl#getDialogDescription Dialog + * Description}
  • * * * @generated @@ -68,6 +73,16 @@ public class EdgeToolImpl extends ToolImpl implements EdgeTool { */ protected String iconURLsExpression = ICON_UR_LS_EXPRESSION_EDEFAULT; + /** + * The cached value of the '{@link #getDialogDescription() Dialog Description}' containment reference. + * + * @see #getDialogDescription() + * @generated + * @ordered + */ + protected DialogDescription dialogDescription; + /** * * @@ -123,6 +138,68 @@ public void setIconURLsExpression(String newIconURLsExpression) { this.eNotify(new ENotificationImpl(this, Notification.SET, DiagramPackage.EDGE_TOOL__ICON_UR_LS_EXPRESSION, oldIconURLsExpression, this.iconURLsExpression)); } + /** + * + * + * @generated + */ + @Override + public DialogDescription getDialogDescription() { + return this.dialogDescription; + } + + /** + * + * + * @generated + */ + public NotificationChain basicSetDialogDescription(DialogDescription newDialogDescription, NotificationChain msgs) { + DialogDescription oldDialogDescription = this.dialogDescription; + this.dialogDescription = newDialogDescription; + if (this.eNotificationRequired()) { + ENotificationImpl notification = new ENotificationImpl(this, Notification.SET, DiagramPackage.EDGE_TOOL__DIALOG_DESCRIPTION, oldDialogDescription, newDialogDescription); + if (msgs == null) + msgs = notification; + else + msgs.add(notification); + } + return msgs; + } + + /** + * + * + * @generated + */ + @Override + public void setDialogDescription(DialogDescription newDialogDescription) { + if (newDialogDescription != this.dialogDescription) { + NotificationChain msgs = null; + if (this.dialogDescription != null) + msgs = ((InternalEObject) this.dialogDescription).eInverseRemove(this, EOPPOSITE_FEATURE_BASE - DiagramPackage.EDGE_TOOL__DIALOG_DESCRIPTION, null, msgs); + if (newDialogDescription != null) + msgs = ((InternalEObject) newDialogDescription).eInverseAdd(this, EOPPOSITE_FEATURE_BASE - DiagramPackage.EDGE_TOOL__DIALOG_DESCRIPTION, null, msgs); + msgs = this.basicSetDialogDescription(newDialogDescription, msgs); + if (msgs != null) + msgs.dispatch(); + } else if (this.eNotificationRequired()) + this.eNotify(new ENotificationImpl(this, Notification.SET, DiagramPackage.EDGE_TOOL__DIALOG_DESCRIPTION, newDialogDescription, newDialogDescription)); + } + + /** + * + * + * @generated + */ + @Override + public NotificationChain eInverseRemove(InternalEObject otherEnd, int featureID, NotificationChain msgs) { + switch (featureID) { + case DiagramPackage.EDGE_TOOL__DIALOG_DESCRIPTION: + return this.basicSetDialogDescription(null, msgs); + } + return super.eInverseRemove(otherEnd, featureID, msgs); + } + /** * * @@ -135,6 +212,8 @@ public Object eGet(int featureID, boolean resolve, boolean coreType) { return this.getTargetElementDescriptions(); case DiagramPackage.EDGE_TOOL__ICON_UR_LS_EXPRESSION: return this.getIconURLsExpression(); + case DiagramPackage.EDGE_TOOL__DIALOG_DESCRIPTION: + return this.getDialogDescription(); } return super.eGet(featureID, resolve, coreType); } @@ -155,6 +234,9 @@ public void eSet(int featureID, Object newValue) { case DiagramPackage.EDGE_TOOL__ICON_UR_LS_EXPRESSION: this.setIconURLsExpression((String) newValue); return; + case DiagramPackage.EDGE_TOOL__DIALOG_DESCRIPTION: + this.setDialogDescription((DialogDescription) newValue); + return; } super.eSet(featureID, newValue); } @@ -173,6 +255,9 @@ public void eUnset(int featureID) { case DiagramPackage.EDGE_TOOL__ICON_UR_LS_EXPRESSION: this.setIconURLsExpression(ICON_UR_LS_EXPRESSION_EDEFAULT); return; + case DiagramPackage.EDGE_TOOL__DIALOG_DESCRIPTION: + this.setDialogDescription((DialogDescription) null); + return; } super.eUnset(featureID); } @@ -189,6 +274,8 @@ public boolean eIsSet(int featureID) { return this.targetElementDescriptions != null && !this.targetElementDescriptions.isEmpty(); case DiagramPackage.EDGE_TOOL__ICON_UR_LS_EXPRESSION: return ICON_UR_LS_EXPRESSION_EDEFAULT == null ? this.iconURLsExpression != null : !ICON_UR_LS_EXPRESSION_EDEFAULT.equals(this.iconURLsExpression); + case DiagramPackage.EDGE_TOOL__DIALOG_DESCRIPTION: + return this.dialogDescription != null; } return super.eIsSet(featureID); } diff --git a/packages/view/backend/sirius-components-view-diagram/src/main/resources/model/diagram.ecore b/packages/view/backend/sirius-components-view-diagram/src/main/resources/model/diagram.ecore index d403cbed9e..ad1c42e6fc 100644 --- a/packages/view/backend/sirius-components-view-diagram/src/main/resources/model/diagram.ecore +++ b/packages/view/backend/sirius-components-view-diagram/src/main/resources/model/diagram.ecore @@ -327,6 +327,8 @@ + diff --git a/packages/view/backend/sirius-components-view-diagram/src/main/resources/model/diagram.genmodel b/packages/view/backend/sirius-components-view-diagram/src/main/resources/model/diagram.genmodel index 700398f479..8dfe401821 100644 --- a/packages/view/backend/sirius-components-view-diagram/src/main/resources/model/diagram.genmodel +++ b/packages/view/backend/sirius-components-view-diagram/src/main/resources/model/diagram.genmodel @@ -247,6 +247,7 @@ + diff --git a/packages/view/backend/sirius-components-view-emf/src/main/java/org/eclipse/sirius/components/view/emf/diagram/SelectionDialogDescriptionConverter.java b/packages/view/backend/sirius-components-view-emf/src/main/java/org/eclipse/sirius/components/view/emf/diagram/SelectionDialogDescriptionConverter.java index 26e88f69b1..021358551b 100644 --- a/packages/view/backend/sirius-components-view-emf/src/main/java/org/eclipse/sirius/components/view/emf/diagram/SelectionDialogDescriptionConverter.java +++ b/packages/view/backend/sirius-components-view-emf/src/main/java/org/eclipse/sirius/components/view/emf/diagram/SelectionDialogDescriptionConverter.java @@ -14,6 +14,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.function.BiFunction; @@ -55,6 +56,14 @@ public class SelectionDialogDescriptionConverter implements IDialogDescriptionCo private static final String TARGET_OBJECT_ID = "targetObjectId"; + private static final String SOURCE_DIAGRAM_ELEMENT_TARGET_OBJECT = "sourceDiagramElementTargetObject"; + + private static final String SOURCE_DIAGRAM_ELEMENT_TARGET_OBJECT_ID = SOURCE_DIAGRAM_ELEMENT_TARGET_OBJECT + "Id"; + + private static final String TARGET_DIAGRAM_ELEMENT_TARGET_OBJECT = "targetDiagramElementTargetObject"; + + private static final String TARGET_DIAGRAM_ELEMENT_TARGET_OBJECT_ID = TARGET_DIAGRAM_ELEMENT_TARGET_OBJECT + "Id"; + private static final String TREE_DESCRIPTION_ID = "treeDescriptionId"; private static final String DIALOG_DESCRIPTION_TREE_REPRESENTATION_NAME = "Selection Dialog Tree Representation"; @@ -76,13 +85,19 @@ public SelectionDialogDescriptionConverter(IObjectService objectService, IDiagra public List convert(DialogDescription dialogDescription, AQLInterpreter interpreter) { List representationDescriptions = new ArrayList<>(); if (dialogDescription instanceof SelectionDialogDescription selectionDialogDescription) { - SelectionDescription selectionDescription = this.convertSelectionDialog(selectionDialogDescription, interpreter); - representationDescriptions.add(selectionDescription); - representationDescriptions.add(selectionDescription.getTreeDescription()); + if (this.isValid(selectionDialogDescription)) { + SelectionDescription selectionDescription = this.convertSelectionDialog(selectionDialogDescription, interpreter); + representationDescriptions.add(selectionDescription); + representationDescriptions.add(selectionDescription.getTreeDescription()); + } } return representationDescriptions; } + private boolean isValid(SelectionDialogDescription selectionDialogDescription) { + return selectionDialogDescription.getSelectionDialogTreeDescription() != null; + } + @Override public boolean canConvert(DialogDescription dialogDescription) { return dialogDescription instanceof SelectionDialogDescription; @@ -293,9 +308,7 @@ private Function> getElementProvider(AQLInterpreter int if (optionalEditingContext.isPresent()) { //Set the targetObject as the SELF value. //The targetObjectId is provided by the frontend in the treeId. - this.getTargetObjectId(variableManager) - .flatMap(targetObjectId -> this.objectService.getObject(optionalEditingContext.get(), targetObjectId)) - .ifPresent(targetObject -> variableManager.put(VariableManager.SELF, targetObject)); + this.convertTreeIdParametersToVariables(variableManager, optionalEditingContext.get()); String elementsExpression = selectionDialogTreeDescription.getElementsExpression(); Result result = interpreter.evaluateExpression(variableManager.getVariables(), elementsExpression); @@ -324,4 +337,22 @@ private String getTreeItemId(VariableManager variableManager) { return id; } + private void convertTreeIdParametersToVariables(VariableManager variableManager, IEditingContext editingContext) { + Map> parameters = variableManager.get(GetOrCreateRandomIdProvider.PREVIOUS_REPRESENTATION_ID, String.class) + .map(this.urlParser::getParameterValues) + .orElse(Map.of()); + this.safeAddVariable(parameters, variableManager, editingContext, TARGET_OBJECT_ID, VariableManager.SELF); + this.safeAddVariable(parameters, variableManager, editingContext, SOURCE_DIAGRAM_ELEMENT_TARGET_OBJECT_ID, SOURCE_DIAGRAM_ELEMENT_TARGET_OBJECT); + this.safeAddVariable(parameters, variableManager, editingContext, TARGET_DIAGRAM_ELEMENT_TARGET_OBJECT_ID, TARGET_DIAGRAM_ELEMENT_TARGET_OBJECT); + } + + private void safeAddVariable(Map> parameters, VariableManager variableManager, IEditingContext editingContext, String parameterName, String variableName) { + Optional.ofNullable(parameters.get(parameterName)) + .filter(list -> !list.isEmpty()) + .map(list -> list.get(0)) + .flatMap(objectId -> this.objectService.getObject(editingContext, objectId)) + .ifPresent(value -> { + variableManager.put(variableName, value); + }); + } } diff --git a/packages/view/backend/sirius-components-view-emf/src/main/java/org/eclipse/sirius/components/view/emf/diagram/ToolConverter.java b/packages/view/backend/sirius-components-view-emf/src/main/java/org/eclipse/sirius/components/view/emf/diagram/ToolConverter.java index 11377b2fb6..9a72496716 100644 --- a/packages/view/backend/sirius-components-view-emf/src/main/java/org/eclipse/sirius/components/view/emf/diagram/ToolConverter.java +++ b/packages/view/backend/sirius-components-view-emf/src/main/java/org/eclipse/sirius/components/view/emf/diagram/ToolConverter.java @@ -205,6 +205,7 @@ private ITool createEdgeTool(EdgeTool edgeTool, NodeDescription nodeDescription, child.put("nodeDescription", nodeDescription); return this.execute(converterContext, convertedNodes, edgeTool, child); }) + .dialogDescriptionId(this.diagramIdProvider.getId(edgeTool.getDialogDescription())) .build(); } diff --git a/packages/view/backend/sirius-components-view-emf/src/main/java/org/eclipse/sirius/components/view/emf/diagram/ViewPaletteProvider.java b/packages/view/backend/sirius-components-view-emf/src/main/java/org/eclipse/sirius/components/view/emf/diagram/ViewPaletteProvider.java index a427fb994f..386286b44e 100644 --- a/packages/view/backend/sirius-components-view-emf/src/main/java/org/eclipse/sirius/components/view/emf/diagram/ViewPaletteProvider.java +++ b/packages/view/backend/sirius-components-view-emf/src/main/java/org/eclipse/sirius/components/view/emf/diagram/ViewPaletteProvider.java @@ -245,19 +245,26 @@ private ToolSection createToolSection(NodeToolSection toolSection, DiagramDescri private ITool createEdgeTool(EdgeTool viewEdgeTool, DiagramDescription diagramDescription, NodeDescription nodeDescription, VariableManager variableManager, AQLInterpreter interpreter) { String toolId = this.idProvider.apply(viewEdgeTool).toString(); List iconURLProvider = this.edgeToolIconURLProvider(viewEdgeTool, interpreter, variableManager); + String dialogDescriptionId = ""; + if (viewEdgeTool.getDialogDescription() != null) { + dialogDescriptionId = this.diagramIdProvider.getId(viewEdgeTool.getDialogDescription()); + } + + List candidates = List.of(SingleClickOnTwoDiagramElementsCandidate.newSingleClickOnTwoDiagramElementsCandidate() + .sources(List.of(nodeDescription)) + .targets(viewEdgeTool.getTargetElementDescriptions().stream() + .filter(org.eclipse.sirius.components.view.diagram.NodeDescription.class::isInstance) + .map(viewDiagramElementDescription -> this.diagramDescriptionService.findNodeDescriptionById(diagramDescription, this.diagramIdProvider.getId(viewDiagramElementDescription))) + .filter(Optional::isPresent) + .map(Optional::get) + .toList()) + .build()); return SingleClickOnTwoDiagramElementsTool.newSingleClickOnTwoDiagramElementsTool(toolId) .label(viewEdgeTool.getName()) .iconURL(iconURLProvider) - .candidates(List.of(SingleClickOnTwoDiagramElementsCandidate.newSingleClickOnTwoDiagramElementsCandidate() - .sources(List.of(nodeDescription)) - .targets(viewEdgeTool.getTargetElementDescriptions().stream() - .filter(org.eclipse.sirius.components.view.diagram.NodeDescription.class::isInstance) - .map(viewDiagramElementDescription -> this.diagramDescriptionService.findNodeDescriptionById(diagramDescription, this.diagramIdProvider.getId(viewDiagramElementDescription))) - .filter(Optional::isPresent) - .map(Optional::get) - .toList()) - .build())) + .candidates(candidates) + .dialogDescriptionId(dialogDescriptionId) .build(); }