package org.eclipse.papyrus.uml.diagram.statemachine.custom.policies;
import java.util.Iterator;
import org.eclipse.draw2d.PositionConstants;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.EditPolicy;
import org.eclipse.gef.Request;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.editpolicies.LayoutEditPolicy;
import org.eclipse.gef.editpolicies.NonResizableEditPolicy;
import org.eclipse.gef.requests.CreateRequest;
import org.eclipse.gmf.runtime.diagram.ui.commands.ICommandProxy;
import org.eclipse.gmf.runtime.diagram.ui.commands.SetBoundsCommand;
import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
import org.eclipse.gmf.runtime.diagram.ui.l10n.DiagramUIMessages;
import org.eclipse.gmf.runtime.diagram.ui.requests.CreateViewAndElementRequest;
import org.eclipse.gmf.runtime.diagram.ui.requests.CreateViewRequest;
import org.eclipse.gmf.runtime.emf.commands.core.command.CompositeTransactionalCommand;
import org.eclipse.gmf.runtime.notation.View;
import org.eclipse.papyrus.uml.diagram.common.editpolicies.BorderItemResizableEditPolicy;
import org.eclipse.papyrus.uml.diagram.statemachine.custom.locators.CustomEntryExitPointPositionLocator;
import org.eclipse.papyrus.uml.diagram.statemachine.edit.parts.PseudostateEntryPointEditPart;
import org.eclipse.papyrus.uml.diagram.statemachine.edit.parts.PseudostateExitPointEditPart;
import org.eclipse.papyrus.uml.diagram.statemachine.part.UMLVisualIDRegistry;
/**
* This edit policy replaces the GMF generated edit policy for StateMachine(s).
* In particular it provides a getCreateCommands that add a ChangeBoundRequest on a created Entry/ExitPoint
* in order to locate it at the cursor position.
*/
public class CustomStateMachineLayoutEditPolicy extends LayoutEditPolicy {
@Override
protected EditPolicy createChildEditPolicy(EditPart child) {
View childView = (View)child.getModel();
switch(UMLVisualIDRegistry.getVisualID(childView)) {
case PseudostateEntryPointEditPart.VISUAL_ID:
case PseudostateExitPointEditPart.VISUAL_ID:
return new BorderItemResizableEditPolicy();
}
EditPolicy result = child.getEditPolicy(EditPolicy.PRIMARY_DRAG_ROLE);
if(result == null) {
result = new NonResizableEditPolicy();
}
return result;
}
@Override
public Command getCommand(Request request) {
// TODO Auto-generated method stub
return super.getCommand(request);
}
@Override
protected Command getCreateCommand(CreateRequest request) {
if(request instanceof CreateViewAndElementRequest) {
CreateViewAndElementRequest req = (CreateViewAndElementRequest)request;
TransactionalEditingDomain editingDomain = ((IGraphicalEditPart)getHost()).getEditingDomain();
CompositeTransactionalCommand cc = new CompositeTransactionalCommand(editingDomain, DiagramUIMessages.AddCommand_Label);
Iterator<?> iter = req.getViewDescriptors().iterator();
// Retrieve parent location
Point parentLoc = getHostFigure().getBounds().getLocation().getCopy();
// Compute relative creation location
Point requestedLocation = request.getLocation().getCopy();
getHostFigure().translateToRelative(requestedLocation);
// Create proposed creation bounds and use the locator to find the expected position
CustomEntryExitPointPositionLocator locator = new CustomEntryExitPointPositionLocator(getHostFigure(), PositionConstants.NONE);
Rectangle proposedBounds = new Rectangle(requestedLocation, new Dimension(20, 20));
Rectangle preferredBounds = locator.getPreferredLocation(proposedBounds);
// Convert the calculated preferred bounds as relative to parent location
Rectangle creationBounds = preferredBounds.getTranslated(parentLoc.getNegated());
while(iter.hasNext()) {
CreateViewRequest.ViewDescriptor viewDescriptor = (CreateViewRequest.ViewDescriptor)iter.next();
cc.compose(new SetBoundsCommand(editingDomain, DiagramUIMessages.SetLocationCommand_Label_Resize, viewDescriptor, creationBounds));
}
if(cc.reduce() == null)
return null;
return new ICommandProxy(cc.reduce());
}
return null;
}
@Override
protected Command getMoveChildrenCommand(Request request) {
return null;
}
}