diff --git a/org.fortiss.tooling.kernel.ui/trunk/src/org/fortiss/tooling/kernel/ui/extension/base/EObjectActionBase.java b/org.fortiss.tooling.kernel.ui/trunk/src/org/fortiss/tooling/kernel/ui/extension/base/EObjectActionBase.java index 40ec62ecc091981fd6b9f6ba065b909aa9d758a9..09058c9166312c62a8362ce32be9a50c3f88924a 100644 --- a/org.fortiss.tooling.kernel.ui/trunk/src/org/fortiss/tooling/kernel/ui/extension/base/EObjectActionBase.java +++ b/org.fortiss.tooling.kernel.ui/trunk/src/org/fortiss/tooling/kernel/ui/extension/base/EObjectActionBase.java @@ -21,6 +21,8 @@ import static java.util.Arrays.asList; import java.util.List; +import org.eclipse.emf.common.util.BasicEList; +import org.eclipse.emf.common.util.EList; import org.eclipse.emf.ecore.EObject; import org.eclipse.jface.action.Action; import org.eclipse.jface.resource.ImageDescriptor; @@ -32,7 +34,7 @@ import org.eclipse.jface.resource.ImageDescriptor; * @author hoelzl * @author $Author$ * @version $Rev$ - * @ConQAT.Rating YELLOW Hash: 1D6CCC2A2CE03ACD4F8129DD9FCEAFCF + * @ConQAT.Rating YELLOW Hash: A544F6FF5459D4E0041E5E37EFD33867 */ public abstract class EObjectActionBase<T extends EObject> extends Action { @@ -43,7 +45,7 @@ public abstract class EObjectActionBase<T extends EObject> extends Action { } /** Stores the target elements. */ - private List<T> targets; + private EList<T> targets; /** Constructor. */ public EObjectActionBase(String text, ImageDescriptor image) { @@ -67,8 +69,13 @@ public abstract class EObjectActionBase<T extends EObject> extends Action { } /** Sets the target object. */ - public void setTargets(List<T> targets) { - this.targets = targets; + public void setTargets(List<T> newTargets) { + if(targets == null) { + targets = new BasicEList<T>(newTargets); + } else { + targets.clear(); + targets.addAll(newTargets); + } } /** Sets the target object. */ @@ -85,7 +92,7 @@ public abstract class EObjectActionBase<T extends EObject> extends Action { } /** Returns the current targets. */ - public List<T> getTargets() { + public EList<T> getTargets() { return targets; } diff --git a/org.fortiss.tooling.kernel.ui/trunk/src/org/fortiss/tooling/kernel/ui/internal/actions/CopyAction.java b/org.fortiss.tooling.kernel.ui/trunk/src/org/fortiss/tooling/kernel/ui/internal/actions/CopyAction.java index 314226da1490d672b73e123f919cbe4f6f4db7a7..dcf3c785111d261867d8d5d9f05b0f0e97d6dabe 100644 --- a/org.fortiss.tooling.kernel.ui/trunk/src/org/fortiss/tooling/kernel/ui/internal/actions/CopyAction.java +++ b/org.fortiss.tooling.kernel.ui/trunk/src/org/fortiss/tooling/kernel/ui/internal/actions/CopyAction.java @@ -19,11 +19,13 @@ package org.fortiss.tooling.kernel.ui.internal.actions; import static org.fortiss.tooling.kernel.ui.util.CopyPasteUtils.copyToClipboard; +import org.eclipse.emf.common.util.EList; import org.eclipse.emf.ecore.EObject; import org.eclipse.ui.ISharedImages; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.actions.ActionFactory; import org.fortiss.tooling.kernel.ui.extension.base.EObjectActionBase; +import org.fortiss.tooling.kernel.utils.KernelModelElementUtils; /** * Action for copying the current selection. @@ -32,7 +34,7 @@ import org.fortiss.tooling.kernel.ui.extension.base.EObjectActionBase; * @author hoelzl * @author $Author$ * @version $Rev$ - * @ConQAT.Rating GREEN Hash: 69A8F1BDE380BB57E2F811EC4A75A83C + * @ConQAT.Rating YELLOW Hash: 454F12FE73DC98AC62710AAC69469E57 */ public class CopyAction extends EObjectActionBase<EObject> { @@ -46,10 +48,16 @@ public class CopyAction extends EObjectActionBase<EObject> { /** {@inheritDoc} */ @Override public void run() { - if(getTarget() == null) { + doCopy(getTargets()); + } + + /** Copy the targets if non empty. */ + public static void doCopy(EList<EObject> targets) { + if(targets == null || targets.isEmpty()) { return; } - copyToClipboard(getTargets()); + EList<EObject> cleanedTargets = KernelModelElementUtils.topParents(targets); + copyToClipboard(KernelModelElementUtils.topParents(cleanedTargets)); } /** {@inheritDoc} */ diff --git a/org.fortiss.tooling.kernel.ui/trunk/src/org/fortiss/tooling/kernel/ui/internal/actions/CutAction.java b/org.fortiss.tooling.kernel.ui/trunk/src/org/fortiss/tooling/kernel/ui/internal/actions/CutAction.java index aaf0e113ebde7dd60dd9f523ac35fd7514341fb2..13df511e6570629c1f0972617f0ebfe579cf9f36 100644 --- a/org.fortiss.tooling.kernel.ui/trunk/src/org/fortiss/tooling/kernel/ui/internal/actions/CutAction.java +++ b/org.fortiss.tooling.kernel.ui/trunk/src/org/fortiss/tooling/kernel/ui/internal/actions/CutAction.java @@ -17,8 +17,8 @@ $Id$ +--------------------------------------------------------------------------*/ package org.fortiss.tooling.kernel.ui.internal.actions; -import java.util.Collection; -import java.util.LinkedList; +import static org.fortiss.tooling.kernel.ui.internal.actions.CopyAction.doCopy; +import static org.fortiss.tooling.kernel.ui.internal.actions.DeleteAction.doDelete; import org.eclipse.emf.ecore.EObject; import org.eclipse.ui.ISharedImages; @@ -27,7 +27,6 @@ import org.eclipse.ui.actions.ActionFactory; import org.fortiss.tooling.kernel.service.ICommandStackService; import org.fortiss.tooling.kernel.service.IElementCompositorService; import org.fortiss.tooling.kernel.ui.extension.base.EObjectActionBase; -import org.fortiss.tooling.kernel.ui.util.CopyPasteUtils; /** * Action for cutting the current selection. @@ -36,7 +35,7 @@ import org.fortiss.tooling.kernel.ui.util.CopyPasteUtils; * @author hoelzl * @author $Author$ * @version $Rev$ - * @ConQAT.Rating GREEN Hash: 83600A03B6ECB95C8C98C805953C9890 + * @ConQAT.Rating YELLOW Hash: 60F02762C4975F4926ABDCC29611BBC8 */ public class CutAction extends EObjectActionBase<EObject> { @@ -53,12 +52,8 @@ public class CutAction extends EObjectActionBase<EObject> { ICommandStackService.INSTANCE.runAsCommand(getTarget(), new Runnable() { @Override public void run() { - // currently we support only single element cutting - // see ActionService.refresh() - Collection<EObject> targets = new LinkedList<EObject>(); - targets.add(getTarget()); - CopyPasteUtils.copyToClipboard(targets); - IElementCompositorService.INSTANCE.decompose(getTarget()); + doCopy(getTargets()); + doDelete(getTargets()); } }); } diff --git a/org.fortiss.tooling.kernel.ui/trunk/src/org/fortiss/tooling/kernel/ui/internal/actions/DeleteAction.java b/org.fortiss.tooling.kernel.ui/trunk/src/org/fortiss/tooling/kernel/ui/internal/actions/DeleteAction.java index 09a2ccfc3e25b01805f8b67061312a04bcfd6ca8..231b41de32ccf3ee88ff763b23b0d6690612784e 100644 --- a/org.fortiss.tooling.kernel.ui/trunk/src/org/fortiss/tooling/kernel/ui/internal/actions/DeleteAction.java +++ b/org.fortiss.tooling.kernel.ui/trunk/src/org/fortiss/tooling/kernel/ui/internal/actions/DeleteAction.java @@ -47,7 +47,7 @@ import org.fortiss.tooling.kernel.ui.service.IModelEditorBindingService; * @author hoelzl * @author $Author$ * @version $Rev$ - * @ConQAT.Rating YELLOW Hash: E733E0FF17436B878C53DDF807C7E373 + * @ConQAT.Rating YELLOW Hash: 4E9C8E039F44355D95C95D006A5369AD */ public class DeleteAction extends EObjectActionBase<EObject> { @@ -61,8 +61,12 @@ public class DeleteAction extends EObjectActionBase<EObject> { /** {@inheritDoc} */ @Override public void run() { - Map<ITopLevelElement, List<EObject>> topLevelTargetsMap = topLevelMap(getTargets()); + doDelete(getTargets()); + } + /** Deletes the given targets (organized in a map by topLevel element). */ + public static void doDelete(List<EObject> unorganizedTargets) { + Map<ITopLevelElement, List<EObject>> topLevelTargetsMap = topLevelMap(unorganizedTargets); for(ITopLevelElement topLevel : topLevelTargetsMap.keySet()) { final List<EObject> targets = topLevelTargetsMap.get(topLevel); boolean topLevelDeleted = false; @@ -112,7 +116,7 @@ public class DeleteAction extends EObjectActionBase<EObject> { } /** Executes the delete using the correct service. */ - private void doCompositorBasedDelete(List<EObject> targets) { + private static void doCompositorBasedDelete(List<EObject> targets) { for(EObject target : targets) { if(IElementCompositorService.INSTANCE.canDecompose(target)) { IElementCompositorService.INSTANCE.decompose(target); @@ -123,7 +127,7 @@ public class DeleteAction extends EObjectActionBase<EObject> { } /** User interaction before deleting a top-level element. */ - private void doTopLevelElementDelete(EObject target) { + private static void doTopLevelElementDelete(EObject target) { ITopLevelElement topElement = IPersistencyService.INSTANCE.getTopLevelElementFor(target); Shell sh = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(); String message = "Are you sure you want to delete '" + topElement.getSaveableName() + "'?"; @@ -156,7 +160,7 @@ public class DeleteAction extends EObjectActionBase<EObject> { * i.e., given a set of model elements M, returns a map f s.t., for every top level element top, * f(top) = { m in M | top is the top level element of m } */ - public Map<ITopLevelElement, List<EObject>> topLevelMap(List<EObject> modelElements) { + public static Map<ITopLevelElement, List<EObject>> topLevelMap(List<EObject> modelElements) { HashMap<ITopLevelElement, List<EObject>> res = new HashMap<ITopLevelElement, List<EObject>>(); for(EObject eo : modelElements) { diff --git a/org.fortiss.tooling.kernel.ui/trunk/src/org/fortiss/tooling/kernel/ui/util/CopyPasteUtils.java b/org.fortiss.tooling.kernel.ui/trunk/src/org/fortiss/tooling/kernel/ui/util/CopyPasteUtils.java index ee870c6aff5984c49716fed1d5bd3022974059d9..19275bfc47d5456c5b70a3a84d5dbe7e3db923eb 100644 --- a/org.fortiss.tooling.kernel.ui/trunk/src/org/fortiss/tooling/kernel/ui/util/CopyPasteUtils.java +++ b/org.fortiss.tooling.kernel.ui/trunk/src/org/fortiss/tooling/kernel/ui/util/CopyPasteUtils.java @@ -17,8 +17,12 @@ $Id$ +--------------------------------------------------------------------------*/ package org.fortiss.tooling.kernel.ui.util; +import static org.fortiss.tooling.kernel.utils.EcoreUtils.pickInstanceOf; + import java.util.Collection; +import org.eclipse.emf.common.util.BasicEList; +import org.eclipse.emf.common.util.EList; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.util.EcoreUtil; import org.eclipse.jface.dialogs.MessageDialog; @@ -28,6 +32,7 @@ import org.eclipse.swt.dnd.TextTransfer; import org.eclipse.swt.dnd.Transfer; import org.eclipse.swt.widgets.Display; import org.fortiss.tooling.kernel.extension.data.IElementCompositionContext; +import org.fortiss.tooling.kernel.model.SpeciallyCopyiable; import org.fortiss.tooling.kernel.service.IElementCompositorService; import org.fortiss.tooling.kernel.ui.dnd.CompositionServiceLocalCopyPasteTransfer; @@ -40,33 +45,42 @@ import org.fortiss.tooling.kernel.ui.dnd.CompositionServiceLocalCopyPasteTransfe * * @author $Author$ * @version $Rev$ - * @ConQAT.Rating GREEN Hash: A40EF644FB2792BDE3DB675D3D7FA0C8 + * @ConQAT.Rating YELLOW Hash: E84BD272D73E0D834E3535040340CBDD */ public class CopyPasteUtils { /** * Copies the given selected objects to the clipboard. * - * @param selection + * @param sel * the collection of {@link EObject}s to be copyied to the * clipboard. */ - public static void copyToClipboard(Collection<EObject> selection) { + public static void copyToClipboard(Collection<EObject> sel) { try { - EObject[] content = new EObject[selection.size()]; + EObject[] content = new EObject[sel.size()]; int i = 0; EcoreUtil.Copier copier = new EcoreUtil.Copier(true, true); - for(EObject sel : selection) { - content[i] = copier.copy(sel); + for(EObject obj : sel) { + content[i] = copier.copy(obj); copier.copyReferences(); i++; } + EList<SpeciallyCopyiable> specialSel = + pickInstanceOf(SpeciallyCopyiable.class, new BasicEList<EObject>(sel)); + for(SpeciallyCopyiable obj : specialSel) { + obj.completeCopyEnvironment(copier); + } + for(SpeciallyCopyiable obj : specialSel) { + obj.copyConnections(copier); + } Clipboard clipboard = new Clipboard(Display.getDefault()); clipboard.setContents(new Object[] {content}, new Transfer[] {CompositionServiceLocalCopyPasteTransfer.getInstance()}, DND.CLIPBOARD | DND.SELECTION_CLIPBOARD); clipboard.dispose(); } catch(Exception e) { + e.printStackTrace(); MessageDialog.openError(Display.getDefault().getActiveShell(), "Copy", "Clipboard contents not writeable: " + e.getMessage()); return; @@ -98,12 +112,18 @@ public class CopyPasteUtils { if(!canPasteInto(target, context)) { return; } - for(EObject insertObj : getClipBoardContent()) { - EcoreUtil.Copier copier = new EcoreUtil.Copier(); - EObject copy = copier.copy(insertObj); + + EcoreUtil.Copier copier = new EcoreUtil.Copier(); + for(EObject obj : getClipBoardContent()) { + EObject copy = copier.copy(obj); copier.copyReferences(); IElementCompositorService.INSTANCE.compose(target, copy, context); } + for(EObject obj : getClipBoardContent()) { + if(obj instanceof SpeciallyCopyiable) { + ((SpeciallyCopyiable)obj).copyConnections(copier); + } + } } /** diff --git a/org.fortiss.tooling.kernel/trunk/model/kernel.ecore b/org.fortiss.tooling.kernel/trunk/model/kernel.ecore index 67a18eeac955c25baac9449dae5dde64ce508457..7d5cad2ab305b3aeb1011530a14e3ec119ee46e6 100644 --- a/org.fortiss.tooling.kernel/trunk/model/kernel.ecore +++ b/org.fortiss.tooling.kernel/trunk/model/kernel.ecore @@ -100,4 +100,30 @@ <eClassifiers xsi:type="ecore:EClass" name="IExternalDocumentReference"> <eStructuralFeatures xsi:type="ecore:EAttribute" name="uri" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/> </eClassifiers> + <eClassifiers xsi:type="ecore:EClass" name="SpeciallyCopyiable"> + <eOperations name="completeCopyEnvironment"> + <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel"> + <details key="body" value="/** To be implemented by subclasses. **/"/> + <details key="documentation" value="Hook to allow changing the copy map, typically by adding elements that are not copied but might still be necessary to preserve some information.
The typical example is to copy connections between elements: the top element containing the connections is not copied, but necessary to copy the connections."/> + </eAnnotations> + <eParameters name="copyMap"> + <eGenericType eClassifier="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EMap"> + <eTypeArguments eClassifier="ecore:EClass http://www.eclipse.org/emf/2002/Ecore#//EObject"/> + <eTypeArguments eClassifier="ecore:EClass http://www.eclipse.org/emf/2002/Ecore#//EObject"/> + </eGenericType> + </eParameters> + </eOperations> + <eOperations name="copyConnections"> + <eAnnotations source="http://www.eclipse.org/emf/2002/GenModel"> + <details key="body" value="/** To be implemented by subclasses. **/"/> + <details key="documentation" value="Hook to allow copying the connections between elements.
Goes hand in hand with completeCopyEnvironment.
Typically, one first calls completeCopyEnvironment on all copied elements and then copyConnections to copy the connections."/> + </eAnnotations> + <eParameters name="copyMap"> + <eGenericType eClassifier="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EMap"> + <eTypeArguments eClassifier="ecore:EClass http://www.eclipse.org/emf/2002/Ecore#//EObject"/> + <eTypeArguments eClassifier="ecore:EClass http://www.eclipse.org/emf/2002/Ecore#//EObject"/> + </eGenericType> + </eParameters> + </eOperations> + </eClassifiers> </ecore:EPackage> diff --git a/org.fortiss.tooling.kernel/trunk/model/kernel.genmodel b/org.fortiss.tooling.kernel/trunk/model/kernel.genmodel index e6d29aa99d1540378d5bd56b6970cd967a63bcab..27e1a2d4421b70f283d0577e2447305ec573d46d 100644 --- a/org.fortiss.tooling.kernel/trunk/model/kernel.genmodel +++ b/org.fortiss.tooling.kernel/trunk/model/kernel.genmodel @@ -46,5 +46,13 @@ <genClasses ecoreClass="kernel.ecore#//IExternalDocumentReference"> <genFeatures createChild="false" ecoreFeature="ecore:EAttribute kernel.ecore#//IExternalDocumentReference/uri"/> </genClasses> + <genClasses ecoreClass="kernel.ecore#//SpeciallyCopyiable"> + <genOperations ecoreOperation="kernel.ecore#//SpeciallyCopyiable/completeCopyEnvironment"> + <genParameters ecoreParameter="kernel.ecore#//SpeciallyCopyiable/completeCopyEnvironment/copyMap"/> + </genOperations> + <genOperations ecoreOperation="kernel.ecore#//SpeciallyCopyiable/copyConnections"> + <genParameters ecoreParameter="kernel.ecore#//SpeciallyCopyiable/copyConnections/copyMap"/> + </genOperations> + </genClasses> </genPackages> </genmodel:GenModel> diff --git a/org.fortiss.tooling.kernel/trunk/src/org/fortiss/tooling/kernel/utils/KernelModelElementUtils.java b/org.fortiss.tooling.kernel/trunk/src/org/fortiss/tooling/kernel/utils/KernelModelElementUtils.java index af86e10887bb506d7b5bd2b75e479e1f3f0d2506..476c7575d4542349f3351289a3152692a28bc23e 100644 --- a/org.fortiss.tooling.kernel/trunk/src/org/fortiss/tooling/kernel/utils/KernelModelElementUtils.java +++ b/org.fortiss.tooling.kernel/trunk/src/org/fortiss/tooling/kernel/utils/KernelModelElementUtils.java @@ -20,6 +20,8 @@ package org.fortiss.tooling.kernel.utils; import java.util.Iterator; import java.util.List; +import org.eclipse.emf.common.util.BasicEList; +import org.eclipse.emf.common.util.EList; import org.eclipse.emf.ecore.EObject; import org.fortiss.tooling.kernel.extension.data.ITopLevelElement; import org.fortiss.tooling.kernel.model.IIdLabeled; @@ -36,7 +38,7 @@ import org.fortiss.tooling.kernel.service.IPersistencyService; * @author hoelzl * @author $Author$ * @version $Rev$ - * @ConQAT.Rating GREEN Hash: 7043206480716A4D94F8FF968AA13525 + * @ConQAT.Rating YELLOW Hash: E6EC9303F505DCCC8EE14C09D896D380 */ public final class KernelModelElementUtils { @@ -177,6 +179,28 @@ public final class KernelModelElementUtils { return false; } + /** + * Keeps only the top-most parents of a list. + * i.e., if the list contains two elements, one is the (direct or indirect) child of the other, + * then it is removed. + */ + public static EList<EObject> topParents(EList<EObject> objs) { + EList<EObject> res = new BasicEList<EObject>(); + for(EObject o1 : objs) { + boolean hasParent = false; + for(EObject o2 : objs) { + if(KernelModelElementUtils.isChildElementOf(o1, o2)) { + hasParent = true; + break; + } + } + if(!hasParent) { + res.add(o1); + } + } + return res; + } + /** * Iterates the content of the given root element and finds a contained * element with the given name and the given class.