org.eclipse.sirius.diagram.ui.tools.internal.clipboard.SiriusClipboardGlobalActionHandler.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.sirius.diagram.ui.tools.internal.clipboard.SiriusClipboardGlobalActionHandler.java

Source

/*******************************************************************************
 * Copyright (c) 2009, 2015 THALES GLOBAL SERVICES and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Obeo - initial API and implementation
 *******************************************************************************/
package org.eclipse.sirius.diagram.ui.tools.internal.clipboard;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.MessageFormat;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Set;

import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.draw2d.FigureCanvas;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.Request;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.editparts.ScalableFreeformRootEditPart;
import org.eclipse.gmf.runtime.common.core.command.AbstractCommand;
import org.eclipse.gmf.runtime.common.core.command.CommandResult;
import org.eclipse.gmf.runtime.common.core.command.ICommand;
import org.eclipse.gmf.runtime.common.core.command.UnexecutableCommand;
import org.eclipse.gmf.runtime.common.ui.action.global.GlobalActionId;
import org.eclipse.gmf.runtime.common.ui.services.action.global.IGlobalActionContext;
import org.eclipse.gmf.runtime.common.ui.util.CustomData;
import org.eclipse.gmf.runtime.common.ui.util.ICustomData;
import org.eclipse.gmf.runtime.diagram.ui.commands.CommandProxy;
import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
import org.eclipse.gmf.runtime.diagram.ui.parts.IDiagramGraphicalViewer;
import org.eclipse.gmf.runtime.diagram.ui.parts.IDiagramWorkbenchPart;
import org.eclipse.gmf.runtime.diagram.ui.render.internal.providers.ImageSupportGlobalActionHandler;
import org.eclipse.gmf.runtime.emf.commands.core.command.CompositeTransactionalCommand;
import org.eclipse.gmf.runtime.notation.Node;
import org.eclipse.gmf.runtime.notation.View;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.sirius.business.api.session.Session;
import org.eclipse.sirius.business.api.session.SessionManager;
import org.eclipse.sirius.diagram.DDiagram;
import org.eclipse.sirius.diagram.DEdge;
import org.eclipse.sirius.diagram.business.api.query.IEdgeMappingQuery;
import org.eclipse.sirius.diagram.business.internal.query.PasteTargetQuery;
import org.eclipse.sirius.diagram.description.EdgeMapping;
import org.eclipse.sirius.diagram.tools.api.command.IDiagramCommandFactory;
import org.eclipse.sirius.diagram.tools.api.command.IDiagramCommandFactoryProvider;
import org.eclipse.sirius.diagram.tools.internal.command.builders.PasteCommandBuilder;
import org.eclipse.sirius.diagram.ui.business.api.view.SiriusLayoutDataManager;
import org.eclipse.sirius.diagram.ui.business.internal.view.RootLayoutData;
import org.eclipse.sirius.diagram.ui.edit.api.part.IDDiagramEditPart;
import org.eclipse.sirius.diagram.ui.provider.Messages;
import org.eclipse.sirius.diagram.ui.tools.api.command.GMFCommandWrapper;
import org.eclipse.sirius.diagram.ui.tools.api.editor.DDiagramEditor;
import org.eclipse.sirius.diagram.ui.tools.api.util.GMFNotationHelper;
import org.eclipse.sirius.diagram.ui.tools.internal.commands.emf.CopyToSiriusClipboardCommand;
import org.eclipse.sirius.diagram.ui.tools.internal.commands.emf.PasteFromSiriusClipboardCommand;
import org.eclipse.sirius.diagram.ui.tools.internal.delete.DeleteWrapperHookExecutorCommand;
import org.eclipse.sirius.ext.base.Option;
import org.eclipse.sirius.ext.gmf.runtime.editparts.GraphicalHelper;
import org.eclipse.sirius.viewpoint.DSemanticDecorator;
import org.eclipse.sirius.viewpoint.SiriusPlugin;
import org.eclipse.sirius.viewpoint.description.tool.PasteDescription;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IWorkbenchPart;

