Skip to content

Commit 7362a5d

Browse files
Stephane DrapeauStephane Drapeau
Stephane Drapeau
authored and
Stephane Drapeau
committed
Added feature to copy/paste semantic elements and graphical style
Change-Id: I0950fdfac51e4a74241c764e530166e85d25fb83
1 parent ab1c85c commit 7362a5d

12 files changed

+679
-190
lines changed

plugins/org.obeonetwork.dsl.bpmn2.design/description/BPMN2.odesign

+29-29
Large diffs are not rendered by default.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,267 @@
1+
/**
2+
* Copyright (c) 2011-2024 Obeo.
3+
* All rights reserved. This program and the accompanying materials
4+
* are made available under the terms of the Eclipse Public License v1.0
5+
* which accompanies this distribution, and is available at
6+
* http://www.eclipse.org/legal/epl-v10.html
7+
*
8+
* Contributors:
9+
* Obeo - initial API and implementation
10+
*
11+
*/
12+
package org.obeonetwork.bpmn2.design;
13+
14+
import java.util.ArrayList;
15+
import java.util.List;
16+
import java.util.Optional;
17+
import java.util.stream.Collectors;
18+
19+
import org.eclipse.core.runtime.IStatus;
20+
import org.eclipse.emf.common.command.CommandStack;
21+
import org.eclipse.emf.common.util.EList;
22+
import org.eclipse.emf.ecore.EObject;
23+
import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain;
24+
import org.eclipse.emf.transaction.RecordingCommand;
25+
import org.eclipse.emf.transaction.TransactionalEditingDomain;
26+
import org.eclipse.gmf.runtime.notation.Bounds;
27+
import org.eclipse.gmf.runtime.notation.Edge;
28+
import org.eclipse.gmf.runtime.notation.FontStyle;
29+
import org.eclipse.gmf.runtime.notation.IdentityAnchor;
30+
import org.eclipse.gmf.runtime.notation.Location;
31+
import org.eclipse.gmf.runtime.notation.Node;
32+
import org.eclipse.gmf.runtime.notation.NotationFactory;
33+
import org.eclipse.gmf.runtime.notation.RelativeBendpoints;
34+
import org.eclipse.gmf.runtime.notation.View;
35+
import org.eclipse.gmf.runtime.notation.datatype.RelativeBendpoint;
36+
import org.eclipse.sirius.diagram.AbstractDNode;
37+
import org.eclipse.sirius.diagram.DDiagramElement;
38+
import org.eclipse.sirius.diagram.DEdge;
39+
import org.eclipse.sirius.diagram.DSemanticDiagram;
40+
import org.eclipse.sirius.diagram.EdgeStyle;
41+
import org.eclipse.sirius.diagram.FlatContainerStyle;
42+
import org.eclipse.sirius.diagram.WorkspaceImage;
43+
import org.eclipse.sirius.viewpoint.Style;
44+
import org.eclipse.ui.IWorkbench;
45+
import org.eclipse.ui.IWorkbenchPage;
46+
import org.eclipse.ui.PlatformUI;
47+
import org.obeonetwork.bpmn2.design.util.GMFHelper;
48+
import org.obeonetwork.bpmn2.design.util.GMFStyleCopier;
49+
import org.obeonetwork.bpmn2.design.util.SiriusHelper;
50+
import org.obeonetwork.bpmn2.design.util.SiriusStyleCopier;
51+
import org.obeonetwork.dsl.bpmn2.BoundaryEvent;
52+
import org.obeonetwork.dsl.bpmn2.FlowNode;
53+
import org.obeonetwork.dsl.bpmn2.SequenceFlow;
54+
55+
public class CopySiriusGMFStylesHelper {
56+
57+
public static void copyStyles(EObject newElement, DDiagramElement containerView, String oldId, String newId) {
58+
if (newElement instanceof BoundaryEvent) {
59+
copyBoundaryEvent((BoundaryEvent) newElement, containerView, oldId, newId);
60+
} else if (newElement instanceof FlowNode) {
61+
copyFlowNode((FlowNode) newElement, containerView, oldId, newId);
62+
} else if (newElement instanceof SequenceFlow) {
63+
copySequenceFlow((SequenceFlow) newElement, containerView, oldId, newId);
64+
}
65+
}
66+
67+
private static void copyBoundaryEvent(BoundaryEvent newElement, DDiagramElement containerView, String oldId,
68+
String newId) {
69+
IWorkbench workbench = PlatformUI.getWorkbench();
70+
IWorkbenchPage[] pages = workbench.getActiveWorkbenchWindow().getPages();
71+
AbstractDNode oldAbstractDNode = SiriusHelper.getAbstractDNode(oldId, pages);
72+
if (oldAbstractDNode != null) {
73+
SiriusHelper.refresh((DSemanticDiagram) containerView.getParentDiagram());
74+
// Update boundary event asynchronously.
75+
Thread t = new Thread() {
76+
public void run() {
77+
int cpt = 0;
78+
while (cpt < 100) {
79+
AbstractDNode newAbstractDNode = SiriusHelper.getAbstractDNode(containerView.getParentDiagram(),
80+
newId);
81+
if (newAbstractDNode == null) {
82+
try {
83+
Thread.sleep(1000);
84+
cpt++;
85+
} catch (InterruptedException e) {
86+
Activator.log(IStatus.ERROR, e.getMessage(), e);
87+
}
88+
} else {
89+
TransactionalEditingDomain ted = (TransactionalEditingDomain) AdapterFactoryEditingDomain
90+
.getEditingDomainFor(newAbstractDNode);
91+
CommandStack commandStack = ted.getCommandStack();
92+
commandStack.execute(new RecordingCommand(ted) {
93+
@Override
94+
protected void doExecute() {
95+
updateStyles(oldAbstractDNode, newAbstractDNode);
96+
}
97+
});
98+
return;
99+
}
100+
}
101+
};
102+
};
103+
t.start();
104+
}
105+
}
106+
107+
private static void copyFlowNode(FlowNode newElement, DDiagramElement containerView, String oldId, String newId) {
108+
IWorkbench workbench = PlatformUI.getWorkbench();
109+
IWorkbenchPage[] pages = workbench.getActiveWorkbenchWindow().getPages();
110+
AbstractDNode oldAbstractDNode = SiriusHelper.getAbstractDNode(oldId, pages);
111+
112+
if (oldAbstractDNode != null) {
113+
SiriusHelper.refresh((DSemanticDiagram) containerView.getParentDiagram());
114+
AbstractDNode newAbstractDNode = SiriusHelper.getAbstractDNode(containerView.getParentDiagram(), newId);
115+
116+
if (newAbstractDNode != null) {
117+
updateStyles(oldAbstractDNode, newAbstractDNode);
118+
}
119+
}
120+
}
121+
122+
private static void copySequenceFlow(SequenceFlow newElement, DDiagramElement containerView, String oldId,
123+
String newId) {
124+
IWorkbench workbench = PlatformUI.getWorkbench();
125+
IWorkbenchPage[] pages = workbench.getActiveWorkbenchWindow().getPages();
126+
// Update edges asynchronously.
127+
Thread t = new Thread() {
128+
public void run() {
129+
int cpt = 0;
130+
DEdge oldDEdge = SiriusHelper.getDEdge(oldId, pages);
131+
if (oldDEdge != null) {
132+
while (cpt < 100) {
133+
DEdge newDEdge = SiriusHelper.getDEdge(containerView.getParentDiagram(), newId);
134+
if (newDEdge == null) {
135+
try {
136+
Thread.sleep(1000);
137+
cpt++;
138+
} catch (InterruptedException e) {
139+
Activator.log(IStatus.ERROR, e.getMessage(), e);
140+
}
141+
} else {
142+
Edge newGMFEdge = (Edge) SiriusHelper.getGMFView(newDEdge);
143+
if (newGMFEdge != null && newDEdge.getStyle() != null) {
144+
updateStyles(oldDEdge, newDEdge);
145+
return;
146+
}
147+
}
148+
}
149+
}
150+
};
151+
};
152+
t.start();
153+
}
154+
155+
private static void updateStyles(DEdge oldAbstractDNode, DEdge newAbstractDNode) {
156+
Edge oldGMFView = (Edge) SiriusHelper.getGMFView(oldAbstractDNode);
157+
Edge newGMFView = (Edge) SiriusHelper.getGMFView(newAbstractDNode);
158+
159+
RelativeBendpoints bendPoints = (RelativeBendpoints) oldGMFView.getBendpoints();
160+
IdentityAnchor sourceAnchor = (IdentityAnchor) oldGMFView.getSourceAnchor();
161+
IdentityAnchor targetAnchor = (IdentityAnchor) oldGMFView.getTargetAnchor();
162+
EdgeStyle oldSiriusStyle = (oldAbstractDNode instanceof DEdge) ? (EdgeStyle) oldAbstractDNode.getStyle() : null;
163+
EList<?> oldGMFStyles = oldGMFView.getStyles();
164+
165+
List<Node> labels = ((List<?>) oldGMFView.getPersistedChildren()).stream()
166+
.filter(it -> GMFHelper.isGmfLabelNode(it)).map(Node.class::cast).collect(Collectors.toList());
167+
168+
TransactionalEditingDomain ted = (TransactionalEditingDomain) AdapterFactoryEditingDomain
169+
.getEditingDomainFor(newAbstractDNode);
170+
CommandStack commandStack = ted.getCommandStack();
171+
commandStack.execute(new RecordingCommand(ted) {
172+
@Override
173+
protected void doExecute() {
174+
RelativeBendpoints newBendpoints = NotationFactory.eINSTANCE.createRelativeBendpoints();
175+
List<RelativeBendpoint> list = new ArrayList<RelativeBendpoint>();
176+
for (Object o : bendPoints.getPoints()) {
177+
if (o instanceof RelativeBendpoint) {
178+
RelativeBendpoint point = (RelativeBendpoint) o;
179+
RelativeBendpoint newPoint = new RelativeBendpoint(point.getSourceX(), point.getSourceY(),
180+
point.getTargetX(), point.getTargetY());
181+
list.add(newPoint);
182+
}
183+
}
184+
newBendpoints.setPoints(list);
185+
newGMFView.setBendpoints(newBendpoints);
186+
187+
IdentityAnchor newSourceAnchor = (IdentityAnchor) newGMFView.getSourceAnchor();
188+
IdentityAnchor newTargetAnchor = (IdentityAnchor) newGMFView.getTargetAnchor();
189+
if (sourceAnchor != null) {
190+
newSourceAnchor.setId(sourceAnchor.getId());
191+
}
192+
if (targetAnchor != null) {
193+
newTargetAnchor.setId(targetAnchor.getId());
194+
}
195+
SiriusStyleCopier.updateEdgeStyle(newAbstractDNode, newGMFView, oldSiriusStyle, oldGMFStyles);
196+
if (!labels.isEmpty()) {
197+
GMFStyleCopier.updateLabels(newGMFView, labels);
198+
}
199+
}
200+
});
201+
}
202+
203+
private static void updateStyles(AbstractDNode oldAbstractDNode, AbstractDNode newAbstractDNode) {
204+
Style oldStyle = oldAbstractDNode.getStyle();
205+
Style newStyle = newAbstractDNode.getStyle();
206+
if (oldStyle instanceof FlatContainerStyle && newStyle instanceof FlatContainerStyle) {
207+
SiriusStyleCopier.updateSiriusNodeContainerFlatContainerStyle((FlatContainerStyle) oldStyle,
208+
(FlatContainerStyle) newStyle);
209+
} else if (oldStyle instanceof WorkspaceImage && newStyle instanceof WorkspaceImage) {
210+
SiriusStyleCopier.updateSiriusNodeContainerWorkspaceImageStyle((WorkspaceImage) oldStyle,
211+
(WorkspaceImage) newStyle);
212+
}
213+
214+
View oldGMFView = SiriusHelper.getGMFView(oldAbstractDNode);
215+
View newGMFView = SiriusHelper.getGMFView(newAbstractDNode);
216+
updateGMFStyles(oldGMFView, newGMFView);
217+
}
218+
219+
private static void updateGMFStyles(View oldGMFView, View newGMFView) {
220+
if (oldGMFView instanceof Node && newGMFView instanceof Node) {
221+
Node oldNode = (Node) oldGMFView;
222+
Node newNode = (Node) newGMFView;
223+
if (oldNode.getLayoutConstraint() instanceof Bounds) {
224+
Bounds oldBounds = (Bounds) oldNode.getLayoutConstraint();
225+
Bounds newBounds = NotationFactory.eINSTANCE.createBounds();
226+
newBounds.setHeight(oldBounds.getHeight());
227+
newBounds.setWidth(oldBounds.getWidth());
228+
newBounds.setX(oldBounds.getX());
229+
newBounds.setY(oldBounds.getY());
230+
newNode.setLayoutConstraint(newBounds);
231+
}
232+
newNode.getStyles().forEach(newStyle -> {
233+
Optional<?> oldStyleOpt = oldNode.getStyles().stream()
234+
.filter(oldStyle -> oldStyle.getClass().equals(newStyle.getClass())).findFirst();
235+
236+
oldStyleOpt.ifPresent(oldStyle -> {
237+
if (oldStyle instanceof FontStyle && newStyle instanceof FontStyle) {
238+
GMFStyleCopier.updateFontStyle((FontStyle) oldStyle, (FontStyle) newStyle);
239+
}
240+
});
241+
});
242+
for (Object o : oldNode.getChildren()) {
243+
if (o instanceof Node) {
244+
Node subOldNode = (Node) o;
245+
if (SiriusHelper.LABEL_NODE_TYPE.equals(subOldNode.getType())
246+
&& subOldNode.getLayoutConstraint() instanceof Location) {
247+
Location oldBounds = (Location) subOldNode.getLayoutConstraint();
248+
Location newBounds = NotationFactory.eINSTANCE.createLocation();
249+
newBounds.setX(oldBounds.getX());
250+
newBounds.setY(oldBounds.getY());
251+
252+
for (Object o2 : newNode.getChildren()) {
253+
if (o2 instanceof Node) {
254+
Node subNewNode = (Node) o2;
255+
if (SiriusHelper.LABEL_NODE_TYPE.equals(subNewNode.getType())
256+
&& subNewNode.getLayoutConstraint() instanceof Location) {
257+
subNewNode.setLayoutConstraint(newBounds);
258+
}
259+
}
260+
}
261+
}
262+
}
263+
}
264+
}
265+
}
266+
267+
}

