diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index 09b1e394f..b0d80dda0 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -29,6 +29,7 @@ - https://github.com/eclipse-syson/syson/issues/274[#274] [import] Namespace.getImportedMemberships method now prevents name collisions - https://github.com/eclipse-syson/syson/issues/271[#271] [diagrams] Remove non end Usages from AllocationDefinition ends compartment - https://github.com/eclipse-syson/syson/issues/229[#229] [diagrams] Prevent circular containment of nested parts including self containment +- https://github.com/eclipse-syson/syson/issues/272[#272] [statetransition-view] Add "state transition" compartment and fix the graphical creation of actions in StateDefinition and StateUsage === Improvements diff --git a/backend/views/syson-diagram-statetransition-view/src/main/java/org/eclipse/syson/diagram/statetransition/view/StateTransitionViewDiagramDescriptionProvider.java b/backend/views/syson-diagram-statetransition-view/src/main/java/org/eclipse/syson/diagram/statetransition/view/StateTransitionViewDiagramDescriptionProvider.java index dac373152..34d5384dd 100644 --- a/backend/views/syson-diagram-statetransition-view/src/main/java/org/eclipse/syson/diagram/statetransition/view/StateTransitionViewDiagramDescriptionProvider.java +++ b/backend/views/syson-diagram-statetransition-view/src/main/java/org/eclipse/syson/diagram/statetransition/view/StateTransitionViewDiagramDescriptionProvider.java @@ -34,9 +34,10 @@ import org.eclipse.syson.diagram.common.view.tools.ToolSectionDescription; import org.eclipse.syson.diagram.statetransition.view.edges.TransitionEdgeDescriptionProvider; import org.eclipse.syson.diagram.statetransition.view.nodes.CompartmentNodeDescriptionProvider; -import org.eclipse.syson.diagram.statetransition.view.nodes.CompositeStateDefinitionNodeDescriptionProvider; +import org.eclipse.syson.diagram.statetransition.view.nodes.DefinitionNodeDescriptionProvider; import org.eclipse.syson.diagram.statetransition.view.nodes.FakeNodeDescriptionProvider; import org.eclipse.syson.diagram.statetransition.view.nodes.PackageNodeDescriptionProvider; +import org.eclipse.syson.diagram.statetransition.view.nodes.StateTransitionCompartmentNodeDescriptionProvider; import org.eclipse.syson.diagram.statetransition.view.nodes.StateTransitionViewEmptyDiagramNodeDescriptionProvider; import org.eclipse.syson.diagram.statetransition.view.nodes.UsageNodeDescriptionProvider; import org.eclipse.syson.sysml.SysmlPackage; @@ -95,9 +96,13 @@ public RepresentationDescription create(IColorProvider colorProvider) { diagramElementDescriptionProviders.add(new StateTransitionViewEmptyDiagramNodeDescriptionProvider(colorProvider)); diagramElementDescriptionProviders.add(new PackageNodeDescriptionProvider(colorProvider)); diagramElementDescriptionProviders.add(new TransitionEdgeDescriptionProvider(colorProvider)); + diagramElementDescriptionProviders + .add(new StateTransitionCompartmentNodeDescriptionProvider(SysmlPackage.eINSTANCE.getStateDefinition(), SysmlPackage.eINSTANCE.getDefinition_OwnedState(), colorProvider, this.nameGenerator)); + diagramElementDescriptionProviders + .add(new StateTransitionCompartmentNodeDescriptionProvider(SysmlPackage.eINSTANCE.getStateUsage(), SysmlPackage.eINSTANCE.getUsage_NestedState(), colorProvider, this.nameGenerator)); DEFINITIONS.forEach(definition -> { - diagramElementDescriptionProviders.add(new CompositeStateDefinitionNodeDescriptionProvider(definition, colorProvider)); + diagramElementDescriptionProviders.add(new DefinitionNodeDescriptionProvider(definition, colorProvider)); }); USAGES.forEach(usage -> { diff --git a/backend/views/syson-diagram-statetransition-view/src/main/java/org/eclipse/syson/diagram/statetransition/view/nodes/CompositeStateDefinitionNodeDescriptionProvider.java b/backend/views/syson-diagram-statetransition-view/src/main/java/org/eclipse/syson/diagram/statetransition/view/nodes/CompositeStateDefinitionNodeDescriptionProvider.java deleted file mode 100644 index 09c4d93d4..000000000 --- a/backend/views/syson-diagram-statetransition-view/src/main/java/org/eclipse/syson/diagram/statetransition/view/nodes/CompositeStateDefinitionNodeDescriptionProvider.java +++ /dev/null @@ -1,103 +0,0 @@ -/******************************************************************************* - * 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.syson.diagram.statetransition.view.nodes; - -import java.util.ArrayList; -import java.util.List; - -import org.eclipse.emf.ecore.EClass; -import org.eclipse.sirius.components.view.builder.IViewDiagramElementFinder; -import org.eclipse.sirius.components.view.builder.providers.IColorProvider; -import org.eclipse.sirius.components.view.diagram.NodeDescription; -import org.eclipse.sirius.components.view.diagram.NodeStyleDescription; -import org.eclipse.sirius.components.view.diagram.NodeToolSection; -import org.eclipse.sirius.components.view.diagram.SynchronizationPolicy; -import org.eclipse.syson.diagram.common.view.nodes.AbstractDefinitionNodeDescriptionProvider; -import org.eclipse.syson.diagram.statetransition.view.STVDescriptionNameGenerator; -import org.eclipse.syson.diagram.statetransition.view.StateTransitionViewDiagramDescriptionProvider; -import org.eclipse.syson.diagram.statetransition.view.services.StateTransitionViewNodeToolSectionSwitch; -import org.eclipse.syson.sysml.SysmlPackage; -import org.eclipse.syson.util.SysMLMetamodelHelper; -import org.eclipse.syson.util.ViewConstants; - -/** - * Node description provider for all SysMLv2 Composite State Usage elements in the StateTransition View diagram. - * - * @author adieumegard - */ -public class CompositeStateDefinitionNodeDescriptionProvider extends AbstractDefinitionNodeDescriptionProvider { - - public CompositeStateDefinitionNodeDescriptionProvider(EClass eClass, IColorProvider colorProvider) { - super(eClass, colorProvider, new STVDescriptionNameGenerator()); - } - - @Override - public NodeDescription create() { - String domainType = SysMLMetamodelHelper.buildQualifiedName(this.eClass); - return this.diagramBuilderHelper.newNodeDescription() - .childrenLayoutStrategy(this.diagramBuilderHelper.newFreeFormLayoutStrategyDescription().build()) - .collapsible(true) - .defaultHeightExpression(ViewConstants.DEFAULT_CONTAINER_NODE_HEIGHT) - .defaultWidthExpression(ViewConstants.DEFAULT_NODE_WIDTH) - .domainType(domainType) - .insideLabel(this.createInsideLabelDescription()) - .name(this.nameGenerator.getNodeName(this.eClass)) - .semanticCandidatesExpression("aql:self.getAllReachable(" + domainType + ")") - .style(this.createCompositeStateUsageNodeStyle()) - .userResizable(true) - .synchronizationPolicy(SynchronizationPolicy.UNSYNCHRONIZED) - .build(); - } - - private NodeStyleDescription createCompositeStateUsageNodeStyle() { - return this.diagramBuilderHelper.newRectangularNodeStyleDescription() - .borderColor(this.colorProvider.getColor(ViewConstants.DEFAULT_BORDER_COLOR)) - .borderRadius(10) - .background(this.colorProvider.getColor(ViewConstants.DEFAULT_BACKGROUND_COLOR)) - .build(); - } - - @Override - protected List getReusedChildren(IViewDiagramElementFinder cache) { - var reusedChildren = new ArrayList(); - - StateTransitionViewDiagramDescriptionProvider.DEFINITIONS.forEach(definition -> cache.getNodeDescription(this.nameGenerator.getNodeName(definition)).ifPresent(reusedChildren::add)); - StateTransitionViewDiagramDescriptionProvider.USAGES.forEach(usage -> cache.getNodeDescription(this.nameGenerator.getNodeName(usage)).ifPresent(reusedChildren::add)); - cache.getNodeDescription(this.nameGenerator.getNodeName(SysmlPackage.eINSTANCE.getTransitionUsage())).ifPresent(reusedChildren::add); - return reusedChildren; - } - - @Override - protected List getAllNodeDescriptions(IViewDiagramElementFinder cache) { - var allNodes = new ArrayList(); - - StateTransitionViewDiagramDescriptionProvider.DEFINITIONS.forEach(definition -> cache.getNodeDescription(this.nameGenerator.getNodeName(definition)).ifPresent(allNodes::add)); - StateTransitionViewDiagramDescriptionProvider.USAGES.forEach(usage -> cache.getNodeDescription(this.nameGenerator.getNodeName(usage)).ifPresent(allNodes::add)); - cache.getNodeDescription(this.nameGenerator.getNodeName(SysmlPackage.eINSTANCE.getPackage())).ifPresent(allNodes::add); - return allNodes; - } - - @Override - protected List getToolSections(NodeDescription nodeDescription, IViewDiagramElementFinder cache) { - StateTransitionViewNodeToolSectionSwitch toolSectionSwitch = new StateTransitionViewNodeToolSectionSwitch(); - toolSectionSwitch.doSwitch(this.eClass); - return toolSectionSwitch.getNodeToolSections(); - } - - @Override - protected List getDroppableNodes(IViewDiagramElementFinder cache) { - var acceptedNodeTypes = new ArrayList(); - cache.getNodeDescription(this.nameGenerator.getNodeName(SysmlPackage.eINSTANCE.getStateUsage())).ifPresent(acceptedNodeTypes::add); - return acceptedNodeTypes; - } -} diff --git a/backend/views/syson-diagram-statetransition-view/src/main/java/org/eclipse/syson/diagram/statetransition/view/nodes/DefinitionNodeDescriptionProvider.java b/backend/views/syson-diagram-statetransition-view/src/main/java/org/eclipse/syson/diagram/statetransition/view/nodes/DefinitionNodeDescriptionProvider.java new file mode 100644 index 000000000..ba8a7a517 --- /dev/null +++ b/backend/views/syson-diagram-statetransition-view/src/main/java/org/eclipse/syson/diagram/statetransition/view/nodes/DefinitionNodeDescriptionProvider.java @@ -0,0 +1,73 @@ +/******************************************************************************* + * 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.syson.diagram.statetransition.view.nodes; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.emf.ecore.EClass; +import org.eclipse.sirius.components.view.builder.IViewDiagramElementFinder; +import org.eclipse.sirius.components.view.builder.providers.IColorProvider; +import org.eclipse.sirius.components.view.diagram.NodeDescription; +import org.eclipse.sirius.components.view.diagram.NodeToolSection; +import org.eclipse.syson.diagram.common.view.nodes.AbstractDefinitionNodeDescriptionProvider; +import org.eclipse.syson.diagram.statetransition.view.STVDescriptionNameGenerator; +import org.eclipse.syson.diagram.statetransition.view.StateTransitionViewDiagramDescriptionProvider; +import org.eclipse.syson.diagram.statetransition.view.services.StateTransitionViewNodeToolSectionSwitch; +import org.eclipse.syson.sysml.SysmlPackage; + +/** + * Node description provider for all SysMLv2 Definitions elements in the State Transition View diagram. + * + * @author gdaniel + */ +public class DefinitionNodeDescriptionProvider extends AbstractDefinitionNodeDescriptionProvider { + + public DefinitionNodeDescriptionProvider(EClass eClass, IColorProvider colorProvider) { + super(eClass, colorProvider, new STVDescriptionNameGenerator()); + } + + @Override + protected List getReusedChildren(IViewDiagramElementFinder cache) { + var reusedChildren = new ArrayList(); + + StateTransitionViewDiagramDescriptionProvider.COMPARTMENTS_WITH_LIST_ITEMS.forEach((type, listItems) -> { + if (type.equals(this.eClass)) { + listItems.forEach(eReference -> { + cache.getNodeDescription(this.nameGenerator.getCompartmentName(type, eReference)).ifPresent(reusedChildren::add); + }); + } + }); + if (this.eClass.equals(SysmlPackage.eINSTANCE.getStateDefinition())) { + cache.getNodeDescription(this.nameGenerator.getFreeFormCompartmentName(this.eClass, SysmlPackage.eINSTANCE.getDefinition_OwnedState())).ifPresent(reusedChildren::add); + } + return reusedChildren; + } + + @Override + protected List getAllNodeDescriptions(IViewDiagramElementFinder cache) { + var allNodes = new ArrayList(); + + StateTransitionViewDiagramDescriptionProvider.DEFINITIONS.forEach(definition -> cache.getNodeDescription(this.nameGenerator.getNodeName(definition)).ifPresent(allNodes::add)); + StateTransitionViewDiagramDescriptionProvider.USAGES.forEach(usage -> cache.getNodeDescription(this.nameGenerator.getNodeName(usage)).ifPresent(allNodes::add)); + cache.getNodeDescription(this.nameGenerator.getNodeName(SysmlPackage.eINSTANCE.getPackage())).ifPresent(allNodes::add); + return allNodes; + } + + @Override + protected List getToolSections(NodeDescription nodeDescription, IViewDiagramElementFinder cache) { + StateTransitionViewNodeToolSectionSwitch toolSectionSwitch = new StateTransitionViewNodeToolSectionSwitch(); + toolSectionSwitch.doSwitch(this.eClass); + return toolSectionSwitch.getNodeToolSections(); + } +} diff --git a/backend/views/syson-diagram-statetransition-view/src/main/java/org/eclipse/syson/diagram/statetransition/view/nodes/FakeNodeDescriptionProvider.java b/backend/views/syson-diagram-statetransition-view/src/main/java/org/eclipse/syson/diagram/statetransition/view/nodes/FakeNodeDescriptionProvider.java index a9628261b..2bd2b109d 100644 --- a/backend/views/syson-diagram-statetransition-view/src/main/java/org/eclipse/syson/diagram/statetransition/view/nodes/FakeNodeDescriptionProvider.java +++ b/backend/views/syson-diagram-statetransition-view/src/main/java/org/eclipse/syson/diagram/statetransition/view/nodes/FakeNodeDescriptionProvider.java @@ -21,6 +21,7 @@ import org.eclipse.syson.diagram.common.view.nodes.AbstractFakeNodeDescriptionProvider; import org.eclipse.syson.diagram.statetransition.view.STVDescriptionNameGenerator; import org.eclipse.syson.diagram.statetransition.view.StateTransitionViewDiagramDescriptionProvider; +import org.eclipse.syson.sysml.SysmlPackage; /** * Fake Node Description allowing to store other Node Descriptions that will be reused by other Node Descriptions. @@ -47,6 +48,11 @@ protected List getChildrenDescription(IViewDiagramElementFinder StateTransitionViewDiagramDescriptionProvider.COMPARTMENTS_WITH_LIST_ITEMS.forEach((type, listItems) -> { listItems.forEach(eReference -> cache.getNodeDescription(nameGenerator.getCompartmentName(type, eReference)).ifPresent(childrenNodes::add)); }); + + // don't forget to add custom compartments + cache.getNodeDescription(nameGenerator.getFreeFormCompartmentName(SysmlPackage.eINSTANCE.getStateDefinition(), SysmlPackage.eINSTANCE.getDefinition_OwnedState())) + .ifPresent(childrenNodes::add); + cache.getNodeDescription(nameGenerator.getFreeFormCompartmentName(SysmlPackage.eINSTANCE.getStateUsage(), SysmlPackage.eINSTANCE.getUsage_NestedState())).ifPresent(childrenNodes::add); return childrenNodes; } } diff --git a/backend/views/syson-diagram-statetransition-view/src/main/java/org/eclipse/syson/diagram/statetransition/view/nodes/StateTransitionCompartmentNodeDescriptionProvider.java b/backend/views/syson-diagram-statetransition-view/src/main/java/org/eclipse/syson/diagram/statetransition/view/nodes/StateTransitionCompartmentNodeDescriptionProvider.java new file mode 100644 index 000000000..b6a080bff --- /dev/null +++ b/backend/views/syson-diagram-statetransition-view/src/main/java/org/eclipse/syson/diagram/statetransition/view/nodes/StateTransitionCompartmentNodeDescriptionProvider.java @@ -0,0 +1,117 @@ +/******************************************************************************* + * 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.syson.diagram.statetransition.view.nodes; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.emf.ecore.EClass; +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.DiagramDescription; +import org.eclipse.sirius.components.view.diagram.InsideLabelDescription; +import org.eclipse.sirius.components.view.diagram.InsideLabelPosition; +import org.eclipse.sirius.components.view.diagram.InsideLabelStyle; +import org.eclipse.sirius.components.view.diagram.NodeDescription; +import org.eclipse.sirius.components.view.diagram.NodePalette; +import org.eclipse.sirius.components.view.diagram.SynchronizationPolicy; +import org.eclipse.syson.diagram.common.view.nodes.AbstractCompartmentNodeDescriptionProvider; +import org.eclipse.syson.diagram.statetransition.view.tools.StateTransitionCompartmentNodeToolProvider; +import org.eclipse.syson.sysml.SysmlPackage; +import org.eclipse.syson.util.AQLConstants; +import org.eclipse.syson.util.IDescriptionNameGenerator; +import org.eclipse.syson.util.SysMLMetamodelHelper; +import org.eclipse.syson.util.ViewConstants; + +/** + * Used to create the 'state transition' free form compartment that contains nested/owned states. + * + * @author gdaniel + */ +public class StateTransitionCompartmentNodeDescriptionProvider extends AbstractCompartmentNodeDescriptionProvider { + + public static final String STATE_COMPARTMENT_NAME = "state transition"; + + private final String name; + + public StateTransitionCompartmentNodeDescriptionProvider(EClass eClass, EReference eReference, IColorProvider colorProvider, IDescriptionNameGenerator nameGenerator) { + super(eClass, eReference, colorProvider, nameGenerator); + this.name = nameGenerator.getFreeFormCompartmentName(this.eClass, this.eReference); + } + + @Override + public NodeDescription create() { + return this.diagramBuilderHelper.newNodeDescription() + .childrenLayoutStrategy(this.diagramBuilderHelper.newFreeFormLayoutStrategyDescription().build()) + .defaultHeightExpression("150") + .defaultWidthExpression(ViewConstants.DEFAULT_NODE_WIDTH) + .domainType(SysMLMetamodelHelper.buildQualifiedName(SysmlPackage.eINSTANCE.getElement())) + .insideLabel(this.createInsideLabelDescription()) + .isHiddenByDefaultExpression("aql:true") + .name(this.name) + .semanticCandidatesExpression(AQLConstants.AQL_SELF) + .style(this.createCompartmentNodeStyle()) + .userResizable(false) + .synchronizationPolicy(SynchronizationPolicy.SYNCHRONIZED) + .build(); + } + + @Override + public void link(DiagramDescription diagramDescription, IViewDiagramElementFinder cache) { + cache.getNodeDescription(this.name).ifPresent(nodeDescription -> { + cache.getNodeDescription(this.nameGenerator.getNodeName(SysmlPackage.eINSTANCE.getStateUsage())).ifPresent(nodeDescription.getReusedChildNodeDescriptions()::add); + nodeDescription.setPalette(this.createCompartmentPalette(cache)); + }); + } + + @Override + protected List getDroppableNodes(IViewDiagramElementFinder cache) { + List droppableNodes = new ArrayList<>(); + cache.getNodeDescription(this.nameGenerator.getNodeName(SysmlPackage.eINSTANCE.getStateUsage())).ifPresent(droppableNodes::add); + return droppableNodes; + } + + @Override + protected InsideLabelDescription createInsideLabelDescription() { + return this.diagramBuilderHelper.newInsideLabelDescription() + .labelExpression(STATE_COMPARTMENT_NAME) + .position(InsideLabelPosition.TOP_CENTER) + .style(this.createInsideLabelStyle()) + .build(); + } + + @Override + protected InsideLabelStyle createInsideLabelStyle() { + return this.diagramBuilderHelper.newInsideLabelStyle() + .displayHeaderSeparator(false) + .fontSize(12) + .italic(true) + .labelColor(this.colorProvider.getColor(ViewConstants.DEFAULT_LABEL_COLOR)) + .showIcon(false) + .withHeader(false) + .build(); + } + + @Override + protected NodePalette createCompartmentPalette(IViewDiagramElementFinder cache) { + var palette = this.diagramBuilderHelper.newNodePalette().dropNodeTool(this.createCompartmentDropFromDiagramTool(cache)); + + // Do not use getItemCreationToolProvider because the compartment contains multiple creation tools. + palette.nodeTools(new StateTransitionCompartmentNodeToolProvider(false).create(cache), + new StateTransitionCompartmentNodeToolProvider(true).create(cache) + ); + + return palette.toolSections(this.defaultToolsFactory.createDefaultHideRevealNodeToolSection()).build(); + } +} diff --git a/backend/views/syson-diagram-statetransition-view/src/main/java/org/eclipse/syson/diagram/statetransition/view/nodes/UsageNodeDescriptionProvider.java b/backend/views/syson-diagram-statetransition-view/src/main/java/org/eclipse/syson/diagram/statetransition/view/nodes/UsageNodeDescriptionProvider.java index f79cd0a6d..85cd74bbc 100644 --- a/backend/views/syson-diagram-statetransition-view/src/main/java/org/eclipse/syson/diagram/statetransition/view/nodes/UsageNodeDescriptionProvider.java +++ b/backend/views/syson-diagram-statetransition-view/src/main/java/org/eclipse/syson/diagram/statetransition/view/nodes/UsageNodeDescriptionProvider.java @@ -48,6 +48,9 @@ protected List getReusedChildren(IViewDiagramElementFinder cach }); } }); + if (this.eClass.equals(SysmlPackage.eINSTANCE.getStateUsage())) { + cache.getNodeDescription(this.nameGenerator.getFreeFormCompartmentName(this.eClass, SysmlPackage.eINSTANCE.getUsage_NestedState())).ifPresent(reusedChildren::add); + } return reusedChildren; } diff --git a/backend/views/syson-diagram-statetransition-view/src/main/java/org/eclipse/syson/diagram/statetransition/view/services/StateTransitionViewNodeToolSectionSwitch.java b/backend/views/syson-diagram-statetransition-view/src/main/java/org/eclipse/syson/diagram/statetransition/view/services/StateTransitionViewNodeToolSectionSwitch.java index 361b0bc79..f86f888ce 100644 --- a/backend/views/syson-diagram-statetransition-view/src/main/java/org/eclipse/syson/diagram/statetransition/view/services/StateTransitionViewNodeToolSectionSwitch.java +++ b/backend/views/syson-diagram-statetransition-view/src/main/java/org/eclipse/syson/diagram/statetransition/view/services/StateTransitionViewNodeToolSectionSwitch.java @@ -22,10 +22,11 @@ import org.eclipse.syson.diagram.common.view.tools.CompartmentNodeToolProvider; import org.eclipse.syson.diagram.statetransition.view.STVDescriptionNameGenerator; import org.eclipse.syson.diagram.statetransition.view.StateTransitionViewDiagramDescriptionProvider; -import org.eclipse.syson.diagram.statetransition.view.tools.StateUsageCompartmentNodeToolProvider; +import org.eclipse.syson.diagram.statetransition.view.tools.StateTransitionCompartmentNodeToolProvider; import org.eclipse.syson.sysml.Definition; import org.eclipse.syson.sysml.Element; import org.eclipse.syson.sysml.StateDefinition; +import org.eclipse.syson.sysml.StateUsage; import org.eclipse.syson.sysml.Usage; import org.eclipse.syson.util.SysmlEClassSwitch; @@ -61,12 +62,21 @@ public Void caseDefinition(Definition object) { @Override public Void caseStateDefinition(StateDefinition object) { List nodeTools = new ArrayList<>(); - nodeTools.add(new StateUsageCompartmentNodeToolProvider(true).create(null)); - nodeTools.add(new StateUsageCompartmentNodeToolProvider(false).create(null)); + nodeTools.add(new StateTransitionCompartmentNodeToolProvider(true).create(null)); + nodeTools.add(new StateTransitionCompartmentNodeToolProvider(false).create(null)); this.addToolsToSection(nodeTools, "Create"); return super.caseStateDefinition(object); } + @Override + public Void caseStateUsage(StateUsage object) { + List nodeTools = new ArrayList<>(); + nodeTools.add(new StateTransitionCompartmentNodeToolProvider(true).create(null)); + nodeTools.add(new StateTransitionCompartmentNodeToolProvider(false).create(null)); + this.addToolsToSection(nodeTools, "Create"); + return super.caseStateUsage(object); + } + @Override public Void caseUsage(Usage object) { this.createToolsForCompartmentItems(object); diff --git a/backend/views/syson-diagram-statetransition-view/src/main/java/org/eclipse/syson/diagram/statetransition/view/services/StateTransitionViewToolService.java b/backend/views/syson-diagram-statetransition-view/src/main/java/org/eclipse/syson/diagram/statetransition/view/services/StateTransitionViewToolService.java index 88817ea4e..f27b244bf 100644 --- a/backend/views/syson-diagram-statetransition-view/src/main/java/org/eclipse/syson/diagram/statetransition/view/services/StateTransitionViewToolService.java +++ b/backend/views/syson-diagram-statetransition-view/src/main/java/org/eclipse/syson/diagram/statetransition/view/services/StateTransitionViewToolService.java @@ -25,6 +25,7 @@ import org.eclipse.sirius.components.view.emf.IViewRepresentationDescriptionSearchService; import org.eclipse.syson.diagram.common.view.services.ViewToolService; import org.eclipse.syson.diagram.statetransition.view.StateTransitionViewDiagramDescriptionProvider; +import org.eclipse.syson.diagram.statetransition.view.nodes.StateTransitionCompartmentNodeDescriptionProvider; import org.eclipse.syson.services.ElementInitializerSwitch; import org.eclipse.syson.sysml.ActionUsage; import org.eclipse.syson.sysml.Definition; @@ -72,11 +73,36 @@ public StateTransitionViewToolService(IObjectService objectService, IRepresentat * whether or not the created State is set as parallel. * @return the given {@link StateDefinition}. */ - public StateDefinition createChildState(StateDefinition stateDefinition, IEditingContext editingContext, IDiagramContext diagramContext, Node selectedNode, + public StateUsage createChildState(StateDefinition stateDefinition, IEditingContext editingContext, IDiagramContext diagramContext, Node selectedNode, Map convertedNodes, boolean isParallel) { StateUsage childState = this.createChildState(stateDefinition, isParallel); - this.createView(childState, editingContext, diagramContext, selectedNode, convertedNodes); - return stateDefinition; + + if (selectedNode.getInsideLabel().getText().equals(StateTransitionCompartmentNodeDescriptionProvider.STATE_COMPARTMENT_NAME)) { + this.createView(childState, editingContext, diagramContext, selectedNode, convertedNodes); + } else { + selectedNode.getChildNodes().stream().filter(child -> child.getInsideLabel().getText().equals(StateTransitionCompartmentNodeDescriptionProvider.STATE_COMPARTMENT_NAME)).findFirst() + .ifPresent(compartmentNode -> { + this.createView(childState, editingContext, diagramContext, compartmentNode, convertedNodes); + }); + } + + return childState; + } + + public StateUsage createChildState(StateUsage stateUsage, IEditingContext editingContext, IDiagramContext diagramContext, Node selectedNode, + Map convertedNodes, boolean isParallel) { + StateUsage childState = this.createChildState(stateUsage, isParallel); + + if (selectedNode.getInsideLabel().getText().equals(StateTransitionCompartmentNodeDescriptionProvider.STATE_COMPARTMENT_NAME)) { + this.createView(childState, editingContext, diagramContext, selectedNode, convertedNodes); + } else { + selectedNode.getChildNodes().stream().filter(child -> child.getInsideLabel().getText().equals(StateTransitionCompartmentNodeDescriptionProvider.STATE_COMPARTMENT_NAME)).findFirst() + .ifPresent(compartmentNode -> { + this.createView(childState, editingContext, diagramContext, compartmentNode, convertedNodes); + }); + } + + return childState; } /** @@ -99,8 +125,29 @@ private StateUsage createChildState(StateDefinition stateDefinition, boolean isP } /** - * Precondition for the "New State" tool from StateTransition View StateDefinition node. Ensures that child states - * of a StateDefinition are either all Parallel or none are. + * Creates a child State onto {@code stateUsage}. + * + * @param stateUsage + * the parent {@link StateUsage} + * @param isParallel + * whether the created state is parallel or not + * @return the created {@link StateUsage} + */ + private StateUsage createChildState(StateUsage stateUsage, boolean isParallel) { + var owningMembership = SysmlFactory.eINSTANCE.createFeatureMembership(); + StateUsage childState = SysmlFactory.eINSTANCE.createStateUsage(); + childState.setIsParallel(isParallel); + owningMembership.getOwnedRelatedElement().add(childState); + stateUsage.getOwnedRelationship().add(owningMembership); + this.elementInitializerSwitch.doSwitch(childState); + return childState; + } + + /** + * Precondition for the "New State" tool from StateTransition View StateDefinition node. + *

