From 6a654acc4ee8ff8f23e81502f58bb593365619b1 Mon Sep 17 00:00:00 2001 From: Axel RICHARD Date: Thu, 12 Mar 2026 11:06:59 +0100 Subject: [PATCH] [2031] Allow to D&D a LibraryPackage from the Explorer to a diagram Bug: https://github.com/eclipse-syson/syson/issues/2031 Signed-off-by: Axel RICHARD --- CHANGELOG.adoc | 1 + .../general/view/GVDropFromExplorerTests.java | 99 +++++++++++++++---- ...xplorerViewControllerIntegrationTests.java | 31 ++---- .../helper/LibraryNamespaceProviderTests.java | 8 +- .../services/DiagramMutationDndService.java | 24 ++--- .../services/DiagramQueryElementService.java | 7 ++ ...bstractPackageNodeDescriptionProvider.java | 1 - .../common/view/services/ViewNodeService.java | 4 + .../pages/release-notes/2026.3.0.adoc | 1 + 9 files changed, 117 insertions(+), 59 deletions(-) diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index 2df4769a5..b91447d99 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -88,6 +88,7 @@ For example `ViewUsage` elements are no longer rendered in _parts_ compartments. - https://github.com/eclipse-syson/syson/issues/2037[#2037] [export] Backslashes need to be escaped during textual export in `LiteralString`. - https://github.com/eclipse-syson/syson/issues/2039[#2039] [import] Import should unescape backslash in `LiteralString`. - https://github.com/eclipse-syson/syson/issues/2052[#2052] [diagrams] Fix an issue where it was possible to create a `SatisfyRequirementUsage` from the `SatisfyRequirementUsage` graphical edge tool with a target that is not a `RequirementUsage`. +- https://github.com/eclipse-syson/syson/issues/2031[#2031] [diagrams] Fix an issue where it was not possible to drag and drop a `LibraryPackage` from the _Explorer_ to a diagram. === Improvements diff --git a/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/diagrams/general/view/GVDropFromExplorerTests.java b/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/diagrams/general/view/GVDropFromExplorerTests.java index 0ff6a4f4e..fb94e2a0c 100644 --- a/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/diagrams/general/view/GVDropFromExplorerTests.java +++ b/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/diagrams/general/view/GVDropFromExplorerTests.java @@ -28,6 +28,8 @@ import org.eclipse.sirius.components.collaborative.diagrams.dto.DiagramEventInput; import org.eclipse.sirius.components.collaborative.diagrams.dto.DiagramRefreshedEventPayload; +import org.eclipse.sirius.components.collaborative.dto.CreateChildInput; +import org.eclipse.sirius.components.collaborative.dto.CreateChildSuccessPayload; import org.eclipse.sirius.components.core.api.IEditingContext; import org.eclipse.sirius.components.core.api.IIdentityService; import org.eclipse.sirius.components.core.api.IObjectSearchService; @@ -36,6 +38,7 @@ import org.eclipse.sirius.components.graphql.tests.ExecuteEditingContextFunctionSuccessPayload; import org.eclipse.sirius.components.representations.MessageLevel; import org.eclipse.sirius.components.view.emf.diagram.IDiagramIdProvider; +import org.eclipse.sirius.web.tests.graphql.CreateChildMutationRunner; import org.eclipse.sirius.web.tests.services.api.IGivenInitialServerState; import org.eclipse.syson.AbstractIntegrationTests; import org.eclipse.syson.GivenSysONServer; @@ -44,6 +47,8 @@ import org.eclipse.syson.application.controllers.diagrams.checkers.CheckNodeOnDiagram; import org.eclipse.syson.application.controllers.diagrams.testers.DropFromExplorerTester; import org.eclipse.syson.application.data.GeneralViewAddExistingElementsTestProjectData; +import org.eclipse.syson.application.data.GeneralViewEmptyTestProjectData; +import org.eclipse.syson.application.services.SysMLv2EditService; import org.eclipse.syson.services.SemanticRunnableFactory; import org.eclipse.syson.services.diagrams.DiagramComparator; import org.eclipse.syson.services.diagrams.DiagramDescriptionIdProvider; @@ -104,6 +109,9 @@ public class GVDropFromExplorerTests extends AbstractIntegrationTests { @Autowired private DiagramComparator diagramComparator; + @Autowired + private CreateChildMutationRunner createChildMutationRunner; + private final IDescriptionNameGenerator descriptionNameGenerator = new SDVDescriptionNameGenerator(); private Flux givenSubscriptionToDiagram() { @@ -113,6 +121,13 @@ private Flux givenSubscriptionToDiagram() { return this.givenDiagramSubscription.subscribe(diagramEventInput); } + private Flux givenSubscriptionToEmptyDiagram() { + var diagramEventInput = new DiagramEventInput(UUID.randomUUID(), + GeneralViewEmptyTestProjectData.EDITING_CONTEXT, + GeneralViewEmptyTestProjectData.GraphicalIds.DIAGRAM_ID); + return this.givenDiagramSubscription.subscribe(diagramEventInput); + } + @BeforeEach public void setUp() { this.givenInitialServerState.initialize(); @@ -181,7 +196,6 @@ public void dropFromExplorerOnEmptyDiagram() { .then(exposedElementsChecker) .thenCancel() .verify(Duration.ofSeconds(10)); - } @GivenSysONServer({ GeneralViewAddExistingElementsTestProjectData.SCRIPT_PATH }) @@ -331,33 +345,84 @@ public void dropFromExplorerTwiceShouldNotExposeElementTwice() { AtomicReference diagram = new AtomicReference<>(); Consumer initialDiagramContentConsumer = assertRefreshedDiagramThat(diagram::set); + Runnable dropPart1 = () -> { + var result = this.dropFromExplorerTester.dropFromExplorer(GeneralViewAddExistingElementsTestProjectData.EDITING_CONTEXT_ID, diagram, + null, semanticElementId.get()); + List messages = JsonPath.read(result.data(), "$.data.dropOnDiagram.messages[*]"); + assertThat(messages).isEmpty(); + }; + + Runnable dropAgainPart1 = () -> { + var result = this.dropFromExplorerTester.dropFromExplorer(GeneralViewAddExistingElementsTestProjectData.EDITING_CONTEXT_ID, diagram, + null, semanticElementId.get()); + List messages = JsonPath.read(result.data(), "$.data.dropOnDiagram.messages[*]"); + assertThat(messages).as("We should receive at least one message when dropping an already visible element").hasSizeGreaterThanOrEqualTo(1); + String messageBody = JsonPath.read(result.data(), "$.data.dropOnDiagram.messages[0].body"); + assertThat(messageBody).isEqualTo("The element part1 is already visible in its parent General View"); + String messageLevel = JsonPath.read(result.data(), "$.data.dropOnDiagram.messages[0].level"); + assertThat(messageLevel).isEqualTo(MessageLevel.WARNING.toString()); + }; + StepVerifier.create(flux) .then(initialState) .consumeNextWith(initialDiagramContentConsumer) - .then(() -> { - var result = this.dropFromExplorerTester.dropFromExplorer(GeneralViewAddExistingElementsTestProjectData.EDITING_CONTEXT_ID, diagram, - null, semanticElementId.get()); - List messages = JsonPath.read(result.data(), "$.data.dropOnDiagram.messages[*]"); - assertThat(messages).isEmpty(); - }) + .then(dropPart1) .consumeNextWith(payload -> { }) .then(hasBeenExposed) - .then(() -> { - var result = this.dropFromExplorerTester.dropFromExplorer(GeneralViewAddExistingElementsTestProjectData.EDITING_CONTEXT_ID, diagram, - null, semanticElementId.get()); - List messages = JsonPath.read(result.data(), "$.data.dropOnDiagram.messages[*]"); - assertThat(messages).as("We should receive at least one message when dropping an already visible element").hasSizeGreaterThanOrEqualTo(1); - String messageBody = JsonPath.read(result.data(), "$.data.dropOnDiagram.messages[0].body"); - assertThat(messageBody).isEqualTo("The element part1 is already visible in its parent General View"); - String messageLevel = JsonPath.read(result.data(), "$.data.dropOnDiagram.messages[0].level"); - assertThat(messageLevel).isEqualTo(MessageLevel.WARNING.toString()); - }) + .then(dropAgainPart1) .consumeNextWith(payload -> { }) .then(hasNotBeenExposedAgain) .thenCancel() .verify(Duration.ofSeconds(10)); } + @GivenSysONServer({ GeneralViewEmptyTestProjectData.SCRIPT_PATH }) + @Test + public void dropLibraryPackageFromExplorerOnDiagram() { + var input = new CreateChildInput( + UUID.randomUUID(), + GeneralViewEmptyTestProjectData.EDITING_CONTEXT, + GeneralViewEmptyTestProjectData.SemanticIds.PACKAGE_1_ID, + SysMLv2EditService.ID_PREFIX + "LibraryPackage"); + var result = this.createChildMutationRunner.run(input); + + String typename = JsonPath.read(result.data(), "$.data.createChild.__typename"); + assertThat(typename).isEqualTo(CreateChildSuccessPayload.class.getSimpleName()); + + String objectId = JsonPath.read(result.data(), "$.data.createChild.object.id"); + assertThat(objectId).isNotBlank(); + + String objectLabel = JsonPath.read(result.data(), "$.data.createChild.object.label"); + assertThat(objectLabel).isEqualTo("LibraryPackage1"); + + var flux = this.givenSubscriptionToEmptyDiagram(); + + AtomicReference diagram = new AtomicReference<>(); + Consumer initialDiagramContentConsumer = assertRefreshedDiagramThat(diagram::set); + + var diagramDescription = this.givenDiagramDescription.getDiagramDescription(GeneralViewEmptyTestProjectData.EDITING_CONTEXT, + SysONRepresentationDescriptionIdentifiers.GENERAL_VIEW_DIAGRAM_DESCRIPTION_ID); + var diagramDescriptionIdProvider = new DiagramDescriptionIdProvider(diagramDescription, this.diagramIdProvider); + + Runnable dropFromExplorerRunnable = () -> { + this.dropFromExplorerTester.dropFromExplorerOnDiagram(GeneralViewEmptyTestProjectData.EDITING_CONTEXT, diagram, objectId); + }; + + Consumer updatedDiagramConsumer = assertRefreshedDiagramThat(newDiagram -> { + assertThat(newDiagram.getNodes()).hasSize(1); + Node packageDiagramNode = newDiagram.getNodes().get(0); + String packageNodeDescriptionId = diagramDescriptionIdProvider.getNodeDescriptionId(this.descriptionNameGenerator.getNodeName(SysmlPackage.eINSTANCE.getPackage())); + assertThat(packageDiagramNode).hasDescriptionId(packageNodeDescriptionId); + }); + + StepVerifier.create(flux) + .consumeNextWith(initialDiagramContentConsumer) + .then(dropFromExplorerRunnable) + .consumeNextWith(updatedDiagramConsumer) + .thenCancel() + .verify(Duration.ofSeconds(10)); + } + private String getSemanticElementWithTargetObjectLabel(IEditingContext editingContext, String targetObjectLabel) { Object semanticRootObject = this.objectSearchService.getObject(editingContext, GeneralViewAddExistingElementsTestProjectData.SemanticIds.PACKAGE_1_ID).orElse(null); assertThat(semanticRootObject).isInstanceOf(Package.class); diff --git a/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/explorer/view/ExplorerViewControllerIntegrationTests.java b/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/explorer/view/ExplorerViewControllerIntegrationTests.java index a5bf83adb..4e9678331 100644 --- a/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/explorer/view/ExplorerViewControllerIntegrationTests.java +++ b/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/explorer/view/ExplorerViewControllerIntegrationTests.java @@ -41,6 +41,7 @@ import org.eclipse.sirius.web.tests.services.explorer.ExplorerEventSubscriptionRunner; import org.eclipse.sirius.web.tests.services.representation.RepresentationIdBuilder; import org.eclipse.syson.AbstractIntegrationTests; +import org.eclipse.syson.GivenSysONServer; import org.eclipse.syson.application.data.ExplorerViewDirectEditTestProjectData; import org.eclipse.syson.application.data.GeneralViewEmptyTestProjectData; import org.eclipse.syson.application.data.ProjectWithLibraryDependencyContainingLibraryPackageTestProjectData; @@ -51,8 +52,6 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.jdbc.Sql; -import org.springframework.test.context.jdbc.SqlConfig; import org.springframework.test.context.transaction.TestTransaction; import org.springframework.transaction.annotation.Transactional; @@ -137,9 +136,7 @@ public void beforeEach() { } @DisplayName("GIVEN a Package, WHEN the New Representation menu is invoked, THEN InterconnectionView is a possible candidate") - @Sql(scripts = { GeneralViewEmptyTestProjectData.SCRIPT_PATH }, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD, - config = @SqlConfig(transactionMode = SqlConfig.TransactionMode.ISOLATED)) - @Sql(scripts = { "/scripts/cleanup.sql" }, executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD, config = @SqlConfig(transactionMode = SqlConfig.TransactionMode.ISOLATED)) + @GivenSysONServer({ GeneralViewEmptyTestProjectData.SCRIPT_PATH }) @Test public void canCreateInterconnectionViewOnPackage() { Map variables = Map.of( @@ -173,9 +170,7 @@ public void canCreateInterconnectionViewOnPackage() { } @DisplayName("GIVEN the SysON Explorer View, WHEN we direct edit a ViewUsage typed with a standard diagram, THEN the type of ViewUsage is not part of the initial value of the direct edit") - @Sql(scripts = { ExplorerViewDirectEditTestProjectData.SCRIPT_PATH }, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD, - config = @SqlConfig(transactionMode = SqlConfig.TransactionMode.ISOLATED)) - @Sql(scripts = { "/scripts/cleanup.sql" }, executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD, config = @SqlConfig(transactionMode = SqlConfig.TransactionMode.ISOLATED)) + @GivenSysONServer({ ExplorerViewDirectEditTestProjectData.SCRIPT_PATH }) @Test public void testDirectEditOnViewUsage() { var expandedIds = this.getAllTreeItemIds(); @@ -203,9 +198,7 @@ public void testDirectEditOnViewUsage() { } @DisplayName("GIVEN the SysON Explorer View, WHEN we direct edit an Element with a shortName, THEN the shortName is not part of the initial value of the direct edit") - @Sql(scripts = { ExplorerViewDirectEditTestProjectData.SCRIPT_PATH }, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD, - config = @SqlConfig(transactionMode = SqlConfig.TransactionMode.ISOLATED)) - @Sql(scripts = { "/scripts/cleanup.sql" }, executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD, config = @SqlConfig(transactionMode = SqlConfig.TransactionMode.ISOLATED)) + @GivenSysONServer({ ExplorerViewDirectEditTestProjectData.SCRIPT_PATH }) @Test public void testDirectEditOnElementWithShortName() { var expandedIds = this.getAllTreeItemIds(); @@ -228,9 +221,7 @@ public void testDirectEditOnElementWithShortName() { } @DisplayName("GIVEN the SysON Explorer View, WHEN hide expose element filter is active, THEN the expose element are not return as tree item") - @Sql(scripts = { ExplorerViewDirectEditTestProjectData.SCRIPT_PATH }, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD, - config = @SqlConfig(transactionMode = SqlConfig.TransactionMode.ISOLATED)) - @Sql(scripts = { "/scripts/cleanup.sql" }, executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD, config = @SqlConfig(transactionMode = SqlConfig.TransactionMode.ISOLATED)) + @GivenSysONServer({ ExplorerViewDirectEditTestProjectData.SCRIPT_PATH }) @Test public void testHideExposeElementFilter() { var expandedIds = this.getAllTreeItemIds(); @@ -249,9 +240,7 @@ public void testHideExposeElementFilter() { } @DisplayName("GIVEN the SysON Explorer View, WHEN hide user libraries filter is active, THEN no user libraries are return as tree item") - @Sql(scripts = { ProjectWithLibraryDependencyContainingLibraryPackageTestProjectData.SCRIPT_PATH }, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD, - config = @SqlConfig(transactionMode = SqlConfig.TransactionMode.ISOLATED)) - @Sql(scripts = { "/scripts/cleanup.sql" }, executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD, config = @SqlConfig(transactionMode = SqlConfig.TransactionMode.ISOLATED)) + @GivenSysONServer({ ProjectWithLibraryDependencyContainingLibraryPackageTestProjectData.SCRIPT_PATH }) @Test public void testHideUserLibrariesFilter() { var expandedIds = List.of(UUID.nameUUIDFromBytes("SysON_Libraries_Directory".getBytes()).toString()); @@ -270,9 +259,7 @@ public void testHideUserLibrariesFilter() { } @DisplayName("GIVEN the SysON Explorer View, WHEN querying the filters, THEN the syson filters are returned") - @Sql(scripts = { ExplorerViewDirectEditTestProjectData.SCRIPT_PATH }, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD, - config = @SqlConfig(transactionMode = SqlConfig.TransactionMode.ISOLATED)) - @Sql(scripts = { "/scripts/cleanup.sql" }, executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD, config = @SqlConfig(transactionMode = SqlConfig.TransactionMode.ISOLATED)) + @GivenSysONServer({ ExplorerViewDirectEditTestProjectData.SCRIPT_PATH }) @Test public void testSysONFiltersOnSysONExplorer() { Map variables = Map.of( @@ -291,9 +278,7 @@ public void testSysONFiltersOnSysONExplorer() { } @DisplayName("GIVEN the Sirius Explorer View, WHEN querying the filters, THEN no syson filters are returned") - @Sql(scripts = { ExplorerViewDirectEditTestProjectData.SCRIPT_PATH }, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD, - config = @SqlConfig(transactionMode = SqlConfig.TransactionMode.ISOLATED)) - @Sql(scripts = { "/scripts/cleanup.sql" }, executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD, config = @SqlConfig(transactionMode = SqlConfig.TransactionMode.ISOLATED)) + @GivenSysONServer({ ExplorerViewDirectEditTestProjectData.SCRIPT_PATH }) @Test public void testSysONFiltersOnSiriusExplorer() { Map variables = Map.of( diff --git a/backend/application/syson-application/src/test/java/org/eclipse/syson/metamodel/helper/LibraryNamespaceProviderTests.java b/backend/application/syson-application/src/test/java/org/eclipse/syson/metamodel/helper/LibraryNamespaceProviderTests.java index 97f9978fb..14dc09c7b 100644 --- a/backend/application/syson-application/src/test/java/org/eclipse/syson/metamodel/helper/LibraryNamespaceProviderTests.java +++ b/backend/application/syson-application/src/test/java/org/eclipse/syson/metamodel/helper/LibraryNamespaceProviderTests.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2025 Obeo. + * Copyright (c) 2025, 2026 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 @@ -76,7 +76,6 @@ public void checkWithRegisteredLibrary() { for (Resource r : this.resourceSet.getResources()) { provider.addImmutableLibrariesNamespaces(r); } - // Test some use case this.assertNamespaceAccess("BooleanFunctions::ToString::x", provider); this.assertNamespaceAccess("Clocks::TimeOf::timeOrderingConstraint", provider); @@ -84,12 +83,10 @@ public void checkWithRegisteredLibrary() { this.assertNamespaceAccess("Views::asElementTable::columnView::viewRendering", provider); this.assertNamespaceAccess("USCustomaryUnits::'degree fahrenheit (absolute temperature scale)'::zeroDegreeFahrenheitToKelvinShift::source", provider); this.assertNamespaceAccess("'Custom library'::'Custom part def'::'Custom part usage'", provider); - } @Test @DisplayName("Given a ResourceSet with no library registered as immutable, WHEN accessing some Namespace from their qualified name, THEN the targeted element should be returned.") - public void withNoLibraryAdded() { LibraryNamespaceProvider provider = new LibraryNamespaceProvider(this.resourceSet); // Test some use case @@ -100,7 +97,6 @@ public void withNoLibraryAdded() { this.assertNamespaceAccess("USCustomaryUnits::'degree fahrenheit (absolute temperature scale)'::zeroDegreeFahrenheitToKelvinShift::source", provider); this.assertNamespaceAccess("USCustomaryUnits::'quad (10^15 Btu_IT)'::unitConversion::isExact", provider); this.assertNamespaceAccess("'Custom library'::'Custom part def'::'Custom part usage'", provider); - } private void assertNamespaceAccess(String expectedQualifiedName, LibraryNamespaceProvider provider) { @@ -108,7 +104,6 @@ private void assertNamespaceAccess(String expectedQualifiedName, LibraryNamespac .as("Looking for " + expectedQualifiedName) .isNotNull() .matches(e -> expectedQualifiedName.equals(e.getQualifiedName())); - } private Resource createStandardLibWithSpace() { @@ -125,5 +120,4 @@ private Resource createStandardLibWithSpace() { this.builder.createInWithName(PartUsage.class, partDef, "Custom part usage"); return resource; } - } diff --git a/backend/services/syson-diagram-services/src/main/java/org/eclipse/syson/diagram/services/DiagramMutationDndService.java b/backend/services/syson-diagram-services/src/main/java/org/eclipse/syson/diagram/services/DiagramMutationDndService.java index 19ec5198a..93ecb1d7e 100644 --- a/backend/services/syson-diagram-services/src/main/java/org/eclipse/syson/diagram/services/DiagramMutationDndService.java +++ b/backend/services/syson-diagram-services/src/main/java/org/eclipse/syson/diagram/services/DiagramMutationDndService.java @@ -316,17 +316,19 @@ private void dropElementFromExplorerInTarget(Element sourceElement, Element targ if (this.modelQueryElementService.isExposed(sourceElement, this.diagramQueryElementService.getViewUsage(editingContext, diagramContext, selectedNode))) { var parentId = this.diagramQueryElementService.getGraphicalParentId(diagramContext, selectedNode); var descriptionId = this.diagramQueryElementService.getNodeDescriptionId(sourceElement, diagramContext.diagram(), editingContext); - var nodeId = new NodeIdProvider().getNodeId(parentId, - descriptionId.get(), - NodeContainmentKind.CHILD_NODE, - this.siriusWebCoreServices.identityService().getId(sourceElement)); - this.diagramQueryElementService.findNodeById(diagramContext.diagram(), nodeId).ifPresent(node -> { - if (node.getState().equals(ViewModifier.Hidden)) { - diagramContext.diagramEvents().add(new HideDiagramElementEvent(Set.of(nodeId), false)); - } else { - this.logAlreadyVisibleMessage(sourceElement, targetElement); - } - }); + if (descriptionId.isPresent()) { + var nodeId = new NodeIdProvider().getNodeId(parentId, + descriptionId.get(), + NodeContainmentKind.CHILD_NODE, + this.siriusWebCoreServices.identityService().getId(sourceElement)); + this.diagramQueryElementService.findNodeById(diagramContext.diagram(), nodeId).ifPresent(node -> { + if (node.getState().equals(ViewModifier.Hidden)) { + diagramContext.diagramEvents().add(new HideDiagramElementEvent(Set.of(nodeId), false)); + } else { + this.logAlreadyVisibleMessage(sourceElement, targetElement); + } + }); + } } else { Node newSelectedNode = selectedNode; if (selectedNode == null) { diff --git a/backend/services/syson-diagram-services/src/main/java/org/eclipse/syson/diagram/services/DiagramQueryElementService.java b/backend/services/syson-diagram-services/src/main/java/org/eclipse/syson/diagram/services/DiagramQueryElementService.java index 505764229..44d37d5f7 100644 --- a/backend/services/syson-diagram-services/src/main/java/org/eclipse/syson/diagram/services/DiagramQueryElementService.java +++ b/backend/services/syson-diagram-services/src/main/java/org/eclipse/syson/diagram/services/DiagramQueryElementService.java @@ -38,6 +38,8 @@ import org.eclipse.syson.sysml.Feature; import org.eclipse.syson.sysml.FeatureTyping; import org.eclipse.syson.sysml.FlowUsage; +import org.eclipse.syson.sysml.LibraryPackage; +import org.eclipse.syson.sysml.SysmlPackage; import org.eclipse.syson.sysml.ViewUsage; import org.eclipse.syson.sysml.helper.EMFUtils; import org.eclipse.syson.sysml.metamodel.services.MetamodelQueryElementService; @@ -298,6 +300,11 @@ public Optional getNodeDescriptionId(Element element, Diagram diagram, I .filter(nodeDesc -> nodeDesc.getName().equals("GV Node Subject")) .map(nodeDesc -> this.diagramIdProvider.getId(nodeDesc)) .findFirst(); + } else if (element instanceof LibraryPackage) { + nodeDescriptionId = EMFUtils.allContainedObjectOfType(optViewDD.get(), org.eclipse.sirius.components.view.diagram.NodeDescription.class) + .filter(nodeDesc -> nodeDesc.getName().equals("GV Node " + SysmlPackage.eINSTANCE.getPackage().getName())) + .map(nodeDesc -> this.diagramIdProvider.getId(nodeDesc)) + .findFirst(); } else { nodeDescriptionId = EMFUtils.allContainedObjectOfType(optViewDD.get(), org.eclipse.sirius.components.view.diagram.NodeDescription.class) .filter(nodeDesc -> nodeDesc.getName().equals("GV Node " + element.eClass().getName())) diff --git a/backend/views/syson-diagram-common-view/src/main/java/org/eclipse/syson/diagram/common/view/nodes/AbstractPackageNodeDescriptionProvider.java b/backend/views/syson-diagram-common-view/src/main/java/org/eclipse/syson/diagram/common/view/nodes/AbstractPackageNodeDescriptionProvider.java index e4f41e74a..90f1a4daa 100644 --- a/backend/views/syson-diagram-common-view/src/main/java/org/eclipse/syson/diagram/common/view/nodes/AbstractPackageNodeDescriptionProvider.java +++ b/backend/views/syson-diagram-common-view/src/main/java/org/eclipse/syson/diagram/common/view/nodes/AbstractPackageNodeDescriptionProvider.java @@ -212,7 +212,6 @@ private NodePalette createNodePalette(NodeDescription nodeDescription, IViewDiag nodesWithoutSection.add(this.createNodeTool(docNodeDesc, SysmlPackage.eINSTANCE.getDocumentation())); }); - return this.diagramBuilderHelper.newNodePalette() .deleteTool(deleteTool.build()) .labelEditTool(editTool.build()) diff --git a/backend/views/syson-diagram-common-view/src/main/java/org/eclipse/syson/diagram/common/view/services/ViewNodeService.java b/backend/views/syson-diagram-common-view/src/main/java/org/eclipse/syson/diagram/common/view/services/ViewNodeService.java index 7c09c3f47..26bdb000e 100644 --- a/backend/views/syson-diagram-common-view/src/main/java/org/eclipse/syson/diagram/common/view/services/ViewNodeService.java +++ b/backend/views/syson-diagram-common-view/src/main/java/org/eclipse/syson/diagram/common/view/services/ViewNodeService.java @@ -43,6 +43,7 @@ import org.eclipse.syson.sysml.AnnotatingElement; import org.eclipse.syson.sysml.Element; import org.eclipse.syson.sysml.Expose; +import org.eclipse.syson.sysml.LibraryPackage; import org.eclipse.syson.sysml.MembershipExpose; import org.eclipse.syson.sysml.Package; import org.eclipse.syson.sysml.PartUsage; @@ -684,6 +685,9 @@ protected List getAncestors(Node selectedNode, Diagram diagram, IEditing * false otherwise. */ protected boolean isTypeOf(Element element, EClass domainType) { + if (element instanceof LibraryPackage) { + return Objects.equals(SysmlPackage.eINSTANCE.getPackage(), domainType); + } return element != null && Objects.equals(element.eClass(), domainType); } } diff --git a/doc/content/modules/user-manual/pages/release-notes/2026.3.0.adoc b/doc/content/modules/user-manual/pages/release-notes/2026.3.0.adoc index 4052075a2..5dbe9c504 100644 --- a/doc/content/modules/user-manual/pages/release-notes/2026.3.0.adoc +++ b/doc/content/modules/user-manual/pages/release-notes/2026.3.0.adoc @@ -25,6 +25,7 @@ They can also add their own SysML-based validation rules by returning additional ** Allow redefining a `PartUsage` with the same name as the redefined `Usage`. ** Fix an issue where `ConnectionDefinition` graphical nodes where incorrectly labelled as `«part def»` instead of `«connection def»`. ** Fix an issue where it was possible to create a `SatisfyRequirementUsage` from the `SatisfyRequirementUsage` graphical edge tool with a target that is not a `RequirementUsage`. +** Fix an issue where it was not possible to drag and drop a `LibraryPackage` from the _Explorer_ to a diagram. * In textual import/export: