|
|
@@ -0,0 +1,171 @@
|
|
|
+package org.yakindu.sct.ui.editor.providers;
|
|
|
+
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.Collection;
|
|
|
+import java.util.HashMap;
|
|
|
+import java.util.Iterator;
|
|
|
+import java.util.LinkedList;
|
|
|
+import java.util.List;
|
|
|
+
|
|
|
+import org.eclipse.core.runtime.Assert;
|
|
|
+import org.eclipse.core.runtime.NullProgressMonitor;
|
|
|
+import org.eclipse.emf.common.util.TreeIterator;
|
|
|
+import org.eclipse.emf.ecore.EAnnotation;
|
|
|
+import org.eclipse.emf.ecore.EObject;
|
|
|
+import org.eclipse.emf.ecore.EcoreFactory;
|
|
|
+import org.eclipse.emf.transaction.TransactionalEditingDomain;
|
|
|
+import org.eclipse.gmf.runtime.common.core.command.ICommand;
|
|
|
+import org.eclipse.gmf.runtime.common.ui.action.actions.global.ClipboardManager;
|
|
|
+import org.eclipse.gmf.runtime.common.ui.util.CustomData;
|
|
|
+import org.eclipse.gmf.runtime.common.ui.util.CustomDataTransfer;
|
|
|
+import org.eclipse.gmf.runtime.common.ui.util.ICustomData;
|
|
|
+import org.eclipse.gmf.runtime.diagram.core.util.ViewUtil;
|
|
|
+import org.eclipse.gmf.runtime.diagram.ui.internal.commands.CopyCommand;
|
|
|
+import org.eclipse.gmf.runtime.emf.clipboard.core.ClipboardUtil;
|
|
|
+import org.eclipse.gmf.runtime.notation.Diagram;
|
|
|
+import org.eclipse.gmf.runtime.notation.Edge;
|
|
|
+import org.eclipse.gmf.runtime.notation.View;
|
|
|
+import org.yakindu.sct.model.sgraph.State;
|
|
|
+import org.yakindu.sct.ui.editor.partitioning.DiagramPartitioningUtil;
|
|
|
+
|
|
|
+/**
|
|
|
+ * Copy command that also copies the corresponding sub diagram for a state, if existing.
|
|
|
+ *
|
|
|
+ * @author kutz
|
|
|
+ *
|
|
|
+ */
|
|
|
+@SuppressWarnings({"restriction", "rawtypes"})
|
|
|
+public class SubdiagramAwareCopyCommand extends CopyCommand implements ICommand {
|
|
|
+
|
|
|
+ public SubdiagramAwareCopyCommand(TransactionalEditingDomain editingDomain, String label, View viewContext,
|
|
|
+ List source) {
|
|
|
+ super(editingDomain, label, viewContext, source);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ protected void copyToClipboard(List source) {
|
|
|
+ /* Check if the source has elements */
|
|
|
+ if (source == null || source.size() == 0) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ CustomData data = copyViews(source);
|
|
|
+ addToClipboardManager(data);
|
|
|
+ }
|
|
|
+
|
|
|
+ protected void addToClipboardManager(CustomData data) {
|
|
|
+ if (data != null) {
|
|
|
+ ClipboardManager.getInstance().addToCache(new ICustomData[]{data}, CustomDataTransfer.getInstance());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ protected CustomData copyViews(List<EObject> source) {
|
|
|
+ String copy = copyWithSubdiagrams(source);
|
|
|
+ return new CustomData(DRAWING_SURFACE, copy.getBytes());
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * This is basically a copy of
|
|
|
+ * {@link org.eclipse.gmf.runtime.diagram.ui.internal.commands.ClipboardCommand.copyViewsToString(List)}
|
|
|
+ * which is static and therefore not exchangeable. Only difference is adding of sub diagrams.
|
|
|
+ */
|
|
|
+ protected String copyWithSubdiagrams(List<EObject> views) {
|
|
|
+ Assert.isNotNull(views);
|
|
|
+ Assert.isTrue(views.size() > 0);
|
|
|
+
|
|
|
+ List<EObject> selection = new ArrayList<EObject>();
|
|
|
+ Iterator iter = views.iterator();
|
|
|
+ while (iter.hasNext()) {
|
|
|
+ EObject viewElement = (View) iter.next();
|
|
|
+ if (viewElement != null) {
|
|
|
+ selection.add(viewElement);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * We must append all inner edges of a node being copied. Edges are
|
|
|
+ * non-containment references, hence they won't be copied for free.
|
|
|
+ * Therefore, we add them here to the list of views to copy.
|
|
|
+ */
|
|
|
+ selection.addAll(getInnerEdges(views));
|
|
|
+
|
|
|
+ // add the measurement unit in an annotation. Put it in the last
|
|
|
+ // position
|
|
|
+ // to work around a limitation in the copy/paste infrastructure, that
|
|
|
+ // selects the ClipboardSupportFactory based on the first element in
|
|
|
+ // the copy list. If the annotation is first, then we get the wrong
|
|
|
+ // clipboard support instance
|
|
|
+ selection.add(getMeasurementUnitAnnotation(views));
|
|
|
+
|
|
|
+ // PATCH START
|
|
|
+ // add all sub diagrams of selected states
|
|
|
+ selection.addAll(getSubDiagrams(views));
|
|
|
+ // PATCH END
|
|
|
+
|
|
|
+ /* Copy the selection to the string */
|
|
|
+ return ClipboardUtil.copyElementsToString(selection, new HashMap(), new NullProgressMonitor());
|
|
|
+ }
|
|
|
+
|
|
|
+ protected EAnnotation getMeasurementUnitAnnotation(List<EObject> views) {
|
|
|
+ View firstView = (View) views.get(0);
|
|
|
+ Diagram dgrm = firstView.getDiagram();
|
|
|
+ EAnnotation measureUnitAnnotation = EcoreFactory.eINSTANCE.createEAnnotation();
|
|
|
+ measureUnitAnnotation.setSource(dgrm.getMeasurementUnit().getName());
|
|
|
+ return measureUnitAnnotation;
|
|
|
+ }
|
|
|
+
|
|
|
+ protected List<Edge> getInnerEdges(List views) {
|
|
|
+ List<Edge> innerEdges = new LinkedList<Edge>();
|
|
|
+ for (Iterator itr = views.iterator(); itr.hasNext();) {
|
|
|
+ View view = (View) itr.next();
|
|
|
+ if (!(view instanceof Diagram)) {
|
|
|
+ innerEdges.addAll(ViewUtil.getAllInnerEdges(view));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return innerEdges;
|
|
|
+ }
|
|
|
+
|
|
|
+ protected List<Diagram> getSubDiagrams(List views) {
|
|
|
+ List<Diagram> subDiagrams = new ArrayList<Diagram>();
|
|
|
+ Iterator iter = views.iterator();
|
|
|
+ while (iter.hasNext()) {
|
|
|
+ View viewElement = (View) iter.next();
|
|
|
+ if (viewElement != null) {
|
|
|
+ EObject semanticElement = viewElement.getElement();
|
|
|
+ if (semanticElement != null && semanticElement instanceof State) {
|
|
|
+ State semanticState = (State) semanticElement;
|
|
|
+ if (semanticState.isComposite()) {
|
|
|
+ subDiagrams.addAll(getAllSubDiagrams(semanticState));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return subDiagrams;
|
|
|
+ }
|
|
|
+
|
|
|
+ protected Collection<? extends Diagram> getAllSubDiagrams(State semanticState) {
|
|
|
+ List<Diagram> subDiagrams = new ArrayList<>();
|
|
|
+ addSubDiagram(semanticState, subDiagrams);
|
|
|
+
|
|
|
+ TreeIterator<EObject> iter = semanticState.eAllContents();
|
|
|
+ while (iter.hasNext()) {
|
|
|
+ EObject next = iter.next();
|
|
|
+ if (next instanceof State) {
|
|
|
+ State subState = (State) next;
|
|
|
+ if (subState.isComposite()) {
|
|
|
+ addSubDiagram(subState, subDiagrams);
|
|
|
+ } else {
|
|
|
+ iter.prune();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return subDiagrams;
|
|
|
+ }
|
|
|
+
|
|
|
+ protected void addSubDiagram(State semanticState, List<Diagram> subDiagrams) {
|
|
|
+ Diagram subDiagram = DiagramPartitioningUtil.getSubDiagram(semanticState);
|
|
|
+ if (subDiagram != null) {
|
|
|
+ subDiagrams.add(subDiagram);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+}
|