import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;

/**
 * Handle for clipboard action.
 * 
 * It allows Sirius to make a semantic copy/cut/paste for semantic elements and
 * to let GFM handle notes.
 * 
 * @author glefur
 * 
 */
public class SiriusClipboardGlobalActionHandler extends ImageSupportGlobalActionHandler {

    /**
     * Keep trace of the paste command computed for canPaste : avoid duplicated
     * command buildong operation and mouse location change between.
     */
    private ICommand pasteCommand;

    /**
     * {@inheritDoc}
     * 
     * @see org.eclipse.gmf.runtime.common.ui.action.AbstractGlobalActionHandler#canHandle(IGlobalActionContext)
     */
    @Override
    public boolean canHandle(IGlobalActionContext cntxt) {

        /*
         * Check if the active part is a IDiagramWorkbenchPart and if the
         * selection is a structured selection
         */
        IWorkbenchPart part = cntxt.getActivePart();
        if (!(part instanceof IDiagramWorkbenchPart) || !(cntxt.getSelection() instanceof IStructuredSelection)) {
            return false;
        }

        /* Check the action id */
        boolean canHandle = false;
        String actionId = cntxt.getActionId();
        if (actionId.equals(GlobalActionId.COPY)) {
            canHandle = canCopy(cntxt);
        } else if (actionId.equals(GlobalActionId.CUT)) {
            canHandle = canCut(cntxt);
        } else if (actionId.equals(GlobalActionId.PASTE)) {
            canHandle = canPaste(cntxt);
        }
        return canHandle;
    }

    /**
     * {@inheritDoc}
     * 
     * @see org.eclipse.gmf.runtime.diagram.ui.render.internal.providers.ImageSupportGlobalActionHandler
     *      #canPaste(org.eclipse.gmf.runtime.common.ui.services.action.global.IGlobalActionContext)
     */
    @Override
    public boolean canPaste(IGlobalActionContext cntxt) {
        boolean canPaste = false;
        pasteCommand = null;
        Set<DSemanticDecorator> dSelection = extractDSelection(cntxt);
        if (!dSelection.isEmpty() && cntxt.getActivePart() instanceof IDiagramWorkbenchPart) {
            IDiagramWorkbenchPart activePart = (IDiagramWorkbenchPart) cntxt.getActivePart();
            canPaste = SiriusClipboardManager.getInstance().hasPasteData() || haveNoteToPaste(cntxt);
            if (canPaste) {
                pasteCommand = getPasteCommand(cntxt, activePart);
                canPaste = pasteCommand != null && pasteCommand.canExecute();
            }
        }

        return canPaste;
    }

    private boolean haveNoteToPaste(IGlobalActionContext cntxt) {
        if (super.canPaste(cntxt)) {
            Request pasteReq = createPasteViewRequest();

            // CreateViewRequest is internal in 3.3 and api in 3.5
            Method method = null;
            try {
                method = pasteReq.getClass().getMethod("getData"); //$NON-NLS-1$
            } catch (SecurityException e) {
                // No method, no data
            } catch (NoSuchMethodException e) {
                // No method, no data
            }

            if (method != null) {
                try {
                    Object data = method.invoke(pasteReq);
                    boolean safeData = data != null;
                    if (data instanceof ICustomData[]) {
                        ICustomData[] datas = (ICustomData[]) data;
                        for (ICustomData cusData : datas) {
                            safeData = safeData && cusData != null;

                            if (safeData && cusData instanceof CustomData) {
                                // safeData = safeData && ((CustomData)
                                // cusData).getData() == null;
                                byte[] noteData = ((CustomData) cusData).getData();
                                safeData = safeData && noteData != null && noteData.length != 0;
                            }
                        }
                    }
                    return safeData;
                } catch (IllegalArgumentException e) {
                    // No access, no data
                } catch (IllegalAccessException e) {
                    // No access, no data
                } catch (InvocationTargetException e) {
                    // No access, no data
                }
            }
        }
        return false;
    }

