package org.eclipse.uml2.diagram.timing.edit.policies.create; import org.eclipse.core.commands.ExecutionException; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IProgressMonitor; 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.Request; import org.eclipse.gef.commands.Command; import org.eclipse.gef.editpolicies.AbstractEditPolicy; import org.eclipse.gmf.runtime.common.core.command.CommandResult; import org.eclipse.gmf.runtime.diagram.core.edithelpers.CreateElementRequestAdapter; import org.eclipse.gmf.runtime.diagram.core.services.ViewService; import org.eclipse.gmf.runtime.diagram.core.util.ViewUtil; 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.l10n.DiagramUIMessages; import org.eclipse.gmf.runtime.diagram.ui.requests.CreateViewAndElementRequest; import org.eclipse.gmf.runtime.emf.commands.core.command.CompositeTransactionalCommand; import org.eclipse.gmf.runtime.emf.core.util.EObjectAdapter; import org.eclipse.gmf.runtime.emf.type.core.requests.CreateElementRequest; import org.eclipse.gmf.runtime.notation.Edge; import org.eclipse.gmf.runtime.notation.Node; import org.eclipse.gmf.runtime.notation.View; import org.eclipse.uml2.diagram.common.editpolicies.AbstractPostCreateCommand; import org.eclipse.uml2.diagram.timing.draw2d.SegmentGeometry; import org.eclipse.uml2.diagram.timing.edit.parts.DSegmentEditPart; import org.eclipse.uml2.diagram.timing.edit.parts.DSegmentEndEditPart; import org.eclipse.uml2.diagram.timing.edit.parts.DSegmentStartEditPart; import org.eclipse.uml2.diagram.timing.edit.parts.DStateSwitchEditPart; import org.eclipse.uml2.diagram.timing.edit.policies.SegmentAnchor; import org.eclipse.uml2.diagram.timing.edit.policies.SegmentAnchor.EditPartAndGlobalBounds; import org.eclipse.uml2.diagram.timing.model.timingd.DSegment; import org.eclipse.uml2.diagram.timing.model.timingd.DSegmentEnd; import org.eclipse.uml2.diagram.timing.model.timingd.DSegmentStart; import org.eclipse.uml2.diagram.timing.model.timingd.DStateSwitch; import org.eclipse.uml2.diagram.timing.model.timingd.TimingDFactory; import org.eclipse.uml2.diagram.timing.part.TimingDVisualIDRegistry; import org.eclipse.uml2.diagram.timing.providers.TimingDElementTypes; public class PostCreateSegmentEditPolicy extends AbstractEditPolicy { public static final String ROLE = PostCreateSegmentEditPolicy.class.getName() + ":Role"; @Override public Command getCommand(Request request) { if (understandsRequest(request)){ return getPostCreateCommand((CreateViewAndElementRequest)request); } return null; } @Override public boolean understandsRequest(Request req) { if (false == req instanceof CreateViewAndElementRequest){ return false; } CreateViewAndElementRequest cvaeReq = (CreateViewAndElementRequest)req; CreateElementRequestAdapter requestAdapter = cvaeReq.getViewAndElementDescriptor().getCreateElementRequestAdapter(); CreateElementRequest semanticRequest = (CreateElementRequest) requestAdapter.getAdapter(CreateElementRequest.class); return (semanticRequest.getElementType() == TimingDElementTypes.DSegment_3003); } private Command getPostCreateCommand(CreateViewAndElementRequest cvaeReq){ CompositeTransactionalCommand cc = new CompositeTransactionalCommand(getDomain(), DiagramUIMessages.AddCommand_Label); cc.compose(new PostCreateSegmentCommand(getDomain(), cvaeReq, getHostImpl())); return new ICommandProxy(cc.reduce()); } private IGraphicalEditPart getHostImpl(){ return (IGraphicalEditPart) getHost(); } private TransactionalEditingDomain getDomain(){ return getHostImpl().getEditingDomain(); } private static class PostCreateSegmentCommand extends AbstractPostCreateCommand { public PostCreateSegmentCommand(TransactionalEditingDomain domain, CreateViewAndElementRequest cvaeReq, IGraphicalEditPart hostEditPart){ super(domain, cvaeReq, hostEditPart, TimingDVisualIDRegistry.TYPED_ADAPTER); } @Override protected CommandResult doExecuteWithResult(IProgressMonitor monitor, IAdaptable info) throws ExecutionException { SegmentAnchor anchor = SegmentAnchor.Util.getAnchor(getCreateRequest()); //System.err.println("Anchor: " + anchor); //System.err.println("Location: " + getRequestLocation()); //System.err.println("Size: " + getRequestSize()); View createdView = getCreatedView(); DSegment createdSegment = getCreatedSegment(); //System.err.println("Created View: " + createdView); //System.err.println("Created Segment: " + createdSegment); DSegmentStart segmentStart = createdSegment.getStart(); if (segmentStart == null){ segmentStart = TimingDFactory.eINSTANCE.createDSegmentStart(); createdSegment.setStart(segmentStart); segmentStart.setOccurrence(createdSegment.getStartOccurrence()); } View segmentStartView = findChildByType(createdView, DSegmentStartEditPart.VISUAL_ID); if (segmentStartView == null){ segmentStartView = ViewService.getInstance().createNode(new EObjectAdapter(segmentStart), createdView, null, ViewUtil.APPEND, getPreferencesHint()); } completeOverlappingSegment(anchor, segmentStart, segmentStartView); return CommandResult.newOKCommandResult(); } private void completeOverlappingSegment(SegmentAnchor anchor, DSegmentStart newSegmentStart, View segmentStartView){ if (anchor == null){ return; } EditPartAndGlobalBounds<DSegmentEditPart> oldSegmentData = anchor.getOverlappingSegmentEditPartData(); if (oldSegmentData == null){ return; } View oldSegmentView = oldSegmentData.getNotationView(); DSegment oldSegment = (DSegment) oldSegmentData.getSemanticElement(); if (oldSegment == null || oldSegmentView == null){ return; } if (oldSegment.isClosedSegment()){ DSegmentEnd oldEnd = oldSegment.getEnd(); Node oldEndView = (Node)findChildByType(oldSegmentView, DSegmentEndEditPart.VISUAL_ID); DStateSwitch oldSwitch = oldEnd.getSwitch(); Edge oldSwitchEdge = findOutgoingEdge(oldEndView, DStateSwitchEditPart.VISUAL_ID, oldSwitch); //1) complete just created segment DSegment newSegment = getCreatedSegment(); DSegmentEnd newSegmentEnd = TimingDFactory.eINSTANCE.createDSegmentEnd(); newSegment.setEnd(newSegmentEnd); newSegmentEnd.setOccurrence(oldEnd.getOccurrence()); //? or the new one View newSegmentEndView = ViewService.getInstance().createNode(new EObjectAdapter(newSegmentEnd), getCreatedView(), null, ViewUtil.APPEND, getPreferencesHint()); SemanticHelper.reconnectSource(oldSwitch, newSegmentEnd); oldSwitchEdge.setSource(newSegmentEndView); //2) now old end is free -- connect it to the new start if (oldEnd.getSwitch() != null){ throw new IllegalStateException("How could it happen?"); } Edge newSwitch = createSwitch(oldEndView, segmentStartView); if (newSwitch == null){ throw new IllegalStateException("Can't create switch between: " + oldEndView + ", and " + segmentStartView); } //3) Shrink old segment Rectangle oldBounds = oldSegmentData.getGlobalBounds(); Point splitLocation = getRequestLocation(); Dimension diff = oldBounds.getTopRight().getDifference(splitLocation); setSize(oldSegmentView, new Dimension(oldBounds.getSize().width - diff.width + 2 * SegmentGeometry.CIRCLE_RADIUS, oldBounds.height)); //4) Shrink new segment setSize(getCreatedView(), new Dimension(diff.width, -1)); return; } DSegmentEnd segmentEnd = TimingDFactory.eINSTANCE.createDSegmentEnd(); segmentEnd.setOccurrence(newSegmentStart.getOccurrence()); oldSegment.setEnd(segmentEnd); View segmentEndView = ViewService.getInstance().createNode(new EObjectAdapter(segmentEnd), oldSegmentView, null, ViewUtil.APPEND, getPreferencesHint()); Rectangle oldBounds = oldSegmentData.getGlobalBounds(); Point splitLocation = getRequestLocation(); Dimension completedSize = splitLocation.getDifference(oldBounds.getTopLeft()); completedSize.height = oldBounds.height; completedSize.width += 2 * SegmentGeometry.CIRCLE_RADIUS; setSize(oldSegmentView, completedSize); Dimension newSegmentSize = splitLocation.getDifference(oldBounds.getTopRight()).getNegated(); newSegmentSize.height = oldBounds.height; setSize(getCreatedView(), newSegmentSize); createSwitch(segmentEndView, segmentStartView); } protected Edge createSwitch(View fromView, View toView){ if (false == fromView.getElement() instanceof DSegmentEnd){ throw new IllegalStateException("Switch source should be DSegmentEnd: " + fromView.getElement()); } if (false == toView.getElement() instanceof DSegmentStart){ throw new IllegalStateException("Switch destination should be DSegmentStart: " + toView.getElement()); } return createSwitch(fromView, (DSegmentEnd)fromView.getElement(), toView, (DSegmentStart)toView.getElement()); } protected Edge createSwitch(View fromView, DSegmentEnd from, View toView, DSegmentStart to){ return new CreateSwitchHelper(getPreferencesHint()).createSwitchEdge(fromView, from, toView, to); } private DSegment getCreatedSegment(){ return (DSegment)getCreatedEntity(); } } }