package org.eclipse.uml2.diagram.sequence.internal.layout.model;
import java.awt.Point;
import org.eclipse.uml2.diagram.sequence.internal.layout.GeometryConstants;
import org.eclipse.uml2.diagram.sequence.internal.layout.abstractgde.AbsLink;
import org.eclipse.uml2.diagram.sequence.internal.layout.vertical.input.LifeLineElement;
import org.eclipse.uml2.diagram.sequence.internal.layout.vertical.input.OrderingConstraint;
/**
*
*/
public class LMSelfMessage extends LMMessage {
LMSelfMessage(AbsLink gdeLink, boolean isFromSendToReceive, boolean isAsynchronous) {
super(gdeLink);
myIsFromSendToReceive = isFromSendToReceive;
myIsAsynchronous = isAsynchronous;
}
boolean isFromSendToReceive() {
return myIsFromSendToReceive;
}
boolean isAsynchronous() {
return myIsAsynchronous;
}
public void layoutHorizontally(boolean fullLayout) {
Point [] newPoints = getHorizontalLayout(fullLayout);
getGdeLink().setLinkPoints(newPoints);
int startXPos = newPoints[0].x;
MessageLabelLayouter.layoutMessageLabelsHorizontally(getGdeLink(), startXPos, startXPos + 1, fullLayout);
}
public Point [] getHorizontalLayout(boolean fullLayout) {
int startXPos = mySendHorizontalPositioning.getSendEndXPos(true);
int endXPos = myReceiveHorizontalPositioning.getReceiveEndXPos(true);
//Reply message start and end points should be swapped
if (! isFromSendToReceive()) {
int t = startXPos;
startXPos = endXPos;
endXPos = t;
}
Point [] linkPoints = getGdeLink().getLinkPoints();
Point [] newPoints = {
getPointFromArray(linkPoints, 0),
getPointFromArray(linkPoints, 1),
getPointFromArray(linkPoints, -2),
getPointFromArray(linkPoints, -1),
};
int xPosMin = (startXPos > endXPos ? startXPos : endXPos) + + GeometryConstants.Message.SELF_MESSAGE_HORIZONTAL_INDENT;
if (isFromSendToReceive()) {
xPosMin += GeometryConstants.Message.SELF_RETURN_MESSAGE_HORIZONTAL_OFFSET;
}
int xPosMax = xPosMin + GeometryConstants.Message.SELF_MESSAGE_HORIZONTAL_RANGE;
int middleSegmentX;
if (fullLayout) {
middleSegmentX = 0;
} else {
middleSegmentX = getPointFromArray(linkPoints, 1).x;
}
if (middleSegmentX < xPosMin) {
middleSegmentX = xPosMin;
}
if (middleSegmentX > xPosMax) {
middleSegmentX = xPosMax;
}
newPoints[0].x = startXPos;
newPoints[1].x = middleSegmentX;
newPoints[2].x = middleSegmentX;
newPoints[3].x = endXPos;
return newPoints;
}
void setLMMessageEndVerticalPosition(int pos, boolean sourceNotDestination, int siblingNumber) {
//new Exception("pos="+pos).printStackTrace(System.out);
Point [] linkPoints = getGdeLink().getLinkPoints();
Point [] newPoints = {
getPointFromArray(linkPoints, 0),
getPointFromArray(linkPoints, 1),
getPointFromArray(linkPoints, -2),
getPointFromArray(linkPoints, -1),
};
boolean changeSourceNotDestinaction = sourceNotDestination ^ !isFromSendToReceive();
if (myIsAsynchronous) {
int slopeSign = isFromSendToReceive() ? 1 : -1;
if (changeSourceNotDestinaction) {
newPoints[0].y = pos;
newPoints[1].y = pos + slopeSign * GeometryConstants.Message.ASYNCHRONOUS_SELF_MESSAGE_VERTICAL_SLOPE;
} else {
newPoints[2].y = pos - slopeSign * GeometryConstants.Message.ASYNCHRONOUS_SELF_MESSAGE_VERTICAL_SLOPE;
newPoints[3].y = pos;
}
} else {
if (changeSourceNotDestinaction) {
newPoints[0].y = pos;
newPoints[1].y = pos;
} else {
newPoints[2].y = pos;
newPoints[3].y = pos;
}
}
getGdeLink().setLinkPoints(newPoints);
//System.out.println("[LMLifeLineBracket.setLMMessageEndVerticalPosition] from "+java.util.Arrays.asList(linkPoints)+" to "+java.util.Arrays.asList(newPoints));
if (sourceNotDestination) {
//if (! sourceNotDestination ^ isFromSendToReceive()) {
MessageLabelLayouter.layoutMessageLabelsVertically(getGdeLink(), pos);
}
}
private Point getPointFromArray(Point [] points, int index) {
if (points == null || points.length == 0) {
return new Point();
} else {
Point foundPoint;
if (index >= 0) {
int halfIndex = (points.length-1) / 2;
if (index > halfIndex) {
index = halfIndex;
}
foundPoint = points[index];
} else {
int halfIndex = points.length / 2;
index = points.length + index;
if (index < halfIndex) {
index = halfIndex;
}
foundPoint = points[index];
}
if (foundPoint == null) {
return new Point();
} else {
return new Point(foundPoint);
}
}
}
LMSendMessageEnd getSendMessageEnd() {
return mySendMessageEnd;
}
LMReceiveMessageEnd getReceiveMessageEnd() {
return myReceiveMessageEnd;
}
protected void setSendMessageEnd(LMSendMessageEnd sendMessageEnd, LMMessageEnd.VerticalConstraintedPositioning sendVerticalPositioning, LMSendMessageEnd.HorizontalPositioning sendHorizontalPositioning) {
mySendMessageEnd = sendMessageEnd;
mySendVerticalPositioning = sendVerticalPositioning;
mySendHorizontalPositioning = sendHorizontalPositioning;
sourceOrDestinationChanged();
}
protected void setReceiveMessageEnd(LMReceiveMessageEnd receiveMessageEnd, LMMessageEnd.VerticalConstraintedPositioning receiveVerticalPositioning, LMReceiveMessageEnd.HorizontalPositioning receiveHorizontalPositioning) {
myReceiveMessageEnd = receiveMessageEnd;
myReceiveVerticalPositioning = receiveVerticalPositioning;
myReceiveHorizontalPositioning = receiveHorizontalPositioning;
sourceOrDestinationChanged();
}
void resetSendMessageEnd() {
mySendMessageEnd = null;
mySendVerticalPositioning = null;
mySendHorizontalPositioning = null;
sourceOrDestinationChanged();
}
void resetReceiveMessageEnd() {
myReceiveMessageEnd = null;
myReceiveVerticalPositioning = null;
myReceiveHorizontalPositioning = null;
sourceOrDestinationChanged();
}
void becomeLayoutConstraint(boolean on) {
if (! (myIsAsynchronous && myIsFromSendToReceive) ) {
return;
}
final LMMessageEnd.ConnectableLifeLineElement sendElement = mySendVerticalPositioning.getTopLifeLineElement();
final LMMessageEnd.ConnectableLifeLineElement receiveElement = myReceiveVerticalPositioning.getTopLifeLineElement();
if (on) {
myOrderingConstraint = new OrderingConstraint() {
public LifeLineElement getBeforeElement() {
return sendElement;
}
public LifeLineElement getAfterElement() {
return receiveElement;
}
public void setInvalid(boolean invalid) {
LMSelfMessage.this.setVerticalConstraintViolationState(invalid);
}
public int getMinSlopeValue() {
return GeometryConstants.Message.MIN_ASYNCHRONOUS_SLOPE_VALUE;
}
};
sendElement.addAfterConstraint(myOrderingConstraint);
receiveElement.addBeforeConstraint(myOrderingConstraint);
} else {
sendElement.removeAfterConstraint(myOrderingConstraint);
receiveElement.removeBeforeConstraint(myOrderingConstraint);
myOrderingConstraint = null;
}
}
boolean isLayoutConstraint() {
return myOrderingConstraint != null;
}
protected boolean calculateIsMessageViolated() {
return myIsVerticalConstraintViolated || super.calculateIsMessageViolated();
}
protected void setVerticalConstraintViolationState(boolean violated) {
myIsVerticalConstraintViolated = violated;
updateMessageViolationState();
}
private final boolean myIsFromSendToReceive;
private final boolean myIsAsynchronous;
private LMReceiveMessageEnd myReceiveMessageEnd;
private LMSendMessageEnd mySendMessageEnd;
private LMMessageEnd.VerticalConstraintedPositioning mySendVerticalPositioning;
private LMMessageEnd.VerticalConstraintedPositioning myReceiveVerticalPositioning;
private LMSendMessageEnd.HorizontalPositioning mySendHorizontalPositioning;
private LMReceiveMessageEnd.HorizontalPositioning myReceiveHorizontalPositioning;
private OrderingConstraint myOrderingConstraint = null;
private boolean myIsVerticalConstraintViolated;
}