    /**
     * {@inheritDoc}
     * 
     * @see org.eclipse.gmf.runtime.diagram.ui.providers.DiagramGlobalActionHandler
     *      #canCopy(org.eclipse.gmf.runtime.common.ui.services.action.global.IGlobalActionContext)
     */
    @Override
    protected boolean canCopy(IGlobalActionContext cntxt) {
        boolean canCopy = false;

        Set<DSemanticDecorator> dselection = extractDSelection(cntxt);
        canCopy = !dselection.isEmpty() || hasSelectedNotes(cntxt);

        return canCopy;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public ICommand getCommand(IGlobalActionContext cntxt) {
        ICommand command = null;
        if (GlobalActionId.PASTE.equals(cntxt.getActionId())
                && cntxt.getActivePart() instanceof IDiagramWorkbenchPart) {
            command = getPasteCommand(cntxt, (IDiagramWorkbenchPart) cntxt.getActivePart());
        } else if (GlobalActionId.CUT.equals(cntxt.getActionId())
                && cntxt.getActivePart() instanceof IDiagramWorkbenchPart) {
            command = getCutCommand(cntxt, (IDiagramWorkbenchPart) cntxt.getActivePart());
        } else {
            command = super.getCommand(cntxt);
        }
        return command;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected ICommand getCopyCommand(IGlobalActionContext cntxt, IDiagramWorkbenchPart diagramPart,
            boolean isUndoable) {
        // GMF Command to handle notes and image copy for windows.
        ICommand gmfCommand = super.getCopyCommand(cntxt, diagramPart, isUndoable);

        Session session = getSession(diagramPart);
        if (session != null) {
            TransactionalEditingDomain domain = session.getTransactionalEditingDomain();
            Set<DSemanticDecorator> dSelection = extractDSelection(cntxt);
            Set<EObject> semanticSelection = extractSemanticSelection(dSelection);

            minimizeSelection(semanticSelection);

            ICommand cmd = UnexecutableCommand.INSTANCE;
            if (gmfCommand != null) {
                cmd = new CompositeTransactionalCommand(domain, gmfCommand.getLabel());
                cmd.compose(gmfCommand);
                cmd.compose(new GMFCommandWrapper(domain,
                        new CopyToSiriusClipboardCommand(domain, dSelection, semanticSelection)));
            }
            return cmd;
        }

        return gmfCommand;
    }

    /**
     * Overridden to hook deleteHooks on cut command.
     * 
     * {@inheritDoc}
     */
    @Override
    protected ICommand getCutCommand(IGlobalActionContext cntxt, IDiagramWorkbenchPart diagramPart) {
        ICommand cutCommand = super.getCutCommand(cntxt, diagramPart);
        if (cutCommand != null && cutCommand.canExecute()) {
            Session session = getSession(diagramPart);
            if (session != null) {
                TransactionalEditingDomain domain = session.getTransactionalEditingDomain();
                Set<DSemanticDecorator> dSelection = extractDSelection(cntxt);
                cutCommand = new DeleteWrapperHookExecutorCommand(domain, dSelection, cutCommand);
            }
        }
        return cutCommand;
    }

    private void minimizeSelection(Set<? extends EObject> selection) {
        for (EObject selected : Sets.newLinkedHashSet(selection)) {
            EObject cont = selected.eContainer();
            while (cont != null) {
                if (selection.contains(cont)) {
                    selection.remove(selected);
                    cont = null;
                } else {
                    cont = cont.eContainer();
                }
            }
        }
    }

    /**
     * Specific paste command for viewpoint.
     */
    private ICommand getPasteCommand(IGlobalActionContext cntxt, IDiagramWorkbenchPart activePart) {
        if (pasteCommand != null) {
            return pasteCommand;
        }
        ICommand result = UnexecutableCommand.INSTANCE;
        Session session = getSession(activePart);
        DDiagram diag = getDiagram(activePart);
        Set<DSemanticDecorator> dSelection = extractDSelection(cntxt);
        if (session != null && diag != null && !dSelection.isEmpty()) {
            boolean valid = true;
            TransactionalEditingDomain domain = session.getTransactionalEditingDomain();
            CompositeTransactionalCommand cc = new CompositeTransactionalCommand(domain,
                    Messages.SiriusClipboardGlobalActionHandler_pasteCommandLabel);
            valid = fillCompositePasteCommand(cc, domain, dSelection, cntxt, activePart);

            // Append GMF Not paste command
            appendNotePasteCommand(cc, cntxt);

            if (valid) {
                result = cc;
                pasteCommand = cc;
            }
        }
        return result;
    }

    private void appendNotePasteCommand(CompositeTransactionalCommand cc, IGlobalActionContext cntxt) {
        if (haveNoteToPaste(cntxt)) {
            Request pasteReq = createPasteViewRequest();

            /* Get the selected edit parts */
            for (IGraphicalEditPart part : Iterables.filter(((IStructuredSelection) cntxt.getSelection()).toList(),
                    IGraphicalEditPart.class)) {
                /*
                 * Send the request to the target edit part of the paste command
                 * for the currently selected part
                 */
                EditPart targetEP = part.getTargetEditPart(pasteReq);
                if (targetEP != null) {
                    Command paste = targetEP.getCommand(pasteReq);
                    if (paste != null) {
                        cc.compose(new CommandProxy(paste));
                    }
                }
            }
        }
    }

    private boolean hasSelectedNotes(IGlobalActionContext cntxt) {
        if (cntxt.getSelection() instanceof IStructuredSelection) {
            for (IGraphicalEditPart ideep : Iterables.filter(((IStructuredSelection) cntxt.getSelection()).toList(),
                    IGraphicalEditPart.class)) {
                Object model = ideep.getModel();
                if (model instanceof Node && GMFNotationHelper.isNote((Node) model)) {
                    return true;
                }
            }
        }
        return false;
    }

    private boolean fillCompositePasteCommand(CompositeTransactionalCommand cc, TransactionalEditingDomain domain,
            Set<DSemanticDecorator> dSelection, IGlobalActionContext cntxt, IDiagramWorkbenchPart activePart) {
        boolean valid = true;
        Iterator<DSemanticDecorator> dSelIt = dSelection.iterator();
        while (valid && dSelIt.hasNext()) {
            DSemanticDecorator pasteTarget = dSelIt.next();
            valid = fillCompositePasteCommand(pasteTarget, cc, domain, cntxt, activePart);
        }
        return valid;
    }

    private boolean fillCompositePasteCommand(DSemanticDecorator pasteTarget, CompositeTransactionalCommand cc,
            TransactionalEditingDomain domain, IGlobalActionContext cntxt, IDiagramWorkbenchPart activePart) {
        boolean valid = true;

        if (SiriusClipboardManager.getInstance().hasPasteData()) {
            Collection<PasteDescription> tools = new PasteTargetQuery(pasteTarget).getAvailablePasteTools();
            if (tools == null || tools.isEmpty()) {
                valid = appendGenericPasteCommand(pasteTarget, cc, domain);
            } else {
                valid = appendToolPasteCommands(pasteTarget, cc, domain, activePart, tools);
            }
        }

        addLayoutDataCommand(cc, activePart, cntxt);

        return valid;
    }

    private boolean appendToolPasteCommands(DSemanticDecorator pasteTarget, CompositeTransactionalCommand cc,
            TransactionalEditingDomain domain, IDiagramWorkbenchPart activePart,
            Collection<PasteDescription> tools) {
        boolean valid = true;

        // Fill current domain clipboard.
        SiriusClipboardManager.getInstance().setDomainClipboard(domain);

        // Init context
        Collection<DSemanticDecorator> dCopies = Sets.newLinkedHashSet();
        Collection<EObject> dTargetcopies = Sets.newLinkedHashSet();
        Collection<EObject> strictSemanticCopies = Sets.newLinkedHashSet();
        fillPasteContext(domain.getClipboard(), dCopies, dTargetcopies, strictSemanticCopies);

        final IDiagramCommandFactory factory = getDiagramCommandFactory(activePart, domain);

        valid = appendStrictSemanticToolPasteCommands(pasteTarget, cc, domain, tools, strictSemanticCopies,
                factory);
        valid = valid && appendStandardToolPasteCommands(pasteTarget, cc, domain, tools, dCopies, factory);

        domain.setClipboard(null);
        return valid;
    }

    private boolean appendStandardToolPasteCommands(DSemanticDecorator pasteTarget,
            CompositeTransactionalCommand cc, TransactionalEditingDomain domain, Collection<PasteDescription> tools,
            Collection<DSemanticDecorator> dCopies, final IDiagramCommandFactory factory) {
        for (DSemanticDecorator semDecCopy : dCopies) {
            PasteDescription tool = getBestPasteTool(pasteTarget, semDecCopy, semDecCopy.getTarget(), tools);
            if (tool != null) {
                cc.compose(new GMFCommandWrapper(domain,
                        factory.buildPasteCommandFromTool(pasteTarget, semDecCopy, tool)));
            } else {
                // No valid tool -> no paste
                return false;
            }
        }
        return true;
    }

    private boolean appendStrictSemanticToolPasteCommands(DSemanticDecorator pasteTarget,
            CompositeTransactionalCommand cc, TransactionalEditingDomain domain, Collection<PasteDescription> tools,
            Collection<EObject> strictSemanticCopies, final IDiagramCommandFactory factory) {
        for (EObject strictSemanticCopy : strictSemanticCopies) {
            PasteDescription tool = getBestPasteTool(pasteTarget, null, strictSemanticCopy, tools);
            if (tool != null) {
                cc.compose(new GMFCommandWrapper(domain,
                        factory.buildPasteCommandFromTool(pasteTarget, strictSemanticCopy, tool)));
            } else {
                // No valid tool -> no paste
                return false;
            }
        }
        return true;
    }

    private void fillPasteContext(Collection<Object> clipboard, Collection<DSemanticDecorator> dCopies,
            Collection<EObject> dTargetcopies, Collection<EObject> strictSemanticCopies) {
        if (clipboard == null) {
            // No viewpoint data in clipboard.
            return;
        }

        for (EObject obj : Iterables.filter(clipboard, EObject.class)) {
            if (obj instanceof DSemanticDecorator) {
                DSemanticDecorator semDecCopy = (DSemanticDecorator) obj;
                if (semDecCopy.getTarget() != null && isTargetInClipboard(clipboard, semDecCopy)) {
                    dCopies.add(semDecCopy);
                    dTargetcopies.add(semDecCopy.getTarget());
                }
            } else {
                strictSemanticCopies.add(obj);
            }
        }
        Iterables.removeAll(strictSemanticCopies, dTargetcopies);
    }

    private boolean isTargetInClipboard(Collection<Object> clipboard, DSemanticDecorator semDecCopy) {
        EObject target = semDecCopy.getTarget();
        boolean inClipboard = clipboard.contains(target);

        // Minimized semantic selection for copy : check parents.
        if (!inClipboard) {
            EObject targetContainer = EcoreUtil.getRootContainer(target);
            inClipboard = clipboard.contains(targetContainer);
        }

        return inClipboard;
    }

    private boolean appendGenericPasteCommand(DSemanticDecorator pasteTarget, CompositeTransactionalCommand cc,
            TransactionalEditingDomain domain) {
        // Generic behavior for all clipboard
        boolean valid = true;
        if (safeDecorator(pasteTarget)) {
            org.eclipse.emf.common.command.Command pasteFromClipboard = new PasteFromSiriusClipboardCommand(domain,
                    pasteTarget.getTarget());
            cc.setLabel(pasteFromClipboard.getLabel());
            cc.compose(new GMFCommandWrapper(domain, pasteFromClipboard));
        } else {
            valid = false;
        }
        return valid;
    }

    private PasteDescription getBestPasteTool(DSemanticDecorator pasteTarget, DSemanticDecorator semDecCopy,
            EObject copy, Collection<PasteDescription> tools) {
        final Collection<PasteDescription> candidates = Sets.newLinkedHashSet();
        for (PasteDescription tool : tools) {
            if (PasteCommandBuilder.checkPastePrecondition(tool, copy, pasteTarget.getTarget(), pasteTarget,
                    semDecCopy)) {
                candidates.add(tool);
            }
        }
        PasteDescription bestTool = null;
        for (final PasteDescription pasteTool : candidates) {
            if (bestTool == null) {
                bestTool = pasteTool;
            } else {
                SiriusPlugin.getDefault().warning(
                        MessageFormat.format(Messages.SiriusClipboardGlobalActionHandler_severalFoundPasteToolError,
                                pasteTarget.getTarget(), bestTool.getName(), pasteTool.getName()),
                        new RuntimeException());
            }
        }

        return bestTool;
    }

    private IDiagramCommandFactory getDiagramCommandFactory(IDiagramWorkbenchPart activePart,
            TransactionalEditingDomain domain) {
        DDiagramEditor diagramEditor = (DDiagramEditor) activePart.getDiagramGraphicalViewer()
                .getProperty(DDiagramEditor.EDITOR_ID);
        Object adapter = diagramEditor.getAdapter(IDiagramCommandFactoryProvider.class);
        IDiagramCommandFactoryProvider cmdFactoryProvider = (IDiagramCommandFactoryProvider) adapter;
        return cmdFactoryProvider.getCommandFactory(domain);
    }

    private Set<EObject> extractSemanticSelection(Collection<DSemanticDecorator> selection) {
        Set<EObject> selectedSemanticElements = new LinkedHashSet<EObject>();
        for (DSemanticDecorator dec : selection) {
            if (safeDecorator(dec)) {
                selectedSemanticElements.add(dec.getTarget());
            }
        }
        return selectedSemanticElements;
    }

    private Set<DSemanticDecorator> extractDSelection(IGlobalActionContext cntxt) {
        Set<DSemanticDecorator> dSelection = new LinkedHashSet<DSemanticDecorator>();
        if (cntxt.getSelection() instanceof IStructuredSelection) {
            for (IGraphicalEditPart ideep : Iterables.filter(((IStructuredSelection) cntxt.getSelection()).toList(),
                    IGraphicalEditPart.class)) {
                Object model = ideep.getModel();
                if (model instanceof View && ((View) model).getElement() instanceof DSemanticDecorator) {
                    dSelection.add((DSemanticDecorator) ((View) model).getElement());
                }
            }
        }
        return dSelection;
    }

    private boolean safeDecorator(DSemanticDecorator dec) {
        boolean safe = dec.getTarget() != null;
        if (dec instanceof DEdge) {
            Option<EdgeMapping> edgeMapping = new IEdgeMappingQuery(((DEdge) dec).getActualMapping())
                    .getEdgeMapping();
            if (!(edgeMapping.some() && edgeMapping.get().isUseDomainElement())) {
                safe = false;
            }
        }
        return safe;
    }

    private Session getSession(IDiagramWorkbenchPart diagramPart) {
        Session session = null;
        if (diagramPart != null && diagramPart.getDiagram() != null
                && diagramPart.getDiagram().getElement() instanceof DDiagram) {
            DSemanticDecorator diagram = (DSemanticDecorator) diagramPart.getDiagram().getElement();
            session = SessionManager.INSTANCE.getSession(diagram.getTarget());
        }

        return session;
    }

    private DDiagram getDiagram(IDiagramWorkbenchPart diagramPart) {
        DDiagram diag = null;
        if (diagramPart != null && diagramPart.getDiagram() != null
                && diagramPart.getDiagram().getElement() instanceof DDiagram) {
            diag = (DDiagram) diagramPart.getDiagram().getElement();
        }

        return diag;
    }

    private void addLayoutDataCommand(CompositeTransactionalCommand cc, IDiagramWorkbenchPart activePart,
            final IGlobalActionContext cntxt) {
        final Set<DSemanticDecorator> dSelection = extractDSelection(cntxt);
        if (dSelection.size() == 1 && cntxt.getSelection() instanceof IStructuredSelection) {
            final Point cursorLocation = getCursorLocation(activePart,
                    ((IStructuredSelection) cntxt.getSelection()).iterator().next());
            cc.compose(new AbstractCommand(Messages.SiriusClipboardGlobalActionHandler_addLayoutDataCommandLabel) {

                @Override
                protected CommandResult doUndoWithResult(IProgressMonitor progressMonitor, IAdaptable info)
                        throws ExecutionException {
                    return CommandResult.newOKCommandResult();
                }

                @Override
                protected CommandResult doRedoWithResult(IProgressMonitor progressMonitor, IAdaptable info)
                        throws ExecutionException {
                    return CommandResult.newOKCommandResult();
                }

                @Override
                protected CommandResult doExecuteWithResult(IProgressMonitor progressMonitor, IAdaptable info)
                        throws ExecutionException {
                    DSemanticDecorator target = dSelection.iterator().next();
                    if (target instanceof DEdge) {
                        DDiagram parentDiagram = ((DEdge) target).getParentDiagram();
                        if (parentDiagram instanceof DSemanticDecorator) {
                            target = (DSemanticDecorator) parentDiagram;
                        }
                    }
                    SiriusLayoutDataManager.INSTANCE
                            .addData(new RootLayoutData(target, cursorLocation, new Dimension(-1, -1)));
                    return CommandResult.newOKCommandResult();
                }
            });
        }
    }

    /**
     * @param object
     * 
     */
    private Point getCursorLocation(IDiagramWorkbenchPart activePart, Object selectedPart) {
        Point loc = null;
        Display current = Display.getCurrent();
        IDiagramGraphicalViewer viewer = activePart.getDiagramGraphicalViewer();
        if (viewer != null && viewer.getControl() instanceof FigureCanvas && current != null) {
            final org.eclipse.swt.graphics.Point cursorLocation = current.getCursorLocation();
            final FigureCanvas control = (FigureCanvas) viewer.getControl();
            final org.eclipse.swt.graphics.Point relativeSWTPoint = control.toControl(cursorLocation);

            final Point point = new Point(relativeSWTPoint.x, relativeSWTPoint.y);
            Point after = point.getCopy();
            control.getViewport().translateFromParent(after);

            final double zoom = ((ScalableFreeformRootEditPart) viewer.getRootEditPart()).getZoomManager()
                    .getZoom();
            loc = after.getScaled(1 / zoom);

            if (!(selectedPart instanceof IDDiagramEditPart)) {
                IGraphicalEditPart part = (IGraphicalEditPart) selectedPart;
                // useLocalCoordinate == false : translate will do nothing
                Point parentLoc = part.getFigure().getBounds().getLocation().getCopy();
                GraphicalHelper.logical2screen(parentLoc, part);
                control.getViewport().translateFromParent(parentLoc);
                loc = loc.getTranslated(parentLoc.getNegated());
            }
        }
        return loc;
    }

}