Skip to content

Commit 11a455f

Browse files
committed
[1233] Add new tools to create State sub actions in general view
Bug: eclipse-syson#1233 Signed-off-by: Jerome Gout <[email protected]>
1 parent 0698e5a commit 11a455f

File tree

11 files changed

+387
-60
lines changed

11 files changed

+387
-60
lines changed

CHANGELOG.adoc

+17-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,22 @@
11
= Changelog
22

3-
== v2025.4.0 (work in progress)
3+
== v2025.6.0 (work in progress)
4+
5+
=== Shapes
6+
7+
=== Breaking changes
8+
9+
=== Dependency update
10+
11+
=== Bug fixes
12+
13+
=== Improvements
14+
15+
- https://github.com/eclipse-syson/syson/issues/1233[#1233] [general-view] Add a creation tool of State sub actions with referenced action inside State elements
16+
17+
=== New features
18+
19+
== v2025.4.0
420

521
=== Shapes
622

backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/diagrams/general/view/GVSubNodeStateTransitionCreationTests.java

+155-34
Large diffs are not rendered by default.

backend/application/syson-application/src/test/java/org/eclipse/syson/application/data/GeneralViewWithTopNodesTestProjectData.java

+2
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ public static final class SemanticIds {
4747
public static final String PART_DEFINITION_TEXTUAL_REP_ID = "a2348331-4625-49b1-8455-2d9e4f0e1dc0";
4848

4949
public static final String PART_USAGE_ID = "2ae87f41-e214-4a36-9985-e9ec156e28e6";
50+
51+
public static final String ACTION_USAGE_ID = "62481ceb-d036-4723-acda-2bace93ae370";
5052
}
5153

5254
}

backend/views/syson-diagram-common-view/src/main/java/org/eclipse/syson/diagram/common/view/services/ViewCreateService.java

