| /******************************************************************************* |
| * Copyright (c) 2011, 2012 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 |
| * |
| * @author Ivar Meikas |
| ******************************************************************************/ |
| package org.eclipse.bpmn2.modeler.core.features; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| import org.eclipse.bpmn2.Group; |
| import org.eclipse.bpmn2.SubProcess; |
| import org.eclipse.bpmn2.modeler.core.LifecycleEvent; |
| import org.eclipse.bpmn2.modeler.core.LifecycleEvent.EventType; |
| import org.eclipse.bpmn2.modeler.core.di.DIUtils; |
| import org.eclipse.bpmn2.modeler.core.runtime.TargetRuntime; |
| import org.eclipse.bpmn2.modeler.core.utils.BusinessObjectUtil; |
| import org.eclipse.bpmn2.modeler.core.utils.FeatureSupport; |
| import org.eclipse.bpmn2.modeler.core.utils.GraphicsUtil; |
| import org.eclipse.graphiti.datatypes.ILocation; |
| import org.eclipse.graphiti.features.IFeatureProvider; |
| import org.eclipse.graphiti.features.context.IMoveShapeContext; |
| import org.eclipse.graphiti.features.context.impl.MoveShapeContext; |
| import org.eclipse.graphiti.features.impl.DefaultMoveShapeFeature; |
| import org.eclipse.graphiti.mm.algorithms.styles.Point; |
| import org.eclipse.graphiti.mm.pictograms.Anchor; |
| import org.eclipse.graphiti.mm.pictograms.AnchorContainer; |
| 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.mm.pictograms.Shape; |
| import org.eclipse.graphiti.services.Graphiti; |
| import org.eclipse.graphiti.ui.editor.DiagramEditor; |
| |
| /** |
| * Default Graphiti {@code MoveShapeFeature} class for Shapes. |
| * <p> |
| */ |
| public class DefaultMoveBPMNShapeFeature extends DefaultMoveShapeFeature { |
| |
| /** The shape's location before the move. */ |
| protected ILocation preMoveLoc; |
| protected PictogramElement[] selectedShapes = null; |
| |
| /** |
| * Instantiates a new default MoveShapeFature. |
| * |
| * @param fp the Feature Provider |
| */ |
| public DefaultMoveBPMNShapeFeature(IFeatureProvider fp) { |
| super(fp); |
| selectedShapes = fp.getDiagramTypeProvider().getDiagramBehavior().getDiagramContainer().getSelectedPictogramElements(); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.graphiti.features.impl.DefaultMoveShapeFeature#canMoveShape(org.eclipse.graphiti.features.context.IMoveShapeContext) |
| */ |
| public boolean canMoveShape(IMoveShapeContext context) { |
| if (Graphiti.getPeService().getProperty(context.getShape(), RoutingNet.LANE)!=null) { |
| return false; |
| } |
| if (FeatureSupport.isLabelShape(context.getPictogramElement())) |
| return false; |
| ContainerShape targetContainer = context.getTargetContainer(); |
| if (FeatureSupport.isLabelShape(targetContainer)) |
| return false; // can't move a shape into a label |
| |
| if (BusinessObjectUtil.getFirstBaseElement(targetContainer) instanceof Group) { |
| // can't move ANYTHING into a Group |
| return false; |
| } |
| if (Graphiti.getPeService().getProperty(targetContainer, RoutingNet.LANE)!=null) { |
| int x = context.getX(); |
| int y = context.getY(); |
| ILocation loc = Graphiti.getPeService().getLocationRelativeToDiagram(targetContainer); |
| ((MoveShapeContext)context).setX(x + loc.getX()); |
| ((MoveShapeContext)context).setY(y + loc.getY()); |
| ((MoveShapeContext)context).setSourceContainer(targetContainer.getContainer()); |
| ((MoveShapeContext)context).setTargetContainer(targetContainer.getContainer()); |
| } |
| |
| boolean doit = true; |
| // context.getSourceContainer() != null && context.getSourceContainer().equals(context.getTargetContainer()); |
| TargetRuntime rt = TargetRuntime.getRuntime(context.getPictogramElement()); |
| LifecycleEvent event = new LifecycleEvent(EventType.PICTOGRAMELEMENT_CAN_MOVE, |
| getFeatureProvider(), context, context.getPictogramElement(), rt); |
| event.doit = doit; |
| LifecycleEvent.notify(event); |
| return event.doit; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.graphiti.features.impl.DefaultMoveShapeFeature#moveShape(org.eclipse.graphiti.features.context.IMoveShapeContext) |
| */ |
| @Override |
| public void moveShape(IMoveShapeContext context) { |
| TargetRuntime rt = TargetRuntime.getRuntime(context.getPictogramElement()); |
| LifecycleEvent.notify(new LifecycleEvent(EventType.PICTOGRAMELEMENT_PRE_MOVE, |
| getFeatureProvider(), context, context.getPictogramElement(), rt)); |
| |
| super.moveShape(context); |
| |
| LifecycleEvent.notify(new LifecycleEvent(EventType.PICTOGRAMELEMENT_POST_MOVE, |
| getFeatureProvider(), context, context.getPictogramElement(), rt)); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.graphiti.features.impl.DefaultMoveShapeFeature#preMoveShape(org.eclipse.graphiti.features.context.IMoveShapeContext) |
| */ |
| @Override |
| protected void preMoveShape(IMoveShapeContext context) { |
| preMoveLoc = Graphiti.getLayoutService().getLocationRelativeToDiagram(context.getShape()); |
| super.preMoveShape(context); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.graphiti.features.impl.DefaultMoveShapeFeature#postMoveShape(org.eclipse.graphiti.features.context.IMoveShapeContext) |
| */ |
| @Override |
| protected void postMoveShape(IMoveShapeContext context) { |
| Shape shape = context.getShape(); |
| Point p = null; |
| |
| ILocation postMoveLoc = Graphiti.getPeService().getLocationRelativeToDiagram(shape); |
| int deltaX = postMoveLoc.getX()-preMoveLoc.getX(); |
| int deltaY = postMoveLoc.getY()-preMoveLoc.getY(); |
| /* |
| * If the shape being moved has a Label and the Label is |
| * {@link org.eclipse.bpmn2.modeler.core.preferences.ShapeStyle.LabelPosition.MOVABLE} |
| * then adjust the Label position by the move offset. |
| */ |
| if (!FeatureSupport.isLabelShape(shape)) { |
| p = GraphicsUtil.createPoint(deltaX, deltaY); |
| DIUtils.updateDIShape(shape); |
| FeatureSupport.updateLabel(getFeatureProvider(), shape, p); |
| } |
| |
| |
| if (shape instanceof ContainerShape) { |
| PictogramElement pe = (PictogramElement) ((ContainerShape)shape).eContainer(); |
| if (BusinessObjectUtil.containsElementOfType(pe, SubProcess.class)) { |
| layoutPictogramElement(pe); |
| } |
| } |
| |
| // if multiple shapes are being moved, only update the connections |
| // after all of them have been moved. This is to avoid relocating |
| // connections unnecessarily as each shape is moved. |
| if (shape==selectedShapes[ selectedShapes.length-1 ]) { |
| List<AnchorContainer> movedShapes = new ArrayList<AnchorContainer>(); |
| for (int i=0; i<selectedShapes.length; ++i) { |
| movedShapes.add((AnchorContainer)selectedShapes[i]); |
| } |
| FeatureSupport.updateConnections(getFeatureProvider(), movedShapes); |
| } |
| |
| // Handle the case where a shape was moved such that it now collides |
| // with an existing connection |
| for (Connection connection : getDiagram().getConnections()) { |
| if (!FeatureSupport.getConnections(shape).contains(connection) && |
| GraphicsUtil.intersects(shape, connection)) { |
| FeatureSupport.updateConnection(getFeatureProvider(), connection); |
| } |
| } |
| |
| FeatureSupport.updateCategoryValues(getFeatureProvider(), shape); |
| |
| for (Anchor a : shape.getAnchors()) { |
| for (Connection c : a.getIncomingConnections()) { |
| FeatureSupport.updateCategoryValues(getFeatureProvider(), c); |
| } |
| for (Connection c : a.getOutgoingConnections()) { |
| FeatureSupport.updateCategoryValues(getFeatureProvider(), c); |
| } |
| } |
| } |
| |
| protected DiagramEditor getDiagramEditor() { |
| return (DiagramEditor)getFeatureProvider().getDiagramTypeProvider().getDiagramBehavior().getDiagramContainer(); |
| } |
| } |