package org.eclipse.papyrus.uml.diagram.sequence.apex.edit.policies;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import org.eclipse.draw2d.Connection;
import org.eclipse.draw2d.FigureCanvas;
import org.eclipse.draw2d.Graphics;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.PolylineConnection;
import org.eclipse.draw2d.PositionConstants;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.PointList;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.gef.ConnectionEditPart;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.EditPartViewer;
import org.eclipse.gef.Request;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.commands.CompoundCommand;
import org.eclipse.gef.commands.UnexecutableCommand;
import org.eclipse.gef.editpolicies.SelectionHandlesEditPolicy;
import org.eclipse.gef.requests.ChangeBoundsRequest;
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.ConnectionNodeEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editparts.GraphicalEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editparts.ShapeNodeEditPart;
import org.eclipse.gmf.runtime.diagram.ui.requests.CreateViewRequest.ViewDescriptor;
import org.eclipse.papyrus.uml.diagram.sequence.apex.command.ApexMoveInteractionFragmentsCommand;
import org.eclipse.papyrus.uml.diagram.sequence.apex.interfaces.IApexLifelineEditPart;
import org.eclipse.papyrus.uml.diagram.sequence.apex.util.ApexSequenceDiagramConstants;
import org.eclipse.papyrus.uml.diagram.sequence.apex.util.ApexSequenceUtil;
import org.eclipse.papyrus.uml.diagram.sequence.edit.parts.LifelineEditPart;
import org.eclipse.papyrus.uml.diagram.sequence.edit.policies.InteractionCompartmentXYLayoutEditPolicy;
import org.eclipse.papyrus.uml.diagram.sequence.util.OccurrenceSpecificationMoveHelper;
import org.eclipse.papyrus.uml.diagram.sequence.util.SequenceRequestConstant;
import org.eclipse.papyrus.uml.diagram.sequence.util.SequenceUtil;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Control;
import org.eclipse.uml2.uml.ExecutionSpecification;
import org.eclipse.uml2.uml.InteractionFragment;
import org.eclipse.uml2.uml.Message;
import org.eclipse.uml2.uml.MessageEnd;
import org.eclipse.uml2.uml.MessageOccurrenceSpecification;
import org.eclipse.uml2.uml.OccurrenceSpecification;
/**
* @author Jiho
*
*/
public class ApexConnectionMoveEditPolicy extends SelectionHandlesEditPolicy {
public final static String CONNECTION_MOVE_ROLE = "ApexConnectionMoveEditPolicy"; //$NON-NLS-1$
private static final int MARGIN = ApexSequenceDiagramConstants.VERTICAL_MARGIN;
private static final int PADDING = ApexSequenceDiagramConstants.EXECUTION_PADDING;
private static final int NEAR_LINE_MARGIN = 2;
private static final int NEAR_LINE_TOLERANCE = 10;
private static boolean flexiblePrev = false;
private PolylineConnection feedback;
private PolylineConnection guideFeedback;
@Override
protected List<Object> createSelectionHandles() {
List<Object> list = new ArrayList<Object>();
return list;
}
/**
* Returns the Connection associated with this EditPolicy.
*/
protected Connection getConnection() {
return (Connection) ((ConnectionEditPart) getHost()).getFigure();
}
@Override
public Command getCommand(Request request) {
if (request instanceof ChangeBoundsRequest) {
if (REQ_MOVE.equals(request.getType())) {
return getMoveConnectionCommand((ChangeBoundsRequest)request);
}
}
return super.getCommand(request);
}
protected Command getMoveConnectionCommand(ChangeBoundsRequest request) {
if(getHost() instanceof ConnectionNodeEditPart) {
ConnectionNodeEditPart connectionPart = (ConnectionNodeEditPart)getHost();
TransactionalEditingDomain editingDomain = connectionPart.getEditingDomain();
EditPartViewer viewer = connectionPart.getViewer();
Message message = (Message)connectionPart.resolveSemanticElement();
MessageEnd sendEvent = message.getSendEvent();
InteractionFragment container = null;
if (sendEvent instanceof MessageOccurrenceSpecification) {
container = ((MessageOccurrenceSpecification)sendEvent).getEnclosingOperand();
if (container == null) {
container = ((MessageOccurrenceSpecification)sendEvent).getEnclosingInteraction();
}
}
if (container == null) {
return null;
}
Point moveDelta = new Point(0, request.getMoveDelta().y());
Point oldLocation = SequenceUtil.getAbsoluteEdgeExtremity(connectionPart, true);
ApexMoveInteractionFragmentsCommand amifCommand = new ApexMoveInteractionFragmentsCommand(
editingDomain, viewer, container, oldLocation, moveDelta, MARGIN);
Command result = new ICommandProxy(amifCommand);
return result;
}
return UnexecutableCommand.INSTANCE;
}
private Command getReorderingCommand(ChangeBoundsRequest request) {
ConnectionNodeEditPart host = (ConnectionNodeEditPart)getHost();
Point location = request.getLocation().getCopy();
Integer[] reorderingLocations = ApexSequenceUtil.apexGetReorderingLocations(host, location);
Integer nearLocation = null;
for (Integer reorderingLocation : reorderingLocations) {
if ((nearLocation != null && Math.abs(nearLocation + NEAR_LINE_MARGIN - location.y) > Math.abs(reorderingLocation + NEAR_LINE_MARGIN - location.y)) ||
(Math.abs(reorderingLocation + NEAR_LINE_MARGIN - location.y) < NEAR_LINE_TOLERANCE)) {
nearLocation = reorderingLocation;
}
}
if (nearLocation != null) {
Point moveDelta = new Point();
TransactionalEditingDomain editingDomain = host.getEditingDomain();
ViewDescriptor descriptor = (ViewDescriptor) host.getAdapter(ViewDescriptor.class);
EditPartViewer viewer = host.getViewer();
}
return null;
}
/**
*
* @param request
* @param connectionPart
* @param moveAlone
* @return
*/
public static Command apexGetMoveConnectionCommand(ChangeBoundsRequest request, ConnectionNodeEditPart connectionPart, boolean moveAlone) {
EObject message = connectionPart.resolveSemanticElement();
if(message instanceof Message) {
MessageEnd send = ((Message)message).getSendEvent();
MessageEnd rcv = ((Message)message).getReceiveEvent();
EditPart srcPart = connectionPart.getSource();
LifelineEditPart srcLifelinePart = SequenceUtil.getParentLifelinePart(srcPart);
EditPart tgtPart = connectionPart.getTarget();
LifelineEditPart tgtLifelinePart = SequenceUtil.getParentLifelinePart(tgtPart);
CompoundCommand compoudCmd = new CompoundCommand("Move Message");
if(send instanceof OccurrenceSpecification && rcv instanceof OccurrenceSpecification && srcLifelinePart != null && tgtLifelinePart != null) {
int moveDeltaY = request.getMoveDelta().y();
int newY = request.getLocation().y();
int oldY = newY - moveDeltaY;
List<EditPart> empty = Collections.emptyList();
int minY = Integer.MIN_VALUE, maxY = Integer.MAX_VALUE;
int realMinY = Integer.MIN_VALUE;
IGraphicalEditPart realPrevPart = null; // ExecutionSpecificationEditPart 포함하여 가장 하위
List<IGraphicalEditPart> prevParts = ApexSequenceUtil.apexGetPrevSiblingEditParts(connectionPart);
List<IGraphicalEditPart> frontLinkedParts = ApexSequenceUtil.apexGetLinkedEditPartList(connectionPart, true, false, true);
for (IGraphicalEditPart part : prevParts) {
minY = Math.max(minY, ApexSequenceUtil.apexGetAbsolutePosition(part, SWT.BOTTOM) + MARGIN);
if (realMinY < minY) {
realMinY = minY;
}
if (part instanceof ConnectionNodeEditPart && !frontLinkedParts.contains(part)) {
// activation중 가장 하위 검색. realMinY는 activation 포함 가장 하위 y값
ConnectionNodeEditPart prevConnPart = (ConnectionNodeEditPart)part;
EditPart prevSourcePart = prevConnPart.getSource();
EditPart prevTargetPart = prevConnPart.getTarget();
if (prevSourcePart instanceof IGraphicalEditPart ) {
EObject eObj = ((IGraphicalEditPart) prevSourcePart).resolveSemanticElement();
if (eObj instanceof ExecutionSpecification && prevSourcePart instanceof ShapeNodeEditPart) {
int tMinY = ApexSequenceUtil.apexGetAbsolutePosition((IGraphicalEditPart)prevTargetPart, SWT.BOTTOM) + MARGIN;
if (realMinY < tMinY) {
realMinY = tMinY;
realPrevPart = (IGraphicalEditPart)prevTargetPart;
}
}
}
if (prevSourcePart instanceof IGraphicalEditPart ) {
EObject eObj = ((IGraphicalEditPart) prevSourcePart).resolveSemanticElement();
if (eObj instanceof ExecutionSpecification && prevTargetPart instanceof ShapeNodeEditPart) {
int ty = ApexSequenceUtil.apexGetAbsolutePosition((IGraphicalEditPart)prevTargetPart, SWT.BOTTOM) + MARGIN;
if (realMinY < ty) {
realMinY = ty;
realPrevPart = (IGraphicalEditPart)prevTargetPart;
}
}
}
}
}
if (prevParts.size() == 0) {
IFigure dotLine = ((IApexLifelineEditPart)srcLifelinePart).getPrimaryShape().getFigureLifelineDotLineFigure();
Rectangle dotLineBounds = dotLine.getBounds().getCopy();
dotLine.translateToAbsolute(dotLineBounds);
minY = dotLineBounds.y() + MARGIN;
realMinY = minY;
}
EObject eObj = realPrevPart.resolveSemanticElement();
if (flexiblePrev && eObj instanceof ExecutionSpecification && realPrevPart instanceof ShapeNodeEditPart) {
Dimension minimumSize = realPrevPart.getFigure().getMinimumSize();
int minimumBottom = ApexSequenceUtil.apexGetAbsolutePosition(realPrevPart, SWT.TOP) + minimumSize.height();
minY = Math.max(minY, minimumBottom);
}
else {
minY = realMinY;
}
List<IGraphicalEditPart> nextParts = ApexSequenceUtil.apexGetNextSiblingEditParts(connectionPart);
for (IGraphicalEditPart part : nextParts) {
int ty = ApexSequenceUtil.apexGetAbsolutePosition(part, SWT.TOP) - MARGIN;
if (maxY > ty) {
maxY = ty;
}
}
if (moveAlone) {
// Target인 Activation의 Minimumsize 이하로 줄어들 수 없음
if ( tgtPart instanceof IGraphicalEditPart ) {
EObject eTgtObj = ((IGraphicalEditPart) tgtPart).resolveSemanticElement();
if (eTgtObj instanceof ExecutionSpecification && tgtPart instanceof ShapeNodeEditPart) {
List sourceConnections = ((IGraphicalEditPart)tgtPart).getSourceConnections();
if (sourceConnections == null || sourceConnections.size() == 0) {
int minimumHeight = ((IGraphicalEditPart)tgtPart).getFigure().getMinimumSize().height();
int bottom = ApexSequenceUtil.apexGetAbsolutePosition((IGraphicalEditPart)tgtPart, SWT.BOTTOM);
maxY = bottom - minimumHeight;
}
}
newY = Math.min(maxY, Math.max(minY, newY));
moveDeltaY = newY - oldY;
}
// source : AbstractExecutionSpecificationEditPart
if ( srcPart instanceof IGraphicalEditPart ) {
EObject eSrcObj = ((IGraphicalEditPart) srcPart).resolveSemanticElement();
if (eSrcObj instanceof ExecutionSpecification && srcPart instanceof ShapeNodeEditPart) {
IGraphicalEditPart srcExecSpecEP = (IGraphicalEditPart)srcPart;
Rectangle oldBounds = ApexSequenceUtil.apexGetAbsoluteRectangle(srcExecSpecEP);
Rectangle newBounds = oldBounds.getCopy();
if (newBounds.bottom() < newY + PADDING) {
newBounds.height = newY + PADDING - newBounds.y;
}
compoudCmd.add( createChangeBoundsCommand(srcExecSpecEP, oldBounds, newBounds, true) );
compoudCmd.add( OccurrenceSpecificationMoveHelper.getMoveMessageOccurrenceSpecificationsCommand(
(OccurrenceSpecification)send, newY, newBounds, srcPart, srcLifelinePart, empty) );
}
else if (srcPart.equals(srcLifelinePart)) { // source : LifelineEditPart
IFigure figure = ((IApexLifelineEditPart)srcLifelinePart).getPrimaryShape().getFigureLifelineDotLineFigure();
Rectangle oldBounds = figure.getBounds().getCopy();
figure.translateToAbsolute(oldBounds);
Rectangle newBounds = oldBounds.getCopy();
if (newBounds.bottom() < newY + MARGIN) {
newBounds.height = newY + MARGIN - oldBounds.y;
}
compoudCmd.add( createChangeBoundsCommand(srcLifelinePart, oldBounds, newBounds, true) );
compoudCmd.add( OccurrenceSpecificationMoveHelper.getMoveMessageOccurrenceSpecificationsCommand(
(OccurrenceSpecification)send, newY, newBounds, srcPart, srcLifelinePart, empty) );
}
}
// target : AbstractExecutionSpecificationEditPart
if ( tgtPart instanceof IGraphicalEditPart ) {
EObject eTgtObj = ((IGraphicalEditPart) tgtPart).resolveSemanticElement();
if (eTgtObj instanceof ExecutionSpecification && tgtPart instanceof ShapeNodeEditPart) {
IGraphicalEditPart tgtExecSpecEP = (IGraphicalEditPart)tgtPart;
Rectangle oldBounds = ApexSequenceUtil.apexGetAbsoluteRectangle(tgtExecSpecEP);
Rectangle newBounds = oldBounds.getCopy();
newBounds.y = newY;
newBounds.height -= moveDeltaY;
compoudCmd.add( createChangeBoundsCommand(tgtExecSpecEP, oldBounds, newBounds, true) );
}
}
}
else {
if (moveDeltaY < 0) {
newY = Math.min(maxY, Math.max(minY, newY));
moveDeltaY = newY - oldY;
}
// flexiblePrev인 경우, 상당 ExecutionSpecification의 크기 줄임
EObject eRealPrevObj = realPrevPart.resolveSemanticElement();
if (flexiblePrev && (eRealPrevObj instanceof ExecutionSpecification && realPrevPart instanceof ShapeNodeEditPart) && realMinY > newY) {
Rectangle oldBounds = ApexSequenceUtil.apexGetAbsoluteRectangle(realPrevPart);
Rectangle newBounds = oldBounds.getCopy();
newBounds.height += (newY - realMinY);
compoudCmd.add( createChangeBoundsCommand(realPrevPart, oldBounds, newBounds, true) );
}
Command sendMessageMoveCmd = null;
if ( srcPart instanceof IGraphicalEditPart ) {
EObject eSrcPart = ((IGraphicalEditPart) srcPart).resolveSemanticElement();
if (eSrcPart instanceof ExecutionSpecification && srcPart instanceof ShapeNodeEditPart) {
IGraphicalEditPart srcExecSpecEP = (IGraphicalEditPart)srcPart;
ConnectionNodeEditPart lastConnPart = null;
int lastY = Integer.MIN_VALUE;
List srcConnParts = srcExecSpecEP.getSourceConnections();
Iterator iter = srcConnParts.iterator();
while (iter.hasNext()) {
ConnectionNodeEditPart srcConnPart = (ConnectionNodeEditPart)iter.next();
EObject semanticElement = srcConnPart.resolveSemanticElement();
if (semanticElement instanceof Message) {
MessageEnd sendEvent = ((Message)semanticElement).getSendEvent();
Point location = SequenceUtil.findLocationOfMessageOccurrence((GraphicalEditPart) srcExecSpecEP, (MessageOccurrenceSpecification) sendEvent);
// Point location = ApexSequenceUtil.apexGetAbsoluteRectangle(srcConnPart).getLocation();
if (lastY < location.y) {
lastY = location.y;
lastConnPart = srcConnPart;
}
}
}
Rectangle oldBounds = ApexSequenceUtil.apexGetAbsoluteRectangle(srcExecSpecEP);
Rectangle newBounds = oldBounds.getCopy();
if (connectionPart.equals(lastConnPart)) {
newBounds.height = oldBounds.height + moveDeltaY;
compoudCmd.add( createChangeBoundsCommand(srcExecSpecEP, oldBounds, newBounds, true) );
}
if (moveDeltaY > 0) {
newBounds.height = oldBounds.height + moveDeltaY;
}
sendMessageMoveCmd = OccurrenceSpecificationMoveHelper.getMoveMessageOccurrenceSpecificationsCommand(
(OccurrenceSpecification)send, newY, newBounds, srcPart, srcLifelinePart, empty);
}
else if (srcPart.equals(srcLifelinePart)) { // source : LifelineEditPart
IFigure figure = ((IApexLifelineEditPart)srcLifelinePart).getPrimaryShape().getFigureLifelineDotLineFigure();
Rectangle oldBounds = figure.getBounds().getCopy();
figure.translateToAbsolute(oldBounds);
Rectangle newBounds = oldBounds.getCopy();
if (newBounds.bottom() < newY + MARGIN) {
newBounds.height = newY + MARGIN - oldBounds.y;
}
compoudCmd.add( createChangeBoundsCommand(srcLifelinePart, oldBounds, newBounds, true) );
compoudCmd.add( OccurrenceSpecificationMoveHelper.getMoveMessageOccurrenceSpecificationsCommand(
(OccurrenceSpecification)send, newY, newBounds, srcPart, srcLifelinePart, empty) );
}
}
List<IGraphicalEditPart> linkedParts = ApexSequenceUtil.apexGetLinkedEditPartList(connectionPart, false, true, false);
for (IGraphicalEditPart linkedPart : linkedParts) {
Rectangle oldBounds = ApexSequenceUtil.apexGetAbsoluteRectangle(linkedPart);
Rectangle newBounds = oldBounds.getCopy();
newBounds.y += moveDeltaY;
compoudCmd.add( createChangeBoundsCommand(linkedPart, oldBounds, newBounds, false) );
}
if (moveDeltaY > 0) {
linkedParts = ApexSequenceUtil.apexGetLinkedEditPartList(connectionPart, true, true, false);
nextParts.removeAll(linkedParts);
if (nextParts.size() > 0) {
IGraphicalEditPart nextSiblingEditPart = nextParts.get(0);
if (nextSiblingEditPart instanceof ConnectionNodeEditPart) {
Command nextCmd = apexGetMoveConnectionCommand(request, (ConnectionNodeEditPart) nextSiblingEditPart, moveAlone);
compoudCmd.add(nextCmd);
}
else {
Command nextCmd = nextSiblingEditPart.getCommand(request);
compoudCmd.add(nextCmd);
// apexGetResizeOrMoveBelowItemsCommand(request, nextSiblingEditPart);
}
}
}
compoudCmd.add(sendMessageMoveCmd);
}
return compoudCmd.size() > 0 ? compoudCmd : null;
}
}
return null;
}
/**
* Message보다 하위의 item들을 delta만큼 이동
* @param request
* @param abstractGraphicalEditPart
* @return
*/
private static Command apexGetResizeOrMoveBelowItemsCommand(ChangeBoundsRequest request, IGraphicalEditPart gep) {
CompoundCommand command = new CompoundCommand();
gep.getCommand(request);
command.add(InteractionCompartmentXYLayoutEditPolicy.getCombinedFragmentResizeChildrenCommand(request, (GraphicalEditPart)gep));
return command;
}
/**
* bounds를 변경하는 Command를 생성
* @param gep
* @param oldBounds
* @param newBounds
* @param isPreserveAnchorsPosition true이면 gep만 단독으로 변경하는 Command 생성, false이면 Request에 의해 변경하는 Command 그룹 생성
* @return
*/
private static Command createChangeBoundsCommand(IGraphicalEditPart gep, Rectangle oldBounds, Rectangle newBounds, boolean isPreserveAnchorsPosition) {
Command command = null;
if (oldBounds.x == newBounds.x && oldBounds.y == newBounds.y &&
oldBounds.width == newBounds.width && oldBounds.height == newBounds.height) {
return null;
}
if (!isPreserveAnchorsPosition) {
TransactionalEditingDomain editingDomain = gep.getEditingDomain();
Rectangle parentBounds = gep.getFigure().getParent().getBounds();
// newBounds를 parent(Lifeline)을 기준으로 한 상대좌표로 변경
gep.getFigure().translateToRelative(newBounds);
newBounds.translate(-parentBounds.x, -parentBounds.y);
// end
command = new ICommandProxy( new SetBoundsCommand(editingDomain, "", gep, newBounds) );
}
else {
ChangeBoundsRequest request = createChangeBoundsRequest(oldBounds, newBounds);
command = gep.getCommand(request);
}
return command;
}
/**
* bounds를 변경하는 ChangeBoundsRequest 생성
* @param oldBounds
* @param newBounds
* @return
*/
private static ChangeBoundsRequest createChangeBoundsRequest(Rectangle oldBounds, Rectangle newBounds) {
ChangeBoundsRequest request = new ChangeBoundsRequest(REQ_RESIZE);
Point moveDelta = new Point(newBounds.x - oldBounds.x, newBounds.y - oldBounds.y);
Dimension sizeDelta = new Dimension(newBounds.width - oldBounds.width, newBounds.height - oldBounds.height);
request.setMoveDelta(moveDelta);
request.setSizeDelta(sizeDelta);
// execution 이동에 의해 editpart들이 겹치는 현상 방지
request.getExtendedData().put(SequenceRequestConstant.DO_NOT_MOVE_EDIT_PARTS, true);
if (oldBounds.y == newBounds.y)
request.setResizeDirection(PositionConstants.SOUTH);
else if (oldBounds.bottom() == newBounds.bottom())
request.setResizeDirection(PositionConstants.NORTH);
else
request.setResizeDirection(PositionConstants.NORTH_SOUTH);
return request;
}
/**
* don't show feedback if the drag is forbidden (message not horizontal).
*/
@Override
public void showSourceFeedback(Request request) {
if (request instanceof ChangeBoundsRequest) {
if (isConstrainedMove((ChangeBoundsRequest)request)) {
showConstrainedMoveFeedback((ChangeBoundsRequest)request, false);
} else {
showMoveConnectionFeedback((ChangeBoundsRequest) request);
}
}
super.showSourceFeedback(request);
}
protected void showMoveConnectionFeedback(ChangeBoundsRequest request) {
showReorderingFeedback(request);
ConnectionNodeEditPart host = (ConnectionNodeEditPart)getHost();
Connection connection = host.getConnectionFigure();
Point moveDelta = request.getMoveDelta();
PointList pl = connection.getPoints().getCopy();
for (int i = 0; i < pl.size(); i++) {
Point p = pl.getPoint(i);
p.y += moveDelta.y;
pl.setPoint(p, i);
}
PolylineConnection feedbackConnection = getDragSourceFeedbackFigure();
feedbackConnection.setPoints(pl);
}
private void showConstrainedMoveFeedback(ChangeBoundsRequest request, boolean isFlexible) {
ConnectionNodeEditPart host = (ConnectionNodeEditPart)getHost();
Connection connection = host.getConnectionFigure();
Point location = request.getLocation().getCopy();
connection.translateToRelative(location);
PointList pl = connection.getPoints().getCopy();
Point oldLocation = pl.getFirstPoint().getCopy();
PolylineConnection feedbackConnection = getDragSourceFeedbackFigure();
int dy = location.y - oldLocation.y;
int minY = ApexSequenceUtil.getMovableTop(host, isFlexible, MARGIN);
int maxY = ApexSequenceUtil.getMovableBottom(host, MARGIN);
if (minY > location.y) {
dy = minY - oldLocation.y;
} else if (maxY < location.y) {
dy = maxY - oldLocation.y;
}
for (int i = 0; i < pl.size(); i++) {
Point p = pl.getPoint(i);
p.y += dy;
pl.setPoint(p, i);
}
feedbackConnection.setForegroundColor(ApexSequenceDiagramConstants.CONSTRAINED_MOVE_LINE_COLOR);
feedbackConnection.setPoints(pl);
}
private void showReorderingFeedback(ChangeBoundsRequest request) {
ConnectionNodeEditPart host = (ConnectionNodeEditPart)getHost();
Point location = request.getLocation().getCopy();
Integer[] reorderingLocations = ApexSequenceUtil.apexGetReorderingLocations(host, location);
Integer nearLocation = null;
for (Integer reorderingLocation : reorderingLocations) {
if ((nearLocation != null && Math.abs(nearLocation + NEAR_LINE_MARGIN - location.y) > Math.abs(reorderingLocation + NEAR_LINE_MARGIN - location.y)) ||
(Math.abs(reorderingLocation + NEAR_LINE_MARGIN - location.y) < NEAR_LINE_TOLERANCE)) {
nearLocation = reorderingLocation;
}
}
if (!isReordering(request) || nearLocation == null) {
if (guideFeedback != null) {
removeFeedback(guideFeedback);
}
guideFeedback = null;
} else {
if (guideFeedback == null) {
guideFeedback = createGuideLineFeedbackFigure();
}
Control control = getHost().getViewer().getControl();
int viewPortXLocation = control.getBounds().x;
int viewPortXExtent = control.getBounds().x + control.getBounds().width;
if (control instanceof FigureCanvas) {
FigureCanvas canvas = (FigureCanvas)control;
Rectangle bounds = canvas.getViewport().getBounds().getCopy();
viewPortXLocation = bounds.x;
viewPortXExtent = bounds.x + bounds.width;
}
PointList pl = new PointList();
pl.addPoint(viewPortXLocation, nearLocation + NEAR_LINE_MARGIN);
pl.addPoint(viewPortXExtent, nearLocation + NEAR_LINE_MARGIN);
guideFeedback.setPoints(pl);
addFeedback(guideFeedback);
}
}
public void eraseSourceFeedback(Request request) {
if (feedback != null) {
removeFeedback(feedback);
}
feedback = null;
if (guideFeedback != null) {
removeFeedback(guideFeedback);
}
guideFeedback = null;
super.eraseSourceFeedback(request);
}
protected PolylineConnection createDragSourceFeedbackConnection() {
PolylineConnection connection = new PolylineConnection();
connection.setLineWidth(1);
connection.setLineStyle(Graphics.LINE_DASHDOT);
connection.setForegroundColor(((IGraphicalEditPart)getHost()).getFigure().getLocalForegroundColor());
return connection;
}
/**
* Returns feedback figure
*
* @return
*/
protected PolylineConnection getDragSourceFeedbackFigure() {
if (feedback == null) {
feedback = createDragSourceFeedbackConnection();
addFeedback(feedback);
}
return feedback;
}
protected PolylineConnection createGuideLineFeedbackFigure() {
if (guideFeedback == null) {
guideFeedback = new PolylineConnection();
guideFeedback.setLineWidth(1);
guideFeedback.setLineStyle(Graphics.LINE_DASH);
guideFeedback.setForegroundColor(ApexSequenceDiagramConstants.REORDERING_LINE_COLOR);
}
return guideFeedback;
}
private boolean isReordering(ChangeBoundsRequest request) {
// return request.isCenteredResize();
return !request.isSnapToEnabled();
}
private boolean isConstrainedMove(ChangeBoundsRequest request) {
return request.isConstrainedMove();
}
}