blob: cabddef42a74c2c9e0fec96c6508e7ad27cacec7 [file] [log] [blame]
/*******************************************************************************
* 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();
}
}