+29
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
import org.eclipse.syson.sysml.ParameterMembership;
6262
import org.eclipse.syson.sysml.PartDefinition;
6363
import org.eclipse.syson.sysml.PartUsage;
64+
import org.eclipse.syson.sysml.PerformActionUsage;
6465
import org.eclipse.syson.sysml.PortUsage;
6566
import org.eclipse.syson.sysml.ReferenceSubsetting;
6667
import org.eclipse.syson.sysml.ReferenceUsage;
@@ -71,6 +72,7 @@
7172
import org.eclipse.syson.sysml.Specialization;
7273
import org.eclipse.syson.sysml.StakeholderMembership;
7374
import org.eclipse.syson.sysml.StateDefinition;
75+
import org.eclipse.syson.sysml.StateSubactionKind;
7476
import org.eclipse.syson.sysml.StateSubactionMembership;
7577
import org.eclipse.syson.sysml.StateUsage;
7678
import org.eclipse.syson.sysml.SubjectMembership;
@@ -147,6 +149,8 @@ public Membership createMembership(Element element) {
147149
Membership membership = null;
148150
if (element instanceof Package) {
149151
membership = SysmlFactory.eINSTANCE.createOwningMembership();
152+
} else if (element instanceof StateUsage) {
153+
membership = SysmlFactory.eINSTANCE.createStateSubactionMembership();
150154
} else {
151155
membership = SysmlFactory.eINSTANCE.createFeatureMembership();
152156
}
@@ -1156,6 +1160,31 @@ public BindingConnectorAsUsage createBindingConnectorAsUsage(Feature source, Fea
11561160
return bindingConnectorAsUsage;
11571161
}
11581162

1163+
/**
1164+
* Creates a state sub action (entry, do or exit actions) as a child of the given StateUsage or StateDefinition.
1165+
* @param self the StateUsage or StateDefinition owning the sub action
1166+
* @param performedAction an ActionUsage or <code>null</code>. If set the new PerformAction should reference this action.
1167+
* @param kindLiteral the kind of the StateSubactionMembership owning the PerformAction
1168+
* @return the new PerformAction or null if self is not a State
1169+
*/
1170+
public PerformActionUsage createStateSubaction(Element self, ActionUsage performedAction, String kindLiteral) {
1171+
if (self instanceof StateUsage || self instanceof StateDefinition) {
1172+
StateSubactionMembership stateSubactionMembership = (StateSubactionMembership) this.createMembership(self, SysmlPackage.eINSTANCE.getStateSubactionMembership());
1173+
stateSubactionMembership.setKind(StateSubactionKind.get(kindLiteral));
1174+
var performAction = SysmlFactory.eINSTANCE.createPerformActionUsage();
1175+
stateSubactionMembership.getOwnedRelatedElement().add(performAction);
1176+
this.elementInitializerSwitch.doSwitch(performAction);
1177+
if (performedAction != null) {
1178+
// set the reference subsetting relationship to the performed action
1179+
var referenceSubsetting = SysmlFactory.eINSTANCE.createReferenceSubsetting();
1180+
referenceSubsetting.setReferencedFeature(performedAction);
1181+
performAction.getOwnedRelationship().add(referenceSubsetting);
1182+
}
1183+
return performAction;
1184+
}
1185+
return null;
1186+
}
1187+
11591188
private boolean isInSameGraphicalContainer(Node sourceNode, Node targetNode, IDiagramService diagramService) {
11601189
Diagram diagram = diagramService.getDiagramContext().getDiagram();
11611190
var sourceParentNode = new NodeFinder(diagram).getParent(sourceNode);

backend/views/syson-diagram-common-view/src/main/java/org/eclipse/syson/diagram/common/view/services/ViewToolService.java

+22
Original file line numberDiff line numberDiff line change
@@ -1316,6 +1316,28 @@ public List<? extends Object> getActorSelectionDialogChildren(Object selectionDi
13161316
return this.getChildrenWithInstancesOf(selectionDialogTreeElement, SysmlPackage.eINSTANCE.getPartUsage());
13171317
}
13181318

1319+
/**
1320+
* Provides the root elements in the tree of the selection dialog for the State sub actions creation tool.
1321+
*
1322+
* @param editingContext
1323+
* the (non-{@code null}) {@link IEditingContext}.
1324+
* @return the (non-{@code null}) {@link List} of all {@link Resource} that contain at least one {@link ActionUsage}.
1325+
*/
1326+
public List<Resource> getStateSubactionReferenceSelectionDialogElements(IEditingContext editingContext) {
1327+
return this.getAllResourcesWithInstancesOf(editingContext, SysmlPackage.eINSTANCE.getActionUsage());
1328+
}
1329+
1330+
/**
1331+
* Provides the children of element in the tree of the selection dialog for the State sub actions creation tool.
1332+
*
1333+
* @param selectionDialogTreeElement
1334+
* a (non-{@code null}) selection dialog tree element.
1335+
* @return the (non-{@code null}) {@link List} of all children that contain (possibly indirectly) an {@link ActionUsage}.
1336+
*/
1337+
public List<? extends Object> getStateSubactionReferenceSelectionDialogChildren(Object selectionDialogTreeElement) {
1338+
return this.getChildrenWithInstancesOf(selectionDialogTreeElement, SysmlPackage.eINSTANCE.getActionUsage());
1339+
}
1340+
13191341
private List<Resource> getAllResourcesWithInstancesOf(IEditingContext editingContext, EClassifier eClassifier) {
13201342
Objects.requireNonNull(editingContext);
13211343

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2025 Obeo.
3+
* This program and the accompanying materials
4+
* are made available under the terms of the Eclipse Public License v2.0
5+
* which accompanies this distribution, and is available at
6+
* https://www.eclipse.org/legal/epl-2.0/
7+
*
8+
* SPDX-License-Identifier: EPL-2.0
9+
*
10+
* Contributors:
11+
* Obeo - initial API and implementation
12+
*******************************************************************************/
13+
14+
package org.eclipse.syson.diagram.common.view.tools;
15+
16+
import java.util.ArrayList;
17+
import java.util.List;
18+
19+
import org.apache.commons.lang3.StringUtils;
20+
import org.eclipse.sirius.components.collaborative.diagrams.api.IDiagramContext;
21+
import org.eclipse.sirius.components.core.api.IEditingContext;
22+
import org.eclipse.sirius.components.view.ChangeContext;
23+
import org.eclipse.sirius.components.view.builder.IViewDiagramElementFinder;
24+
import org.eclipse.sirius.components.view.builder.generated.diagram.DiagramBuilders;
25+
import org.eclipse.sirius.components.view.builder.generated.view.ViewBuilders;
26+
import org.eclipse.sirius.components.view.builder.providers.INodeToolProvider;
27+
import org.eclipse.sirius.components.view.diagram.DialogDescription;
28+
import org.eclipse.sirius.components.view.diagram.NodeTool;
29+
import org.eclipse.syson.sysml.StateSubactionKind;
30+
import org.eclipse.syson.sysml.SysmlPackage;
31+
import org.eclipse.syson.util.AQLUtils;
32+
import org.eclipse.syson.util.SysMLMetamodelHelper;
33+
34+
/**
35+
* Node Tool of StateUsage and StateDefinition to create StateSubaction child elements.
36+
*
37+
* @author Jerome Gout
38+
*/
39+
public class StateSubactionNodeToolProvider implements INodeToolProvider {
40+
41+
private final DiagramBuilders diagramBuilderHelper = new DiagramBuilders();
42+
43+
private final ViewBuilders viewBuilderHelper = new ViewBuilders();
44+
45+
private final StateSubactionKind kind;
46+
47+
private final boolean isReferencing;
48+
49+
public StateSubactionNodeToolProvider(StateSubactionKind kind, boolean isReferencing) {
50+
this.kind = kind;
51+
this.isReferencing = isReferencing;
52+
}
53+
54+
@Override
55+
public NodeTool create(IViewDiagramElementFinder cache) {
56+
57+
var tool = this.diagramBuilderHelper.newNodeTool()
58+
.name(this.getNodeToolLabel())
59+
.iconURLsExpression("/icons/full/obj16/PerformActionUsage.svg")
60+
.body(this.getCreateSubactionOperation())
61+
.preconditionExpression(AQLUtils.getSelfServiceCallExpression("isEmptyOfActionKindCompartment", AQLUtils.aqlString(this.kind.getLiteral())));
62+
63+
if (this.isReferencing) {
64+
tool.dialogDescription(this.getExistingActionSelectionDialog());
65+
}
66+
67+
return tool.build();
68+
}
69+
70+
private String getNodeToolLabel() {
71+
String result = "New " + StringUtils.capitalize(this.kind.getName()) + " Action";
72+
if (this.isReferencing) {
73+
result += " with referenced Action";
74+
}
75+
return result;
76+
}
77+
78+
private ChangeContext getCreateSubactionOperation() {
79+
var revealOperation = this.viewBuilderHelper.newChangeContext()
80+
.expression(AQLUtils.getServiceCallExpression("selectedNode", "revealCompartment", List.of("self", IDiagramContext.DIAGRAM_CONTEXT, IEditingContext.EDITING_CONTEXT, "convertedNodes")));
81+
82+
var params = new ArrayList<String>();
83+
if (this.isReferencing) {
84+
params.add("selectedObject");
85+
} else {
86+
params.add("null");
87+
}
88+
params.add(AQLUtils.aqlString(this.kind.getLiteral()));
89+
return this.viewBuilderHelper.newChangeContext()
90+
.expression(AQLUtils.getSelfServiceCallExpression("createStateSubaction", params))
91+
.children(revealOperation.build())
92+
.build();
93+
}
94+
95+
private DialogDescription getExistingActionSelectionDialog() {
96+
var domainType = SysMLMetamodelHelper.buildQualifiedName(SysmlPackage.eINSTANCE.getActionUsage());
97+
98+
var selectionDialogTree = this.diagramBuilderHelper.newSelectionDialogTreeDescription()
99+
.elementsExpression(AQLUtils.getServiceCallExpression("editingContext", "getStateSubactionReferenceSelectionDialogElements"))
100+
.childrenExpression(AQLUtils.getSelfServiceCallExpression("getStateSubactionReferenceSelectionDialogChildren"))
101+
.build();
102+
103+
var selectExistingActionUsage = this.diagramBuilderHelper.newSelectionDialogDescription()
104+
.selectionDialogTreeDescription(selectionDialogTree)
105+
.selectionMessage("Select an existing Action to associate to the " + StringUtils.capitalize(this.kind.getName()) + " action you want to create:");
106+
107+
return selectExistingActionUsage.build();
108+
}
109+
}

backend/views/syson-diagram-general-view/src/main/java/org/eclipse/syson/diagram/general/view/nodes/ActionsCompartmentNodeDescriptionProvider.java

+12-11
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2024 Obeo.
2+
* Copyright (c) 2024, 2025 Obeo.
33
* This program and the accompanying materials
44
* are made available under the terms of the Eclipse Public License v2.0
55
* which accompanies this distribution, and is available at
@@ -23,8 +23,10 @@
2323
import org.eclipse.sirius.components.view.diagram.NodePalette;
2424
import org.eclipse.sirius.components.view.diagram.NodeToolSection;
2525
import org.eclipse.syson.diagram.common.view.nodes.AbstractActionsCompartmentNodeDescriptionProvider;
26-
import org.eclipse.syson.diagram.common.view.tools.StateTransitionActionCompartmentToolProvider;
26+
import org.eclipse.syson.diagram.common.view.services.description.ToolConstants;
27+
import org.eclipse.syson.diagram.common.view.tools.StateSubactionNodeToolProvider;
2728
import org.eclipse.syson.diagram.general.view.GeneralViewDiagramDescriptionProvider;
29+
import org.eclipse.syson.sysml.StateSubactionKind;
2830
import org.eclipse.syson.util.IDescriptionNameGenerator;
2931

3032
/**
@@ -60,16 +62,15 @@ protected List<NodeDescription> getDroppableNodes(IViewDiagramElementFinder cach
6062
protected NodePalette createCompartmentPalette(IViewDiagramElementFinder cache) {
6163
var palette = this.diagramBuilderHelper.newNodePalette()
6264
.dropNodeTool(this.createCompartmentDropFromDiagramTool(cache));
63-
6465
var toolSections = this.toolDescriptionService.createDefaultNodeToolSections();
65-
List<EReference> refList = GeneralViewDiagramDescriptionProvider.COMPARTMENTS_WITH_MERGED_LIST_ITEMS.get(this.eClass);
66-
if (refList != null) {
67-
refList.forEach(eRef -> {
68-
var eType = eRef.getEType();
69-
var toolSectionName = this.toolDescriptionService.getToolSectionName(eType);
70-
this.toolDescriptionService.addNodeTool(toolSections, toolSectionName, new StateTransitionActionCompartmentToolProvider(eRef).create(cache));
71-
});
72-
}
66+
// add sub actions tools
67+
this.toolDescriptionService.addNodeTool(toolSections, ToolConstants.BEHAVIOR, new StateSubactionNodeToolProvider(StateSubactionKind.ENTRY, false).create(cache));
68+
this.toolDescriptionService.addNodeTool(toolSections, ToolConstants.BEHAVIOR, new StateSubactionNodeToolProvider(StateSubactionKind.ENTRY, true).create(cache));
69+
this.toolDescriptionService.addNodeTool(toolSections, ToolConstants.BEHAVIOR, new StateSubactionNodeToolProvider(StateSubactionKind.DO, false).create(cache));
70+
this.toolDescriptionService.addNodeTool(toolSections, ToolConstants.BEHAVIOR, new StateSubactionNodeToolProvider(StateSubactionKind.DO, true).create(cache));
71+
this.toolDescriptionService.addNodeTool(toolSections, ToolConstants.BEHAVIOR, new StateSubactionNodeToolProvider(StateSubactionKind.EXIT, false).create(cache));
72+
this.toolDescriptionService.addNodeTool(toolSections, ToolConstants.BEHAVIOR, new StateSubactionNodeToolProvider(StateSubactionKind.EXIT, true).create(cache));
73+
7374
toolSections.add(this.defaultToolsFactory.createDefaultHideRevealNodeToolSection());
7475
this.toolDescriptionService.removeEmptyNodeToolSections(toolSections);
7576

backend/views/syson-diagram-general-view/src/main/java/org/eclipse/syson/diagram/general/view/services/GeneralViewNodeToolSectionSwitch.java

+14-13
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
import org.eclipse.syson.diagram.common.view.tools.SetAsRefToolProvider;
4848
import org.eclipse.syson.diagram.common.view.tools.StakeholdersCompartmentNodeToolProvider;
4949
import org.eclipse.syson.diagram.common.view.tools.StartActionNodeToolProvider;
50-
import org.eclipse.syson.diagram.common.view.tools.StateTransitionActionCompartmentToolProvider;
50+
import org.eclipse.syson.diagram.common.view.tools.StateSubactionNodeToolProvider;
5151
import org.eclipse.syson.diagram.common.view.tools.StateTransitionCompartmentNodeToolProvider;
5252
import org.eclipse.syson.diagram.common.view.tools.SubjectCompartmentNodeToolProvider;
5353
import org.eclipse.syson.diagram.general.view.GVDescriptionNameGenerator;
@@ -76,6 +76,7 @@
7676
import org.eclipse.syson.sysml.RequirementDefinition;
7777
import org.eclipse.syson.sysml.RequirementUsage;
7878
import org.eclipse.syson.sysml.StateDefinition;
79+
import org.eclipse.syson.sysml.StateSubactionKind;
7980
import org.eclipse.syson.sysml.StateUsage;
8081
import org.eclipse.syson.sysml.SysmlPackage;
8182
import org.eclipse.syson.sysml.Usage;
@@ -618,13 +619,13 @@ public List<NodeToolSection> caseStateDefinition(StateDefinition object) {
618619
this.toolDescriptionService.addNodeTool(sections, ToolConstants.BEHAVIOR, new StateTransitionCompartmentNodeToolProvider(true, false).create(this.cache));
619620
this.toolDescriptionService.addNodeTool(sections, ToolConstants.BEHAVIOR, new StateTransitionCompartmentNodeToolProvider(false, true).create(this.cache));
620621
this.toolDescriptionService.addNodeTool(sections, ToolConstants.BEHAVIOR, new StateTransitionCompartmentNodeToolProvider(true, true).create(this.cache));
621-
this.toolDescriptionService.addNodeTool(sections, ToolConstants.BEHAVIOR,
622-
new StateTransitionActionCompartmentToolProvider(SysmlPackage.eINSTANCE.getStateDefinition_EntryAction()).create(this.cache));
623-
this.toolDescriptionService.addNodeTool(sections, ToolConstants.BEHAVIOR,
624-
new StateTransitionActionCompartmentToolProvider(SysmlPackage.eINSTANCE.getStateDefinition_DoAction()).create(this.cache));
625-
this.toolDescriptionService.addNodeTool(sections, ToolConstants.BEHAVIOR,
626-
new StateTransitionActionCompartmentToolProvider(SysmlPackage.eINSTANCE.getStateDefinition_ExitAction()).create(this.cache));
627622
this.toolDescriptionService.addNodeTool(sections, ToolConstants.BEHAVIOR, new ExhibitStateWithReferenceNodeToolProvider(this.descriptionNameGenerator).create(this.cache));
623+
this.toolDescriptionService.addNodeTool(sections, ToolConstants.BEHAVIOR, new StateSubactionNodeToolProvider(StateSubactionKind.ENTRY, true).create(this.cache));
624+
this.toolDescriptionService.addNodeTool(sections, ToolConstants.BEHAVIOR, new StateSubactionNodeToolProvider(StateSubactionKind.ENTRY, false).create(this.cache));
625+
this.toolDescriptionService.addNodeTool(sections, ToolConstants.BEHAVIOR, new StateSubactionNodeToolProvider(StateSubactionKind.DO, true).create(this.cache));
626+
this.toolDescriptionService.addNodeTool(sections, ToolConstants.BEHAVIOR, new StateSubactionNodeToolProvider(StateSubactionKind.DO, false).create(this.cache));
627+
this.toolDescriptionService.addNodeTool(sections, ToolConstants.BEHAVIOR, new StateSubactionNodeToolProvider(StateSubactionKind.EXIT, true).create(this.cache));
628+
this.toolDescriptionService.addNodeTool(sections, ToolConstants.BEHAVIOR, new StateSubactionNodeToolProvider(StateSubactionKind.EXIT, false).create(this.cache));
628629
sections.add(this.toolDescriptionService.relatedElementsNodeToolSection(true));
629630
this.toolDescriptionService.removeEmptyNodeToolSections(sections);
630631
return sections;
@@ -637,13 +638,13 @@ public List<NodeToolSection> caseStateUsage(StateUsage object) {
637638
this.toolDescriptionService.addNodeTool(sections, ToolConstants.BEHAVIOR, new StateTransitionCompartmentNodeToolProvider(true, false).create(this.cache));
638639
this.toolDescriptionService.addNodeTool(sections, ToolConstants.BEHAVIOR, new StateTransitionCompartmentNodeToolProvider(false, true).create(this.cache));
639640
this.toolDescriptionService.addNodeTool(sections, ToolConstants.BEHAVIOR, new StateTransitionCompartmentNodeToolProvider(true, true).create(this.cache));
640-
this.toolDescriptionService.addNodeTool(sections, ToolConstants.BEHAVIOR,
641-
new StateTransitionActionCompartmentToolProvider(SysmlPackage.eINSTANCE.getStateDefinition_EntryAction()).create(this.cache));
642-
this.toolDescriptionService.addNodeTool(sections, ToolConstants.BEHAVIOR,
643-
new StateTransitionActionCompartmentToolProvider(SysmlPackage.eINSTANCE.getStateDefinition_DoAction()).create(this.cache));
644-
this.toolDescriptionService.addNodeTool(sections, ToolConstants.BEHAVIOR,
645-
new StateTransitionActionCompartmentToolProvider(SysmlPackage.eINSTANCE.getStateDefinition_ExitAction()).create(this.cache));
646641
this.toolDescriptionService.addNodeTool(sections, ToolConstants.BEHAVIOR, new ExhibitStateWithReferenceNodeToolProvider(this.descriptionNameGenerator).create(this.cache));
642+
this.toolDescriptionService.addNodeTool(sections, ToolConstants.BEHAVIOR, new StateSubactionNodeToolProvider(StateSubactionKind.ENTRY, true).create(this.cache));
643+
this.toolDescriptionService.addNodeTool(sections, ToolConstants.BEHAVIOR, new StateSubactionNodeToolProvider(StateSubactionKind.ENTRY, false).create(this.cache));
644+
this.toolDescriptionService.addNodeTool(sections, ToolConstants.BEHAVIOR, new StateSubactionNodeToolProvider(StateSubactionKind.DO, true).create(this.cache));
645+
this.toolDescriptionService.addNodeTool(sections, ToolConstants.BEHAVIOR, new StateSubactionNodeToolProvider(StateSubactionKind.DO, false).create(this.cache));
646+
this.toolDescriptionService.addNodeTool(sections, ToolConstants.BEHAVIOR, new StateSubactionNodeToolProvider(StateSubactionKind.EXIT, true).create(this.cache));
647+
this.toolDescriptionService.addNodeTool(sections, ToolConstants.BEHAVIOR, new StateSubactionNodeToolProvider(StateSubactionKind.EXIT, false).create(this.cache));
647648
this.toolDescriptionService.addNodeTool(sections, ToolConstants.STRUCTURE, new SetAsCompositeToolProvider().create(this.cache));
648649
this.toolDescriptionService.addNodeTool(sections, ToolConstants.STRUCTURE, new SetAsRefToolProvider().create(this.cache));
649650
sections.add(this.toolDescriptionService.relatedElementsNodeToolSection(true));

doc/content/modules/user-manual/pages/release-notes/2025.4.0.adoc

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
= 2025.4.0 (work in progress)
1+
= 2025.4.0
22

33
== Key highlights
44

0 commit comments

Comments
 (0)