package org.eclipse.papyrus.uml.diagram.statemachine.custom.policies; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.draw2d.ColorConstants; import org.eclipse.draw2d.FigureUtilities; import org.eclipse.draw2d.Graphics; import org.eclipse.draw2d.IFigure; import org.eclipse.draw2d.RectangleFigure; import org.eclipse.draw2d.Shape; import org.eclipse.draw2d.geometry.Point; import org.eclipse.draw2d.geometry.PrecisionRectangle; import org.eclipse.draw2d.geometry.Rectangle; import org.eclipse.emf.transaction.TransactionalEditingDomain; import org.eclipse.gef.EditPart; import org.eclipse.gef.LayerConstants; import org.eclipse.gef.Request; import org.eclipse.gef.commands.Command; import org.eclipse.gef.editparts.LayerManager; import org.eclipse.gef.requests.ChangeBoundsRequest; import org.eclipse.gef.requests.CreateRequest; import org.eclipse.gmf.runtime.diagram.ui.commands.ICommandProxy; import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart; import org.eclipse.gmf.runtime.diagram.ui.editparts.ShapeCompartmentEditPart; import org.eclipse.gmf.runtime.diagram.ui.editpolicies.CreationEditPolicy; import org.eclipse.gmf.runtime.diagram.ui.l10n.DiagramUIMessages; import org.eclipse.gmf.runtime.diagram.ui.requests.CreateUnspecifiedTypeRequest; import org.eclipse.gmf.runtime.diagram.ui.requests.DropObjectsRequest; import org.eclipse.gmf.runtime.emf.commands.core.command.CompositeTransactionalCommand; import org.eclipse.gmf.runtime.emf.type.core.IElementType; import org.eclipse.gmf.runtime.emf.type.core.IHintedType; import org.eclipse.gmf.runtime.notation.View; import org.eclipse.papyrus.uml.diagram.common.commands.SemanticAdapter; import org.eclipse.papyrus.uml.diagram.statemachine.custom.commands.CustomRegionCreateElementCommand; import org.eclipse.papyrus.uml.diagram.statemachine.custom.figures.RegionFigure; import org.eclipse.papyrus.uml.diagram.statemachine.custom.helpers.Zone; import org.eclipse.papyrus.uml.diagram.statemachine.edit.parts.RegionEditPart; import org.eclipse.papyrus.uml.diagram.statemachine.providers.UMLElementTypes; public class CustomRegionCompartmentCreationEditPolicy extends CreationEditPolicy { IFigure sizeOnDropFeedback = null; String dropLocation = Zone.RIGHT; @Override public void eraseTargetFeedback(Request request) { if(sizeOnDropFeedback != null) { LayerManager.Helper.find(getHost()).getLayer(LayerConstants.FEEDBACK_LAYER).remove(sizeOnDropFeedback); sizeOnDropFeedback = null; } } @Override public Command getCommand(Request request) { // CHECK THIS TransactionalEditingDomain editingDomain = ((IGraphicalEditPart)getHost()).getEditingDomain(); CompositeTransactionalCommand cc = new CompositeTransactionalCommand(editingDomain, DiagramUIMessages.AddCommand_Label); if(understandsRequest(request)) { if(request instanceof CreateUnspecifiedTypeRequest) { CreateUnspecifiedTypeRequest unspecReq = (CreateUnspecifiedTypeRequest)request; for(Iterator iter = unspecReq.getElementTypes().iterator(); iter.hasNext();) { IElementType elementType = (IElementType)iter.next(); CreateRequest createRequest = unspecReq.getRequestForType(elementType); if(((IHintedType)elementType).getSemanticHint().equals(((IHintedType)UMLElementTypes.Region_3000).getSemanticHint())) { // starting point is the existing region compartment on // which mouse was moving View existingRegionCompartmentView = (View)getHost().getModel(); // the existing region view View existingRegionView = (View)existingRegionCompartmentView.eContainer(); // get and adaptable for it, to pass on to commands IAdaptable adaptableForExistingRegionView = (IAdaptable)new SemanticAdapter(null, existingRegionView); // do the whole job CustomRegionCreateElementCommand createNewRegion = new CustomRegionCreateElementCommand(adaptableForExistingRegionView, null, ((IGraphicalEditPart)getHost()).getDiagramPreferencesHint(), editingDomain, DiagramUIMessages.CreateCommand_Label, dropLocation); cc.compose(createNewRegion); return new ICommandProxy(cc.reduce()); } } } else if(request instanceof ChangeBoundsRequest) { ChangeBoundsRequest changeBoundsRequest = (ChangeBoundsRequest)request; Point mouseLocation = changeBoundsRequest.getLocation(); DropObjectsRequest dropRequest = new DropObjectsRequest(); dropRequest.setLocation(mouseLocation); List<View> list = new ArrayList<View>(); Iterator<EditPart> it = changeBoundsRequest.getEditParts().iterator(); while(it.hasNext()) { EditPart ep = it.next(); if(ep instanceof RegionEditPart) { View regionToDrag = (View)ep.getModel(); list.add(regionToDrag); } } dropRequest.setObjects(list); return getHost().getCommand(dropRequest); } return super.getCommand(request); } return null; } protected IFigure getSizeOnDropFeedback() { if(sizeOnDropFeedback == null) { sizeOnDropFeedback = new RectangleFigure(); FigureUtilities.makeGhostShape((Shape)sizeOnDropFeedback); ((Shape)sizeOnDropFeedback).setLineStyle(Graphics.LINE_DASHDOT); sizeOnDropFeedback.setForegroundColor(ColorConstants.white); LayerManager.Helper.find(getHost()).getLayer(LayerConstants.FEEDBACK_LAYER).add(sizeOnDropFeedback); } return sizeOnDropFeedback; } @Override public EditPart getTargetEditPart(Request request) { if(request instanceof CreateUnspecifiedTypeRequest) { CreateUnspecifiedTypeRequest createUnspecifiedTypeRequest = (CreateUnspecifiedTypeRequest)request; if(understandsRequest(request)) { List<?> elementTypes = createUnspecifiedTypeRequest.getElementTypes(); // Treat the case where only one element type is listed // Only take EntryPoint or ExitPoint element type into account if((elementTypes.size() == 1) && (((IElementType)(elementTypes.get(0)) == UMLElementTypes.Pseudostate_16000) || ((IElementType)(elementTypes.get(0)) == UMLElementTypes.Pseudostate_17000))) { // If the target is a compartment replace by its grand parent edit part if((getHost() instanceof ShapeCompartmentEditPart)) { return getHost().getParent().getParent().getParent(); } } } } return super.getTargetEditPart(request); } @Override public void showTargetFeedback(Request request) { if(request instanceof CreateUnspecifiedTypeRequest) { CreateUnspecifiedTypeRequest unspecReq = (CreateUnspecifiedTypeRequest)request; for(Iterator iter = unspecReq.getElementTypes().iterator(); iter.hasNext();) { IElementType elementType = (IElementType)iter.next(); if(elementType.equals(UMLElementTypes.Region_3000)) { RegionFigure targetFig = ((RegionEditPart)getHost().getParent()).getPrimaryShape(); // make a local copy Rectangle targetFigBounds = targetFig.getBounds().getCopy(); // transform the coordinates to absolute targetFig.translateToAbsolute(targetFigBounds); // retrieve mouse location Point mouseLocation = unspecReq.getLocation(); // get the drop location, i.e. RIGHT, LEFT, TOP, BOTTOM dropLocation = Zone.getZoneFromLocationInRectangleWithAbsoluteCoordinates(mouseLocation, targetFigBounds); // perform corresponding change (scaling, translation) on // targetFigBounds // and updates the graph node drop location property if(Zone.isTop(dropLocation)) { targetFigBounds.setSize(targetFigBounds.getSize().scale(1.0, 0.5)); } else if(Zone.isLeft(dropLocation)) { targetFigBounds.setSize(targetFigBounds.getSize().scale(0.5, 1.0)); } else if(Zone.isRight(dropLocation)) { targetFigBounds.setSize(targetFigBounds.getSize().scale(0.5, 1.0)); targetFigBounds.translate(targetFigBounds.width, 0); } else if(Zone.isBottom(dropLocation)) { targetFigBounds.setSize(targetFigBounds.getSize().scale(1.0, 0.5)); targetFigBounds.translate(0, targetFigBounds.height); } getSizeOnDropFeedback().setBounds(new PrecisionRectangle(targetFigBounds)); } } } } }