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

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:

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:

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

 

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.