/******************************************************************************* * Copyright (c) 2011, 2012, 2013 Red Hat, Inc. * All rights reserved. * This program is 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: * Red Hat, Inc. - initial API and implementation ******************************************************************************/ package org.eclipse.bpmn2.modeler.core.features; import java.util.ArrayList; import java.util.List; import org.eclipse.bpmn2.BaseElement; import org.eclipse.bpmn2.modeler.core.utils.BusinessObjectUtil; import org.eclipse.graphiti.features.IFeatureProvider; import org.eclipse.graphiti.features.context.ICopyContext; import org.eclipse.graphiti.mm.pictograms.Anchor; import org.eclipse.graphiti.mm.pictograms.Connection; import org.eclipse.graphiti.mm.pictograms.ContainerShape; import org.eclipse.graphiti.mm.pictograms.PictogramElement; import org.eclipse.graphiti.ui.features.AbstractCopyFeature; /** * Default Graphiti {@code CopyFeature} base class for all BPMN2 model elements which * are associated with BPMN DI elements. */ public class DefaultCopyBPMNElementFeature extends AbstractCopyFeature { /** * Instantiates a new default {@code CopyFeature). * * @param fp the Feature Provider */ public DefaultCopyBPMNElementFeature(IFeatureProvider fp) { super(fp); } /* (non-Javadoc) * @see org.eclipse.graphiti.features.ICopyFeature#canCopy(org.eclipse.graphiti.features.context.ICopyContext) */ @Override 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 have linked BaseElements for (PictogramElement pe : pes) { final Object bo = BusinessObjectUtil.getFirstBaseElement(pe); if (!(bo instanceof BaseElement)) { return false; } } return true; } /* (non-Javadoc) * @see org.eclipse.graphiti.features.ICopyFeature#copy(org.eclipse.graphiti.features.context.ICopyContext) */ @Override public void copy(ICopyContext context) { PictogramElement[] pes = context.getPictogramElements(); List<PictogramElement> copied = new ArrayList<PictogramElement>(); for (int i = 0; i < pes.length; i++) { PictogramElement pe = pes[i]; // only copy connections if both source and target Shapes // are also selected (i.e. don't copy a "dangling" connection) if (pe instanceof Connection) { Connection connection = (Connection)pe; PictogramElement source = connection.getStart().getParent(); PictogramElement target = connection.getEnd().getParent(); boolean containsSource = false; boolean containsTarget = false; for (PictogramElement p : pes) { if (source==p) containsSource = true; else if (target==p) containsTarget = true; } if (containsSource && containsTarget) { copied.add(pe); } } else { copied.add(pe); } } // include all connections between the selected shapes, even if they // are not selected. copied.addAll(findAllConnections(copied)); // remove PEs that are contained in FlowElementsContainers List<PictogramElement> ignored = new ArrayList<PictogramElement>(); for (PictogramElement pe : copied) { if (pe instanceof ContainerShape) { for (PictogramElement childPe : ((ContainerShape) pe).getChildren()) { if (copied.contains(childPe)) ignored.add(childPe); } } } copied.removeAll(ignored); // copy all PictogramElements to the clipboard putToClipboard(copied.toArray()); } /** * Find all outgoing and incoming connections attached to the given list of shapes. * * @param shapes the shapes * @return a list of connections */ public static List<Connection> findAllConnections(List<PictogramElement> shapes) { List<Connection> connections = new ArrayList<Connection>(); for (PictogramElement pe : shapes) { if (pe instanceof ContainerShape) { ContainerShape shape = (ContainerShape)pe; for (Anchor a : shape.getAnchors()) { for (Connection c : a.getIncomingConnections()) { if ( (shapes.contains(c.getStart().getParent()) || shapes.contains(c.getEnd().getParent())) && !shapes.contains(c) && !connections.contains(c)) { connections.add(c); } } for (Connection c : a.getOutgoingConnections()) { if ( (shapes.contains(c.getStart().getParent()) || shapes.contains(c.getEnd().getParent())) && !shapes.contains(c) && !connections.contains(c)) { connections.add(c); } } } } } return connections; } }