# Providing Copy & Paste Functionality

## Copy & Paste Functionality

The copy & paste of graphical elements is integrated with the general copy and paste concept for models

Note, that copy & paste in diagrams is always executed on the graphical model-elements. This gives the freedom to implement copy & paste with different semantics

- On paste a duplicate of the graphical pictogram element and of the underlying business-model element is created. However, it is sometimes difficult to create a duplicate of the business-model element, because the semantic boundaries of it may be ambiguous, think of a “deep copy”.
- On paste a duplicate of the graphical pictogram element is created, which is associated to the same underlying business-model element as the originally copied graphical pictogram element.

Below we will explain an example, which provides copy & paste functionality for EClasses. For simplicity reasons we only create a duplicate of the graphical pictogram element and not also of the business-model element.

## Creating a Copy Feature

First we have to create a copy feature and make it available in the feature provider.

A copy feature has to implement the interface ICopyFeature. Instead of implementing it directly it should extend one of the available base classes. In this example we extend the base class AbstractCopyFeature, which offers methods to easily access the clipboard.

In this case we have to implement/overwrite two methods:

- The method canCopy has to check if the given context (containing the selected elements) can be copied to the clipboard.
- The method copy finally has to copy the given context to the clipboard.

You can see the complete implementation of the copy feature here:

package org.eclipse.graphiti.examples.tutorial.features;
public class TutorialCopyEClassFeature extends AbstractCopyFeature {
public TutorialCopyEClassFeature(IFeatureProvider fp) {
super(fp);
}
public boolean canCopy(ICopyContext context) {
final PictogramElement[] pes = context.getPictogramElements();
if (pes == null || pes.length == 0) { // nothing selected
return false;
}
// return true, if all selected elements are a EClasses
for (PictogramElement pe : pes) {
final Object bo = getBusinessObjectForPictogramElement(pe);
if (!(bo instanceof EClass)) {
return false;
}
}
return true;
}
public void copy(ICopyContext context) {
// get the business-objects for all pictogram-elements
// we already verified, that all business-objets are EClasses
PictogramElement[] pes = context.getPictogramElements();
Object[] bos = new Object[pes.length ];
for (int i = 0; i < pes.length ; i++) {
PictogramElement pe = pes[i];
bos[i] = getBusinessObjectForPictogramElement(pe);
}
// put all business objects to the clipboard
putToClipboard(bos);
}
}

Additionally the feature provider has to deliver our newly created feature (overwrite the method getCopyFeature).

This implementation can be seen here:

@Override
public ICopyFeature getCopyFeature(ICopyContext context) {
return new TutorialCopyEClassFeature(this);
}

## Creating a Paste Feature

Now we have to create a corresponding paste feature and make it available in the feature provider.

A paste feature has to implement the interface IPasteFeature. Instead of implementing it directly it should extend one of the available base classes. In this example we extend the base class AbstractPasteFeature, which offers methods to easily access the clipboard.

In this case we have to implement/overwrite two methods:

- The method canPaste has to check if the current clipboard contents can be pasted on the given context (containing the target object).
- The method paste finally has to paste the current clipboard contents on the given context.

You can see the complete implementation of the paste feature here:

package org.eclipse.graphiti.examples.tutorial.features;
public class TutorialPasteEClassFeature extends AbstractPasteFeature {
public TutorialPasteEClassFeature(IFeatureProvider fp) {
super(fp);
}
public boolean canPaste(IPasteContext context) {
// only support pasting directly in the diagram (nothing else selected)
PictogramElement[] pes = context.getPictogramElements();
if (pes.length != 1 || !(pes[0] instanceof Diagram)) {
return false;
}
// can paste, if all objects on the clipboard are EClasses
Object[] fromClipboard = getFromClipboard();
if (fromClipboard == null || fromClipboard.length == 0) {
return false;
}
for (Object object : fromClipboard) {
if (!(object instanceof EClass)) {
return false;
}
}
return true;
}
public void paste(IPasteContext context) {
// we already verified, that we paste directly in the diagram
PictogramElement[] pes = context.getPictogramElements();
Diagram diagram = (Diagram) pes[0];
// get the EClasses from the clipboard without copying them
// (only copy the pictogram element, not the business object)
// then create new pictogram elements using the add feature
Object[] objects = getFromClipboard();
for (Object object : objects) {
AddContext ac = new AddContext();
// For simplicity paste all objects at the location given in the
// context (no stacking or similar)
ac.setLocation(context.getX(), context.getY());
ac.setTargetContainer(diagram);
addGraphicalRepresentation(ac, object);
}
}
}

Additionally the feature provider has to deliver our newly created feature (overwrite the method getPasteFeature).

This implementation can be seen here:

@Override
public IPasteFeature getPasteFeature(IPasteContext context) {
return new TutorialPasteEClassFeature(this);
}

## Test: Copy & Paste a EClass

Now start the editor again

- Create a new EClass.
- Copy the EClass to the clipboard using the context-menu.
- Paste the clipboard to the diagram using the context-menu, so that a new EClass is created in the upper-left corner of the diagram (in future versions of the graphics framework it will be possible to paste at the current mouse-location).
- Verify that in the context-menu of a EClass the paste action is disabled.
- Rename the new EClass, and verify that the other EClass is also renamed. This happens, because the implementation only duplicates the graphical pictogram element and not the underlying business-model element.
  Note: it might be necessary to explicitly call the update-action on the other EClass. This is currently in discussion in Graphitti.

Note: The example coding in this tutorial restricts the copy and paste process to the graphical representation. The domain or business objects behind the representation (the EClass objects) will not be copied along. In a real tool implementation this can of course also be modified to also copy the domain objects along with the representation.

Note on performance: The methods canCopy and canPaste are called often, so try to keep them as lightweight as possible to avoid performance issues.

Note: Tools might need to check if a pasted object can be resolved in the scope of the target diagram editor or viewer; objects might e.g. not be reolvable in case they were just created inside another editor and were not yet saved to any resource. In case a pasted object cannot be resolved some special handling might be necessary. This could e.g. be that it is not allowed to paste such objects or that the domain object needs to be created together with its representation in the target diagram; in any case this needs to be handled by the domain editor in a suitable way. The graphiti framework offers the method isResolvable to determine this. An example is shown in the implemented version of the tutorial; it shows how to disable paste in such a case.