+ * This method ensures that child states of a StateDefinition are either all Parallel or none are. + *

* * @param stateDefinition * the {@link StateDefinition} corresponding to the target object on which the tool has been called. @@ -116,6 +163,24 @@ public boolean canCreateChildState(StateDefinition stateDefinition, boolean isPa return isEmpty || allMatch; } + /** + * Precondition for the "New State" tool from StateTransition View StateUsage node. + *

+ * This method ensures that child states of a {@link StateUsage} are either all parallel or none are. + *

+ * + * @param stateUsage + * the {@link StateUsage} corresponding to the target object on which the tool has been called + * @param isParallel + * whether or not the created State will be set as parallel + * @return whether an owned {@code parallel} or not) StateUsage can be created in {@code stateDefinition} + */ + public boolean canCreateChildState(StateUsage stateUsage, boolean isParallel) { + boolean isEmpty = stateUsage.getNestedState().isEmpty(); + boolean allMatch = stateUsage.getNestedState().stream().allMatch(st -> st.isIsParallel() == isParallel); + return isEmpty || allMatch; + } + /** * Create a new TransitionUsage and set it as the child of the parent of the sourceAction element. Sets its source * and target. diff --git a/backend/views/syson-diagram-statetransition-view/src/main/java/org/eclipse/syson/diagram/statetransition/view/tools/StateUsageCompartmentNodeToolProvider.java b/backend/views/syson-diagram-statetransition-view/src/main/java/org/eclipse/syson/diagram/statetransition/view/tools/StateTransitionCompartmentNodeToolProvider.java similarity index 85% rename from backend/views/syson-diagram-statetransition-view/src/main/java/org/eclipse/syson/diagram/statetransition/view/tools/StateUsageCompartmentNodeToolProvider.java rename to backend/views/syson-diagram-statetransition-view/src/main/java/org/eclipse/syson/diagram/statetransition/view/tools/StateTransitionCompartmentNodeToolProvider.java index 463784a61..2f0a8ec1d 100644 --- a/backend/views/syson-diagram-statetransition-view/src/main/java/org/eclipse/syson/diagram/statetransition/view/tools/StateUsageCompartmentNodeToolProvider.java +++ b/backend/views/syson-diagram-statetransition-view/src/main/java/org/eclipse/syson/diagram/statetransition/view/tools/StateTransitionCompartmentNodeToolProvider.java @@ -15,15 +15,15 @@ import org.eclipse.syson.diagram.common.view.tools.AbstractCompartmentNodeToolProvider; /** - * Node tool provider for Children State compartment. + * Node tool provider for creating nested/owned states in the "state transition" State compartment. * * @author adieumegard */ -public class StateUsageCompartmentNodeToolProvider extends AbstractCompartmentNodeToolProvider { +public class StateTransitionCompartmentNodeToolProvider extends AbstractCompartmentNodeToolProvider { private boolean isParallel; - public StateUsageCompartmentNodeToolProvider(boolean isParallel) { + public StateTransitionCompartmentNodeToolProvider(boolean isParallel) { super(); this.isParallel = isParallel; } @@ -62,6 +62,6 @@ protected String getNodeToolIconURLsExpression() { @Override protected boolean revealOnCreate() { - return false; + return true; } }