diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index 4e6674df4b..db32eba6f0 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -81,6 +81,7 @@ It is also now possible to create new concerns using the _New Concern_ tool from - https://github.com/eclipse-syson/syson/issues/2397[#2397] [diagrams] Display existing binary requirement derivations as edges in the _General View_. A requirement derivation is a `ConnectionUsage` annotated with the `#derivation` metadata or typed by `DerivationConnections::Derivation`. The edge goes from the derived requirement to the original one and is displayed as a dashed `«derive»` line, so it can be distinguished from a `«satisfy»` edge. +- https://github.com/eclipse-syson/syson/issues/2403[#2403] [diagrams] Add support for the inheritance of `ItemUsage` border nodes on `ActionDefinition` and `ActionUsage` graphical nodes. == v2026.7.0 diff --git a/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/diagrams/general/view/GVFlowUsageTests.java b/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/diagrams/general/view/GVFlowUsageTests.java index 1da41de736..e47139daa4 100644 --- a/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/diagrams/general/view/GVFlowUsageTests.java +++ b/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/diagrams/general/view/GVFlowUsageTests.java @@ -685,6 +685,8 @@ private List getExpectedFlowTargetDescriptionNames() { this.descriptionNameGenerator.getInheritedBorderNodeName(SysmlPackage.eINSTANCE.getPortUsage(), SysmlPackage.eINSTANCE.getDefinition_OwnedPort()), this.descriptionNameGenerator.getBorderNodeName(SysmlPackage.eINSTANCE.getItemUsage(), SysmlPackage.eINSTANCE.getDefinition_OwnedItem()), this.descriptionNameGenerator.getBorderNodeName(SysmlPackage.eINSTANCE.getItemUsage(), SysmlPackage.eINSTANCE.getUsage_NestedItem()), + this.descriptionNameGenerator.getInheritedBorderNodeName(SysmlPackage.eINSTANCE.getItemUsage(), SysmlPackage.eINSTANCE.getDefinition_OwnedItem()), + this.descriptionNameGenerator.getInheritedBorderNodeName(SysmlPackage.eINSTANCE.getItemUsage(), SysmlPackage.eINSTANCE.getUsage_NestedItem()), this.descriptionNameGenerator.getBorderNodeName(SysmlPackage.eINSTANCE.getReferenceUsage()), this.descriptionNameGenerator.getInheritedBorderNodeName(SysmlPackage.eINSTANCE.getReferenceUsage())); } diff --git a/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/diagrams/general/view/inheritance/GVCompartmentItemInheritanceTests.java b/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/diagrams/general/view/inheritance/GVCompartmentItemInheritanceTests.java index 65d1649e80..d1ed0c51dc 100644 --- a/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/diagrams/general/view/inheritance/GVCompartmentItemInheritanceTests.java +++ b/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/diagrams/general/view/inheritance/GVCompartmentItemInheritanceTests.java @@ -188,11 +188,11 @@ private static Stream actionsCompartmentItemInheritanceArguments() { private static Stream itemsCompartmentItemInheritanceArguments() { NestedElementTestArgument nestedItemWithBorderNode = new NestedElementTestArgument("New Item", "items", "item1", "", 1, 1, 0); return Stream.of( - Arguments.of(ACTION_DEFINITION_ARGUMENT, nestedItemWithBorderNode, ACTION_USAGE_ARGUMENT, FEATURE_TYPING_ARGUMENT), - Arguments.of(ACTION_DEFINITION_ARGUMENT, nestedItemWithBorderNode, ACTION_DEFINITION_ARGUMENT, SUBCLASSIFICATION_ARGUMENT), - Arguments.of(ACTION_USAGE_ARGUMENT, nestedItemWithBorderNode, ACTION_USAGE_ARGUMENT, SUBSETTING_ARGUMENT), - Arguments.of(ACTION_USAGE_ARGUMENT, nestedItemWithBorderNode, ACTION_USAGE_ARGUMENT, REFERENCE_SUBSETTING_ARGUMENT), - Arguments.of(ACTION_USAGE_ARGUMENT, nestedItemWithBorderNode, ACTION_USAGE_ARGUMENT, REDEFINITION_ARGUMENT), + Arguments.of(ACTION_DEFINITION_ARGUMENT, nestedItemWithBorderNode, ACTION_USAGE_ARGUMENT, FEATURE_TYPING_ARGUMENT.withExtraBorderNodes(1)), + Arguments.of(ACTION_DEFINITION_ARGUMENT, nestedItemWithBorderNode, ACTION_DEFINITION_ARGUMENT, SUBCLASSIFICATION_ARGUMENT.withExtraBorderNodes(1)), + Arguments.of(ACTION_USAGE_ARGUMENT, nestedItemWithBorderNode, ACTION_USAGE_ARGUMENT, SUBSETTING_ARGUMENT.withExtraBorderNodes(1)), + Arguments.of(ACTION_USAGE_ARGUMENT, nestedItemWithBorderNode, ACTION_USAGE_ARGUMENT, REFERENCE_SUBSETTING_ARGUMENT.withExtraBorderNodes(1)), + Arguments.of(ACTION_USAGE_ARGUMENT, nestedItemWithBorderNode, ACTION_USAGE_ARGUMENT, REDEFINITION_ARGUMENT.withExtraBorderNodes(1)), Arguments.of(PORT_USAGE_ARGUMENT, nestedItemWithBorderNode, PORT_USAGE_ARGUMENT, SUBSETTING_ARGUMENT), Arguments.of(PORT_USAGE_ARGUMENT, nestedItemWithBorderNode, PORT_USAGE_ARGUMENT, REFERENCE_SUBSETTING_ARGUMENT), Arguments.of(PORT_DEFINITION_ARGUMENT, nestedItemWithBorderNode, PORT_DEFINITION_ARGUMENT, SUBCLASSIFICATION_ARGUMENT) diff --git a/backend/views/syson-diagram-common-view/src/main/java/org/eclipse/syson/diagram/common/view/nodes/AbstractItemUsageBorderNodeDescriptionProvider.java b/backend/views/syson-diagram-common-view/src/main/java/org/eclipse/syson/diagram/common/view/nodes/AbstractItemUsageBorderNodeDescriptionProvider.java new file mode 100644 index 0000000000..08e224f74f --- /dev/null +++ b/backend/views/syson-diagram-common-view/src/main/java/org/eclipse/syson/diagram/common/view/nodes/AbstractItemUsageBorderNodeDescriptionProvider.java @@ -0,0 +1,154 @@ +/******************************************************************************* + * Copyright (c) 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 + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ +package org.eclipse.syson.diagram.common.view.nodes; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +import org.eclipse.emf.ecore.EReference; +import org.eclipse.sirius.components.view.builder.IViewDiagramElementFinder; +import org.eclipse.sirius.components.view.builder.providers.IColorProvider; +import org.eclipse.sirius.components.view.diagram.ConditionalNodeStyle; +import org.eclipse.sirius.components.view.diagram.DiagramDescription; +import org.eclipse.sirius.components.view.diagram.EdgeTool; +import org.eclipse.sirius.components.view.diagram.NodeDescription; +import org.eclipse.sirius.components.view.diagram.NodePalette; +import org.eclipse.sirius.components.view.diagram.NodeStyleDescription; +import org.eclipse.sirius.components.view.diagram.OutsideLabelDescription; +import org.eclipse.sirius.components.view.diagram.OutsideLabelStyle; +import org.eclipse.sirius.components.view.diagram.SynchronizationPolicy; +import org.eclipse.sirius.components.view.diagram.UserResizableDirection; +import org.eclipse.syson.diagram.common.view.services.ViewEdgeToolService; +import org.eclipse.syson.services.UtilService; +import org.eclipse.syson.sysml.SysmlPackage; +import org.eclipse.syson.util.AQLConstants; +import org.eclipse.syson.util.IDescriptionNameGenerator; +import org.eclipse.syson.util.ServiceMethod; +import org.eclipse.syson.util.SysMLMetamodelHelper; +import org.eclipse.syson.util.ViewConstants; + +/** + * Common behavior for all item usage border node description. + * + * @author gcoutabe + */ +public abstract class AbstractItemUsageBorderNodeDescriptionProvider extends AbstractNodeDescriptionProvider { + + protected final IDescriptionNameGenerator descriptionNameGenerator; + + protected final EReference eReference; + + public AbstractItemUsageBorderNodeDescriptionProvider(EReference eReference, IColorProvider colorProvider, IDescriptionNameGenerator descriptionNameGenerator) { + super(colorProvider); + this.eReference = Objects.requireNonNull(eReference); + this.descriptionNameGenerator = Objects.requireNonNull(descriptionNameGenerator); + } + + protected abstract String getSemanticCandidatesExpression(); + + protected abstract String getName(); + + protected abstract OutsideLabelDescription createOutsideLabelDescription(); + + protected abstract List getEdgeTools(IViewDiagramElementFinder cache, NodeDescription nodeDescription); + + protected abstract NodePalette createNodePalette(IViewDiagramElementFinder cache, NodeDescription nodeDescription); + + @Override + public NodeDescription create() { + String domainType = SysMLMetamodelHelper.buildQualifiedName(SysmlPackage.eINSTANCE.getItemUsage()); + return this.diagramBuilderHelper.newNodeDescription() + .defaultHeightExpression("10") + .defaultWidthExpression("10") + .domainType(domainType) + .outsideLabels(this.createOutsideLabelDescription()) + .name(this.getName()) + .semanticCandidatesExpression(this.getSemanticCandidatesExpression()) + .style(this.createItemUnsetNodeStyle()) + .conditionalStyles(this.createItemUsageConditionalNodeStyles().toArray(ConditionalNodeStyle[]::new)) + .userResizable(UserResizableDirection.NONE) + .synchronizationPolicy(SynchronizationPolicy.SYNCHRONIZED) + .build(); + } + + protected IDescriptionNameGenerator getDescriptionNameGenerator() { + return this.descriptionNameGenerator; + } + + private NodeStyleDescription createItemUnsetNodeStyle() { + return this.diagramBuilderHelper.newRectangularNodeStyleDescription() + .borderColor(this.colorProvider.getColor(ViewConstants.DEFAULT_BORDER_COLOR)) + .borderRadius(0) + .background(this.colorProvider.getColor(ViewConstants.DEFAULT_BACKGROUND_COLOR)) + .build(); + } + + protected OutsideLabelStyle createOutsideLabelStyle() { + return this.diagramBuilderHelper.newOutsideLabelStyle() + .bold(false) + .borderSize(0) + .fontSize(12) + .italic(false) + .labelColor(this.colorProvider.getColor(ViewConstants.DEFAULT_LABEL_COLOR)) + .showIconExpression(AQLConstants.AQL_FALSE) + .strikeThrough(false) + .underline(false) + .build(); + } + + private List createItemUsageConditionalNodeStyles() { + var borderColor = this.colorProvider.getColor(ViewConstants.DEFAULT_BORDER_COLOR); + return List.of( + this.diagramBuilderHelper.newConditionalNodeStyle() + .condition(ServiceMethod.of0(UtilService::isInFeature).aqlSelf()) + .style(this.createImageNodeStyleDescription("/images/feature_in.svg", borderColor, true)) + .build(), + this.diagramBuilderHelper.newConditionalNodeStyle() + .condition(ServiceMethod.of0(UtilService::isOutFeature).aqlSelf()) + .style(this.createImageNodeStyleDescription("/images/feature_out.svg", borderColor, true)) + .build(), + this.diagramBuilderHelper.newConditionalNodeStyle() + .condition(ServiceMethod.of0(UtilService::isInOutFeature).aqlSelf()) + .style(this.createImageNodeStyleDescription("/images/feature_inout.svg", borderColor, true)) + .build()); + } + + @Override + public void link(DiagramDescription diagramDescription, IViewDiagramElementFinder cache) { + var optItemUsageBorderNodeDescription = cache.getNodeDescription(this.getName()); + + NodeDescription nodeDescription = optItemUsageBorderNodeDescription.get(); + nodeDescription.setPalette(this.createNodePalette(cache, nodeDescription)); + } + + private List getBindingConnectorAsUsageToolTarget(IViewDiagramElementFinder cache) { + var nodeDescriptions = new ArrayList(); + cache.getNodeDescription(this.getName()).ifPresent(nodeDescriptions::add); + cache.getNodeDescription(this.getDescriptionNameGenerator().getBorderNodeName(SysmlPackage.eINSTANCE.getItemUsage(), this.eReference)).ifPresent(nodeDescriptions::add); + return nodeDescriptions; + } + + protected EdgeTool createBindingConnectorAsUsageEdgeTool(IViewDiagramElementFinder cache) { + return this.getViewEdgeToolService(cache).createBindingConnectorAsUsageEdgeTool(this.getBindingConnectorAsUsageToolTarget(cache)); + } + + protected EdgeTool createFlowUsageEdgeTool(IViewDiagramElementFinder cache) { + return this.getViewEdgeToolService(cache).createFlowUsageEdgeTool(this.getFlowUsageToolTargetDescriptions(cache, this.descriptionNameGenerator)); + } + + protected ViewEdgeToolService getViewEdgeToolService(IViewDiagramElementFinder cache) { + return new ViewEdgeToolService(this.viewBuilderHelper, this.diagramBuilderHelper, cache.getNodeDescriptions(), this.descriptionNameGenerator); + } + +} diff --git a/backend/views/syson-diagram-common-view/src/main/java/org/eclipse/syson/diagram/common/view/nodes/AbstractNodeDescriptionProvider.java b/backend/views/syson-diagram-common-view/src/main/java/org/eclipse/syson/diagram/common/view/nodes/AbstractNodeDescriptionProvider.java index 13742cecd5..ee889cc2ec 100644 --- a/backend/views/syson-diagram-common-view/src/main/java/org/eclipse/syson/diagram/common/view/nodes/AbstractNodeDescriptionProvider.java +++ b/backend/views/syson-diagram-common-view/src/main/java/org/eclipse/syson/diagram/common/view/nodes/AbstractNodeDescriptionProvider.java @@ -94,6 +94,8 @@ protected List getFlowUsageToolTargetDescriptions(IViewDiagramE cache.getNodeDescription(descriptionNameGenerator.getInheritedBorderNodeName(SysmlPackage.eINSTANCE.getPortUsage(), SysmlPackage.eINSTANCE.getDefinition_OwnedPort())).ifPresent(nodes::add); cache.getNodeDescription(descriptionNameGenerator.getBorderNodeName(SysmlPackage.eINSTANCE.getItemUsage(), SysmlPackage.eINSTANCE.getDefinition_OwnedItem())).ifPresent(nodes::add); cache.getNodeDescription(descriptionNameGenerator.getBorderNodeName(SysmlPackage.eINSTANCE.getItemUsage(), SysmlPackage.eINSTANCE.getUsage_NestedItem())).ifPresent(nodes::add); + cache.getNodeDescription(descriptionNameGenerator.getInheritedBorderNodeName(SysmlPackage.eINSTANCE.getItemUsage(), SysmlPackage.eINSTANCE.getDefinition_OwnedItem())).ifPresent(nodes::add); + cache.getNodeDescription(descriptionNameGenerator.getInheritedBorderNodeName(SysmlPackage.eINSTANCE.getItemUsage(), SysmlPackage.eINSTANCE.getUsage_NestedItem())).ifPresent(nodes::add); cache.getNodeDescription(descriptionNameGenerator.getBorderNodeName(SysmlPackage.eINSTANCE.getReferenceUsage())).ifPresent(nodes::add); cache.getNodeDescription(descriptionNameGenerator.getInheritedBorderNodeName(SysmlPackage.eINSTANCE.getReferenceUsage())).ifPresent(nodes::add); return nodes; diff --git a/backend/views/syson-diagram-common-view/src/main/java/org/eclipse/syson/diagram/common/view/nodes/InheritedItemUsageBorderNodeDescriptionProvider.java b/backend/views/syson-diagram-common-view/src/main/java/org/eclipse/syson/diagram/common/view/nodes/InheritedItemUsageBorderNodeDescriptionProvider.java new file mode 100644 index 0000000000..077495c98d --- /dev/null +++ b/backend/views/syson-diagram-common-view/src/main/java/org/eclipse/syson/diagram/common/view/nodes/InheritedItemUsageBorderNodeDescriptionProvider.java @@ -0,0 +1,78 @@ +/******************************************************************************* + * Copyright (c) 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 + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ +package org.eclipse.syson.diagram.common.view.nodes; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.emf.ecore.EReference; +import org.eclipse.sirius.components.view.builder.IViewDiagramElementFinder; +import org.eclipse.sirius.components.view.builder.providers.IColorProvider; +import org.eclipse.sirius.components.view.diagram.EdgeTool; +import org.eclipse.sirius.components.view.diagram.NodeDescription; +import org.eclipse.sirius.components.view.diagram.NodePalette; +import org.eclipse.sirius.components.view.diagram.OutsideLabelDescription; +import org.eclipse.sirius.components.view.diagram.OutsideLabelPosition; +import org.eclipse.syson.diagram.services.aql.DiagramQueryAQLService; +import org.eclipse.syson.sysml.SysmlPackage; +import org.eclipse.syson.util.AQLConstants; +import org.eclipse.syson.util.AQLUtils; +import org.eclipse.syson.util.IDescriptionNameGenerator; +import org.eclipse.syson.util.ServiceMethod; + +/** + * Used to create the inherited item usage border node description. + * + * @author gcoutable + */ +public class InheritedItemUsageBorderNodeDescriptionProvider extends AbstractItemUsageBorderNodeDescriptionProvider { + + public InheritedItemUsageBorderNodeDescriptionProvider(EReference eReference, IColorProvider colorProvider, IDescriptionNameGenerator descriptionNameGenerator) { + super(eReference, colorProvider, descriptionNameGenerator); + } + + @Override + protected String getSemanticCandidatesExpression() { + return ServiceMethod.of1(DiagramQueryAQLService::getInheritedCompartmentItems).aqlSelf(AQLUtils.aqlString(this.eReference.getName())); + } + + @Override + protected String getName() { + return this.descriptionNameGenerator.getInheritedBorderNodeName(SysmlPackage.eINSTANCE.getItemUsage(), this.eReference); + } + + @Override + protected OutsideLabelDescription createOutsideLabelDescription() { + return this.diagramBuilderHelper.newOutsideLabelDescription() + .labelExpression(AQLConstants.AQL + "'^' + self.getBorderNodeUsageLabel()") + .position(OutsideLabelPosition.BOTTOM_CENTER) + .style(this.createOutsideLabelStyle()) + .build(); + } + + @Override + protected List getEdgeTools(IViewDiagramElementFinder cache, NodeDescription nodeDescription) { + List edgeTools = new ArrayList<>(); + edgeTools.add(this.createBindingConnectorAsUsageEdgeTool(cache)); + edgeTools.add(this.createFlowUsageEdgeTool(cache)); + return edgeTools; + } + + @Override + protected NodePalette createNodePalette(IViewDiagramElementFinder cache, NodeDescription nodeDescription) { + return this.diagramBuilderHelper.newNodePalette() + .toolSections(this.defaultToolsFactory.createDefaultHideRevealNodeToolSection()) + .edgeTools(this.getEdgeTools(cache, nodeDescription).toArray(EdgeTool[]::new)) + .build(); + } +} diff --git a/backend/views/syson-diagram-common-view/src/main/java/org/eclipse/syson/diagram/common/view/nodes/ItemUsageBorderNodeDescriptionProvider.java b/backend/views/syson-diagram-common-view/src/main/java/org/eclipse/syson/diagram/common/view/nodes/ItemUsageBorderNodeDescriptionProvider.java index f16f84f1fd..87caf524f7 100644 --- a/backend/views/syson-diagram-common-view/src/main/java/org/eclipse/syson/diagram/common/view/nodes/ItemUsageBorderNodeDescriptionProvider.java +++ b/backend/views/syson-diagram-common-view/src/main/java/org/eclipse/syson/diagram/common/view/nodes/ItemUsageBorderNodeDescriptionProvider.java @@ -14,96 +14,47 @@ import java.util.ArrayList; import java.util.List; -import java.util.Objects; import org.eclipse.emf.ecore.EReference; import org.eclipse.sirius.components.view.builder.IViewDiagramElementFinder; import org.eclipse.sirius.components.view.builder.providers.IColorProvider; -import org.eclipse.sirius.components.view.diagram.ConditionalNodeStyle; -import org.eclipse.sirius.components.view.diagram.DiagramDescription; import org.eclipse.sirius.components.view.diagram.EdgeTool; import org.eclipse.sirius.components.view.diagram.NodeDescription; import org.eclipse.sirius.components.view.diagram.NodePalette; -import org.eclipse.sirius.components.view.diagram.NodeStyleDescription; import org.eclipse.sirius.components.view.diagram.OutsideLabelDescription; import org.eclipse.sirius.components.view.diagram.OutsideLabelPosition; -import org.eclipse.sirius.components.view.diagram.OutsideLabelStyle; -import org.eclipse.sirius.components.view.diagram.SynchronizationPolicy; -import org.eclipse.sirius.components.view.diagram.UserResizableDirection; -import org.eclipse.syson.diagram.common.view.services.ViewEdgeToolService; import org.eclipse.syson.diagram.services.aql.DiagramMutationAQLService; import org.eclipse.syson.diagram.services.aql.DiagramQueryAQLService; import org.eclipse.syson.services.DeleteService; -import org.eclipse.syson.services.UtilService; import org.eclipse.syson.sysml.SysmlPackage; import org.eclipse.syson.util.AQLConstants; import org.eclipse.syson.util.IDescriptionNameGenerator; import org.eclipse.syson.util.ServiceMethod; import org.eclipse.syson.util.SysMLMetamodelHelper; -import org.eclipse.syson.util.ViewConstants; /** * Used to create the item usage border node description. * * @author arthur daussy */ -public class ItemUsageBorderNodeDescriptionProvider extends AbstractNodeDescriptionProvider { - - private final IDescriptionNameGenerator descriptionNameGenerator; - - private final EReference eReference; +public class ItemUsageBorderNodeDescriptionProvider extends AbstractItemUsageBorderNodeDescriptionProvider { public ItemUsageBorderNodeDescriptionProvider(EReference eReference, IColorProvider colorProvider, IDescriptionNameGenerator descriptionNameGenerator) { - super(colorProvider); - this.eReference = Objects.requireNonNull(eReference); - this.descriptionNameGenerator = Objects.requireNonNull(descriptionNameGenerator); - } - - private List getBindingConnectorAsUsageToolTarget(IViewDiagramElementFinder cache) { - var nodeDescriptions = new ArrayList(); - cache.getNodeDescription(this.getName()).ifPresent(nodeDescriptions::add); - cache.getNodeDescription(this.getDescriptionNameGenerator().getBorderNodeName(SysmlPackage.eINSTANCE.getItemUsage(), this.eReference)).ifPresent(nodeDescriptions::add); - return nodeDescriptions; + super(eReference, colorProvider, descriptionNameGenerator); } - private String getSemanticCandidatesExpression() { + @Override + protected String getSemanticCandidatesExpression() { var itemUsage = SysMLMetamodelHelper.buildQualifiedName(SysmlPackage.eINSTANCE.getItemUsage()); return AQLConstants.AQL_SELF + "." + this.eReference.getName() + "->select(e | e.oclIsTypeOf(" + itemUsage + "))"; } - private String getName() { + @Override + protected String getName() { return this.descriptionNameGenerator.getBorderNodeName(SysmlPackage.eINSTANCE.getItemUsage(), this.eReference); } @Override - public NodeDescription create() { - String domainType = SysMLMetamodelHelper.buildQualifiedName(SysmlPackage.eINSTANCE.getItemUsage()); - return this.diagramBuilderHelper.newNodeDescription() - .defaultHeightExpression("10") - .defaultWidthExpression("10") - .domainType(domainType) - .outsideLabels(this.createOutsideLabelDescription()) - .name(this.getName()) - .semanticCandidatesExpression(this.getSemanticCandidatesExpression()) - .style(this.createItemUnsetNodeStyle()) - .conditionalStyles(this.createItemUsageConditionalNodeStyles().toArray(ConditionalNodeStyle[]::new)) - .userResizable(UserResizableDirection.NONE) - .synchronizationPolicy(SynchronizationPolicy.SYNCHRONIZED) - .build(); - } - - protected IDescriptionNameGenerator getDescriptionNameGenerator() { - return this.descriptionNameGenerator; - } - - private NodeStyleDescription createItemUnsetNodeStyle() { - return this.diagramBuilderHelper.newRectangularNodeStyleDescription() - .borderColor(this.colorProvider.getColor(ViewConstants.DEFAULT_BORDER_COLOR)) - .borderRadius(0) - .background(this.colorProvider.getColor(ViewConstants.DEFAULT_BACKGROUND_COLOR)) - .build(); - } - protected OutsideLabelDescription createOutsideLabelDescription() { return this.diagramBuilderHelper.newOutsideLabelDescription() .labelExpression(ServiceMethod.of0(DiagramQueryAQLService::getBorderNodeUsageLabel).aqlSelf()) @@ -112,45 +63,16 @@ protected OutsideLabelDescription createOutsideLabelDescription() { .build(); } - private OutsideLabelStyle createOutsideLabelStyle() { - return this.diagramBuilderHelper.newOutsideLabelStyle() - .bold(false) - .borderSize(0) - .fontSize(12) - .italic(false) - .labelColor(this.colorProvider.getColor(ViewConstants.DEFAULT_LABEL_COLOR)) - .showIconExpression(AQLConstants.AQL_FALSE) - .strikeThrough(false) - .underline(false) - .build(); - } - - private List createItemUsageConditionalNodeStyles() { - var borderColor = this.colorProvider.getColor(ViewConstants.DEFAULT_BORDER_COLOR); - return List.of( - this.diagramBuilderHelper.newConditionalNodeStyle() - .condition(ServiceMethod.of0(UtilService::isInFeature).aqlSelf()) - .style(this.createImageNodeStyleDescription("/images/feature_in.svg", borderColor, true)) - .build(), - this.diagramBuilderHelper.newConditionalNodeStyle() - .condition(ServiceMethod.of0(UtilService::isOutFeature).aqlSelf()) - .style(this.createImageNodeStyleDescription("/images/feature_out.svg", borderColor, true)) - .build(), - this.diagramBuilderHelper.newConditionalNodeStyle() - .condition(ServiceMethod.of0(UtilService::isInOutFeature).aqlSelf()) - .style(this.createImageNodeStyleDescription("/images/feature_inout.svg", borderColor, true)) - .build()); - } - @Override - public void link(DiagramDescription diagramDescription, IViewDiagramElementFinder cache) { - var optItemUsageBorderNodeDescription = cache.getNodeDescription(this.getName()); - - NodeDescription nodeDescription = optItemUsageBorderNodeDescription.get(); - nodeDescription.setPalette(this.createNodePalette(cache, nodeDescription)); + protected List getEdgeTools(IViewDiagramElementFinder cache, NodeDescription nodeDescription) { + List edgeTools = new ArrayList<>(); + edgeTools.add(this.createBindingConnectorAsUsageEdgeTool(cache)); + edgeTools.add(this.createFlowUsageEdgeTool(cache)); + return edgeTools; } - private NodePalette createNodePalette(IViewDiagramElementFinder cache, NodeDescription nodeDescription) { + @Override + protected NodePalette createNodePalette(IViewDiagramElementFinder cache, NodeDescription nodeDescription) { var changeContext = this.viewBuilderHelper.newChangeContext() .expression(ServiceMethod.of0(DeleteService::deleteFromModel).aqlSelf()); @@ -170,23 +92,8 @@ private NodePalette createNodePalette(IViewDiagramElementFinder cache, NodeDescr .deleteTool(deleteTool.build()) .labelEditTool(editTool.build()) .toolSections(this.defaultToolsFactory.createDefaultHideRevealNodeToolSection()) - .edgeTools( - this.createBindingConnectorAsUsageEdgeTool(cache), - this.createFlowUsageEdgeTool(cache)) + .edgeTools(this.getEdgeTools(cache, nodeDescription).toArray(EdgeTool[]::new)) .quickAccessTools(this.getDuplicateElementAndNodeTool()) .build(); } - - private EdgeTool createBindingConnectorAsUsageEdgeTool(IViewDiagramElementFinder cache) { - return this.getViewEdgeToolService(cache).createBindingConnectorAsUsageEdgeTool(this.getBindingConnectorAsUsageToolTarget(cache)); - } - - protected EdgeTool createFlowUsageEdgeTool(IViewDiagramElementFinder cache) { - return this.getViewEdgeToolService(cache).createFlowUsageEdgeTool(this.getFlowUsageToolTargetDescriptions(cache, this.descriptionNameGenerator)); - } - - protected ViewEdgeToolService getViewEdgeToolService(IViewDiagramElementFinder cache) { - return new ViewEdgeToolService(this.viewBuilderHelper, this.diagramBuilderHelper, cache.getNodeDescriptions(), this.descriptionNameGenerator); - } - } diff --git a/backend/views/syson-standard-diagrams-view/src/main/java/org/eclipse/syson/standard/diagrams/view/SDVDiagramDescriptionProvider.java b/backend/views/syson-standard-diagrams-view/src/main/java/org/eclipse/syson/standard/diagrams/view/SDVDiagramDescriptionProvider.java index dd8bcad3db..3a5568bafd 100644 --- a/backend/views/syson-standard-diagrams-view/src/main/java/org/eclipse/syson/standard/diagrams/view/SDVDiagramDescriptionProvider.java +++ b/backend/views/syson-standard-diagrams-view/src/main/java/org/eclipse/syson/standard/diagrams/view/SDVDiagramDescriptionProvider.java @@ -59,6 +59,7 @@ import org.eclipse.syson.diagram.common.view.nodes.FramedConcernCompartmentNodeDescription; import org.eclipse.syson.diagram.common.view.nodes.ImportedPackageNodeDescriptionProvider; import org.eclipse.syson.diagram.common.view.nodes.InheritedCompartmentItemNodeDescriptionProvider; +import org.eclipse.syson.diagram.common.view.nodes.InheritedItemUsageBorderNodeDescriptionProvider; import org.eclipse.syson.diagram.common.view.nodes.InterconnectionCompartmentNodeDescriptionProvider; import org.eclipse.syson.diagram.common.view.nodes.ItemUsageBorderNodeDescriptionProvider; import org.eclipse.syson.diagram.common.view.nodes.JoinActionNodeDescriptionProvider; @@ -495,6 +496,8 @@ private List> createDiagramElementDescript .add(new InheritedPortUsageBorderNodeDescriptionProvider(SysmlPackage.eINSTANCE.getDefinition_OwnedPort(), colorProvider, this.getDescriptionNameGenerator())); diagramElementDescriptionProviders.add(new ItemUsageBorderNodeDescriptionProvider(SysmlPackage.eINSTANCE.getDefinition_OwnedItem(), colorProvider, this.getDescriptionNameGenerator())); diagramElementDescriptionProviders.add(new ItemUsageBorderNodeDescriptionProvider(SysmlPackage.eINSTANCE.getUsage_NestedItem(), colorProvider, this.getDescriptionNameGenerator())); + diagramElementDescriptionProviders.add(new InheritedItemUsageBorderNodeDescriptionProvider(SysmlPackage.eINSTANCE.getDefinition_OwnedItem(), colorProvider, this.getDescriptionNameGenerator())); + diagramElementDescriptionProviders.add(new InheritedItemUsageBorderNodeDescriptionProvider(SysmlPackage.eINSTANCE.getUsage_NestedItem(), colorProvider, this.getDescriptionNameGenerator())); diagramElementDescriptionProviders.add(new ReferenceUsageBorderNodeDescriptionProvider(colorProvider, this.getDescriptionNameGenerator())); diagramElementDescriptionProviders.add(new InheritedReferenceUsageBorderNodeDescriptionProvider(colorProvider, this.getDescriptionNameGenerator())); diff --git a/backend/views/syson-standard-diagrams-view/src/main/java/org/eclipse/syson/standard/diagrams/view/edges/BindingConnectorAsUsageEdgeDescriptionProvider.java b/backend/views/syson-standard-diagrams-view/src/main/java/org/eclipse/syson/standard/diagrams/view/edges/BindingConnectorAsUsageEdgeDescriptionProvider.java index fbe9e74fbc..3edc908f31 100644 --- a/backend/views/syson-standard-diagrams-view/src/main/java/org/eclipse/syson/standard/diagrams/view/edges/BindingConnectorAsUsageEdgeDescriptionProvider.java +++ b/backend/views/syson-standard-diagrams-view/src/main/java/org/eclipse/syson/standard/diagrams/view/edges/BindingConnectorAsUsageEdgeDescriptionProvider.java @@ -54,6 +54,8 @@ protected List getSourceNodes(IViewDiagramElementFinder cache) cache.getNodeDescription(this.descriptionNameGenerator.getBorderNodeName(SysmlPackage.eINSTANCE.getPortUsage(), SysmlPackage.eINSTANCE.getDefinition_OwnedPort())).ifPresent(nodes::add); cache.getNodeDescription(this.descriptionNameGenerator.getBorderNodeName(SysmlPackage.eINSTANCE.getItemUsage(), SysmlPackage.eINSTANCE.getDefinition_OwnedItem())).ifPresent(nodes::add); cache.getNodeDescription(this.descriptionNameGenerator.getBorderNodeName(SysmlPackage.eINSTANCE.getItemUsage(), SysmlPackage.eINSTANCE.getUsage_NestedItem())).ifPresent(nodes::add); + cache.getNodeDescription(this.descriptionNameGenerator.getInheritedBorderNodeName(SysmlPackage.eINSTANCE.getItemUsage(), SysmlPackage.eINSTANCE.getDefinition_OwnedItem())).ifPresent(nodes::add); + cache.getNodeDescription(this.descriptionNameGenerator.getInheritedBorderNodeName(SysmlPackage.eINSTANCE.getItemUsage(), SysmlPackage.eINSTANCE.getUsage_NestedItem())).ifPresent(nodes::add); cache.getNodeDescription(this.descriptionNameGenerator.getInheritedBorderNodeName(SysmlPackage.eINSTANCE.getPortUsage(), SysmlPackage.eINSTANCE.getUsage_NestedPort())).ifPresent(nodes::add); cache.getNodeDescription(this.descriptionNameGenerator.getInheritedBorderNodeName(SysmlPackage.eINSTANCE.getPortUsage(), SysmlPackage.eINSTANCE.getDefinition_OwnedPort())) .ifPresent(nodes::add); diff --git a/backend/views/syson-standard-diagrams-view/src/main/java/org/eclipse/syson/standard/diagrams/view/edges/FeatureValueEdgeDescriptionProvider.java b/backend/views/syson-standard-diagrams-view/src/main/java/org/eclipse/syson/standard/diagrams/view/edges/FeatureValueEdgeDescriptionProvider.java index 542147f689..d4927d6e87 100644 --- a/backend/views/syson-standard-diagrams-view/src/main/java/org/eclipse/syson/standard/diagrams/view/edges/FeatureValueEdgeDescriptionProvider.java +++ b/backend/views/syson-standard-diagrams-view/src/main/java/org/eclipse/syson/standard/diagrams/view/edges/FeatureValueEdgeDescriptionProvider.java @@ -52,6 +52,8 @@ protected List getSourceNodes(IViewDiagramElementFinder cache) List nodes = new ArrayList<>(); cache.getNodeDescription(this.descriptionNameGenerator.getBorderNodeName(SysmlPackage.eINSTANCE.getItemUsage(), SysmlPackage.eINSTANCE.getDefinition_OwnedItem())).ifPresent(nodes::add); cache.getNodeDescription(this.descriptionNameGenerator.getBorderNodeName(SysmlPackage.eINSTANCE.getItemUsage(), SysmlPackage.eINSTANCE.getUsage_NestedItem())).ifPresent(nodes::add); + cache.getNodeDescription(this.descriptionNameGenerator.getInheritedBorderNodeName(SysmlPackage.eINSTANCE.getItemUsage(), SysmlPackage.eINSTANCE.getDefinition_OwnedItem())).ifPresent(nodes::add); + cache.getNodeDescription(this.descriptionNameGenerator.getInheritedBorderNodeName(SysmlPackage.eINSTANCE.getItemUsage(), SysmlPackage.eINSTANCE.getUsage_NestedItem())).ifPresent(nodes::add); cache.getNodeDescription(this.descriptionNameGenerator.getBorderNodeName(SysmlPackage.eINSTANCE.getPortUsage(), SysmlPackage.eINSTANCE.getUsage_NestedPort())).ifPresent(nodes::add); cache.getNodeDescription(this.descriptionNameGenerator.getBorderNodeName(SysmlPackage.eINSTANCE.getPortUsage(), SysmlPackage.eINSTANCE.getDefinition_OwnedPort())).ifPresent(nodes::add); cache.getNodeDescription(this.descriptionNameGenerator.getInheritedBorderNodeName(SysmlPackage.eINSTANCE.getPortUsage(), SysmlPackage.eINSTANCE.getUsage_NestedPort())).ifPresent(nodes::add); diff --git a/backend/views/syson-standard-diagrams-view/src/main/java/org/eclipse/syson/standard/diagrams/view/edges/FlowUsageEdgeDescriptionProvider.java b/backend/views/syson-standard-diagrams-view/src/main/java/org/eclipse/syson/standard/diagrams/view/edges/FlowUsageEdgeDescriptionProvider.java index 1088ab6f64..3fb7e3e5e0 100644 --- a/backend/views/syson-standard-diagrams-view/src/main/java/org/eclipse/syson/standard/diagrams/view/edges/FlowUsageEdgeDescriptionProvider.java +++ b/backend/views/syson-standard-diagrams-view/src/main/java/org/eclipse/syson/standard/diagrams/view/edges/FlowUsageEdgeDescriptionProvider.java @@ -57,6 +57,8 @@ protected List getSourceNodes(IViewDiagramElementFinder cache) .ifPresent(nodes::add); cache.getNodeDescription(this.descriptionNameGenerator.getBorderNodeName(SysmlPackage.eINSTANCE.getItemUsage(), SysmlPackage.eINSTANCE.getDefinition_OwnedItem())).ifPresent(nodes::add); cache.getNodeDescription(this.descriptionNameGenerator.getBorderNodeName(SysmlPackage.eINSTANCE.getItemUsage(), SysmlPackage.eINSTANCE.getUsage_NestedItem())).ifPresent(nodes::add); + cache.getNodeDescription(this.descriptionNameGenerator.getInheritedBorderNodeName(SysmlPackage.eINSTANCE.getItemUsage(), SysmlPackage.eINSTANCE.getDefinition_OwnedItem())).ifPresent(nodes::add); + cache.getNodeDescription(this.descriptionNameGenerator.getInheritedBorderNodeName(SysmlPackage.eINSTANCE.getItemUsage(), SysmlPackage.eINSTANCE.getUsage_NestedItem())).ifPresent(nodes::add); cache.getNodeDescription(this.descriptionNameGenerator.getBorderNodeName(SysmlPackage.eINSTANCE.getReferenceUsage())).ifPresent(nodes::add); cache.getNodeDescription(this.descriptionNameGenerator.getInheritedBorderNodeName(SysmlPackage.eINSTANCE.getReferenceUsage())).ifPresent(nodes::add); return nodes; diff --git a/backend/views/syson-standard-diagrams-view/src/main/java/org/eclipse/syson/standard/diagrams/view/nodes/DefinitionNodeDescriptionProvider.java b/backend/views/syson-standard-diagrams-view/src/main/java/org/eclipse/syson/standard/diagrams/view/nodes/DefinitionNodeDescriptionProvider.java index b31dffc7d6..799af72e2c 100644 --- a/backend/views/syson-standard-diagrams-view/src/main/java/org/eclipse/syson/standard/diagrams/view/nodes/DefinitionNodeDescriptionProvider.java +++ b/backend/views/syson-standard-diagrams-view/src/main/java/org/eclipse/syson/standard/diagrams/view/nodes/DefinitionNodeDescriptionProvider.java @@ -79,6 +79,7 @@ protected Set getReusedBorderNodes(IViewDiagramElementFinder ca }); if (SysmlPackage.eINSTANCE.getActionDefinition().equals(this.eClass)) { cache.getNodeDescription(this.getDescriptionNameGenerator().getBorderNodeName(SysmlPackage.eINSTANCE.getItemUsage(), SysmlPackage.eINSTANCE.getDefinition_OwnedItem())).ifPresent(borderNodes::add); + cache.getNodeDescription(this.getDescriptionNameGenerator().getInheritedBorderNodeName(SysmlPackage.eINSTANCE.getItemUsage(), SysmlPackage.eINSTANCE.getDefinition_OwnedItem())).ifPresent(borderNodes::add); cache.getNodeDescription(this.getDescriptionNameGenerator().getBorderNodeName(SysmlPackage.eINSTANCE.getReferenceUsage())).ifPresent(borderNodes::add); cache.getNodeDescription(this.getDescriptionNameGenerator().getInheritedBorderNodeName(SysmlPackage.eINSTANCE.getReferenceUsage())).ifPresent(borderNodes::add); } else if (SysmlPackage.eINSTANCE.getPortDefinition().equals(this.eClass)) { diff --git a/backend/views/syson-standard-diagrams-view/src/main/java/org/eclipse/syson/standard/diagrams/view/nodes/FakeNodeDescriptionProvider.java b/backend/views/syson-standard-diagrams-view/src/main/java/org/eclipse/syson/standard/diagrams/view/nodes/FakeNodeDescriptionProvider.java index a13ab9689e..a83916e686 100644 --- a/backend/views/syson-standard-diagrams-view/src/main/java/org/eclipse/syson/standard/diagrams/view/nodes/FakeNodeDescriptionProvider.java +++ b/backend/views/syson-standard-diagrams-view/src/main/java/org/eclipse/syson/standard/diagrams/view/nodes/FakeNodeDescriptionProvider.java @@ -225,5 +225,9 @@ private void addReusableBorderedNode(IViewDiagramElementFinder cache, IDescripti .ifPresent(childrenNodes::add); cache.getNodeDescription(this.descriptionNameGenerator.getBorderNodeName(SysmlPackage.eINSTANCE.getItemUsage(), SysmlPackage.eINSTANCE.getUsage_NestedItem())) .ifPresent(childrenNodes::add); + cache.getNodeDescription(this.descriptionNameGenerator.getInheritedBorderNodeName(SysmlPackage.eINSTANCE.getItemUsage(), SysmlPackage.eINSTANCE.getDefinition_OwnedItem())) + .ifPresent(childrenNodes::add); + cache.getNodeDescription(this.descriptionNameGenerator.getInheritedBorderNodeName(SysmlPackage.eINSTANCE.getItemUsage(), SysmlPackage.eINSTANCE.getUsage_NestedItem())) + .ifPresent(childrenNodes::add); } } diff --git a/backend/views/syson-standard-diagrams-view/src/main/java/org/eclipse/syson/standard/diagrams/view/nodes/UsageNodeDescriptionProvider.java b/backend/views/syson-standard-diagrams-view/src/main/java/org/eclipse/syson/standard/diagrams/view/nodes/UsageNodeDescriptionProvider.java index 245482bd81..edafcb388e 100644 --- a/backend/views/syson-standard-diagrams-view/src/main/java/org/eclipse/syson/standard/diagrams/view/nodes/UsageNodeDescriptionProvider.java +++ b/backend/views/syson-standard-diagrams-view/src/main/java/org/eclipse/syson/standard/diagrams/view/nodes/UsageNodeDescriptionProvider.java @@ -116,6 +116,7 @@ protected Set getReusedBorderNodes(IViewDiagramElementFinder ca }); if (SysmlPackage.eINSTANCE.getActionUsage().equals(this.eClass)) { cache.getNodeDescription(this.getDescriptionNameGenerator().getBorderNodeName(SysmlPackage.eINSTANCE.getItemUsage(), SysmlPackage.eINSTANCE.getUsage_NestedItem())).ifPresent(borderNodes::add); + cache.getNodeDescription(this.getDescriptionNameGenerator().getInheritedBorderNodeName(SysmlPackage.eINSTANCE.getItemUsage(), SysmlPackage.eINSTANCE.getUsage_NestedItem())).ifPresent(borderNodes::add); cache.getNodeDescription(this.getDescriptionNameGenerator().getBorderNodeName(SysmlPackage.eINSTANCE.getReferenceUsage())).ifPresent(borderNodes::add); cache.getNodeDescription(this.getDescriptionNameGenerator().getInheritedBorderNodeName(SysmlPackage.eINSTANCE.getReferenceUsage())).ifPresent(borderNodes::add); } else if (SysmlPackage.eINSTANCE.getPortUsage().equals(this.eClass)) { diff --git a/doc/content/modules/user-manual/assets/images/release-notes-action-inherited-item-border-nodes.png b/doc/content/modules/user-manual/assets/images/release-notes-action-inherited-item-border-nodes.png new file mode 100644 index 0000000000..b152327db2 Binary files /dev/null and b/doc/content/modules/user-manual/assets/images/release-notes-action-inherited-item-border-nodes.png differ diff --git a/doc/content/modules/user-manual/pages/release-notes/2026.9.0.adoc b/doc/content/modules/user-manual/pages/release-notes/2026.9.0.adoc index c20e93cd39..818205c889 100644 --- a/doc/content/modules/user-manual/pages/release-notes/2026.9.0.adoc +++ b/doc/content/modules/user-manual/pages/release-notes/2026.9.0.adoc @@ -73,7 +73,9 @@ Once both requirements are displayed in a _General View_ diagram, by dropping th The direction of the edge is given by the `#original` and `#derive` metadata of its ends, so it does not depend on the order in which those ends are declared. ** On `ActionUsage` and `ActionDefinition` graphical nodes with the _items_ compartment collapsed, when an `ItemUsage` without direction is created, represents the `ItemUsage` with a border node instead of an `ItemUsage` graphical node linked by composition. So now, on `ActionDefinition` and `ActionUsage` creating and displaying `ItemUsage` graphical nodes with and without direction behaves identically. - +** Add support for the inheritance of `ItemUsage` border nodes on `ActionDefinition` and `ActionUsage` graphical nodes. ++ +image::release-notes-action-inherited-item-border-nodes.png[ItemUsage border node inheritance on ActionDefinition and ActionUsage] == Bug fixes