plugins/org.obeonetwork.dsl.bpmn2.design/src/org/obeonetwork/bpmn2/design/ProcessService.java

+25-19
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@
2121
import org.eclipse.emf.ecore.EAttribute;
2222
import org.eclipse.emf.ecore.EClass;
2323
import org.eclipse.emf.ecore.EObject;
24-
import org.eclipse.emf.ecore.EReference;
2524
import org.eclipse.emf.ecore.EStructuralFeature;
2625
import org.eclipse.emf.ecore.util.EcoreUtil;
2726
import org.eclipse.emf.ecore.util.EcoreUtil.Copier;
27+
import org.eclipse.sirius.diagram.DDiagramElement;
2828
import org.obeonetwork.dsl.bpmn2.BoundaryEvent;
2929
import org.obeonetwork.dsl.bpmn2.Bpmn2Factory;
3030
import org.obeonetwork.dsl.bpmn2.Bpmn2Package;
@@ -99,36 +99,42 @@ protected void copyAttribute(EAttribute eAttribute, EObject eObject, EObject cop
9999
}
100100
}
101101

102-
public static void paste(EObject container, EObject containerView, EObject copiedView, EObject copiedElement) {
102+
public static void paste(EObject newContainer, DDiagramElement containerView, EObject copiedView,
103+
EObject newElement) {
104+
String oldId = EcoreUtil.getID(newElement);
105+
String newId = EcoreUtil.generateUUID();
106+
103107
// change IDs
104-
EcoreUtil.setID(copiedElement, EcoreUtil.generateUUID());
105-
for (Iterator<EObject> iterator = copiedElement.eAllContents(); iterator.hasNext();) {
108+
EcoreUtil.setID(newElement, newId);
109+
for (Iterator<EObject> iterator = newElement.eAllContents(); iterator.hasNext();) {
106110
EcoreUtil.setID(iterator.next(), EcoreUtil.generateUUID());
107111
}
108112

109113
// change Name
110-
EStructuralFeature nameFeature = copiedElement.eClass().getEStructuralFeature("name"); //$NON-NLS-1$
114+
EStructuralFeature nameFeature = newElement.eClass().getEStructuralFeature("name"); //$NON-NLS-1$
111115
if (nameFeature != null) {
112-
Object name = copiedElement.eGet(nameFeature);
116+
Object name = newElement.eGet(nameFeature);
113117
if (name == null) {
114118
name = "";
115119
}
116-
copiedElement.eSet(nameFeature, name + " (copy)"); // $NON-NLS-1$
120+
if (!(newElement instanceof SequenceFlow)) {
121+
name = name + " (copy)";
122+
}
123+
newElement.eSet(nameFeature, name); // $NON-NLS-1$
117124
}
118125

119-
// add to container
120-
for (EReference containment : container.eClass().getEAllContainments()) {
121-
if (containment.getEType().equals(copiedElement.eClass())
122-
|| copiedElement.eClass().getEAllSuperTypes().contains(containment.getEType())) {
123-
if (containment.isMany()) {
124-
@SuppressWarnings("unchecked")
125-
EList<EObject> values = ((EList<EObject>) container.eGet(containment));
126-
values.add(copiedElement);
127-
} else {
128-
container.eSet(containment, copiedElement);
129-
}
126+
// Set reference and containment
127+
if (newContainer instanceof Lane) {
128+
Lane lane = (Lane) newContainer;
129+
if (newElement instanceof FlowNode) {
130+
lane.getFlowNodeRefs().add((FlowNode) newElement);
130131
}
131132
}
133+
FlowElementsContainer flowElementsContainer = getFlowElementsContainer(newContainer);
134+
flowElementsContainer.getFlowElements().add((FlowElement) newElement);
135+
136+
// Copy Sirius and GMF styles
137+
CopySiriusGMFStylesHelper.copyStyles(newElement, containerView, oldId, newId);
132138
}
133139

134140
public EList<FlowElement> getSubElements(EObject eo) {
@@ -178,7 +184,7 @@ public EObject createFlowElement(EObject container, String typeToCreate) {
178184
return newElement;
179185
}
180186

181-
private FlowElementsContainer getFlowElementsContainer(EObject eo) {
187+
private static FlowElementsContainer getFlowElementsContainer(EObject eo) {
182188
FlowElementsContainer result = null;
183189
if (eo instanceof FlowElementsContainer) {
184190
result = (FlowElementsContainer) eo;

0 commit comments

Comments
 (0)