package org.eclipse.uml2.diagram.sequence.internal.layout.horizontal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import org.eclipse.uml2.diagram.sequence.internal.layout.GeometryConstants;
import org.eclipse.uml2.diagram.sequence.internal.layout.horizontal.FramesManager.FrameInfo;
import org.eclipse.uml2.diagram.sequence.internal.layout.horizontal.LifeLineHorizontalLayouter.PreparedLayout;
import org.eclipse.uml2.diagram.sequence.internal.layout.model.LMBadElement;
import org.eclipse.uml2.diagram.sequence.internal.layout.model.LMFoundInvocationOccurence;
import org.eclipse.uml2.diagram.sequence.internal.layout.model.LMFrame;
import org.eclipse.uml2.diagram.sequence.internal.layout.model.LMFrameContainer;
import org.eclipse.uml2.diagram.sequence.internal.layout.model.LMLifeLine;
import org.eclipse.uml2.diagram.sequence.internal.layout.model.LMMessage;
import org.eclipse.uml2.diagram.sequence.internal.layout.model.SdLayoutModelAccess;
/**
*
*/
public class SDHorizontalLayout {
public SDHorizontalLayout(SdLayoutModelAccess layoutModelAccess) {
myLayoutModelAccess = layoutModelAccess;
//Model model = mySDLayout.getDiagramEntity().getModel();
}
public LifelineCoveringFramesCache getLifelineCoveringFramesCache() {
return myLifelineCoverinngFramesCache;
}
private LifelineCoveringFramesCache myLifelineCoverinngFramesCache;
//private int myTimeToWorkCounter = 20;
/**
* @return rightPos
*/
public int applyConstraints(int leftPos, final boolean fullLayout) {
//System.out.println("[SDHorizontalLayout.applyConstraints] start layout");
List lmLifelinesNonsortedlList = myLayoutModelAccess.getLayoutModel().getLifeLinesList();
List lifelineLayouters = new ArrayList(lmLifelinesNonsortedlList.size());
for (Iterator it = lmLifelinesNonsortedlList.iterator(); it.hasNext(); ) {
Object nextLifeLineObject = it.next();
if (nextLifeLineObject instanceof LMLifeLine == false) {
continue;
}
LMLifeLine lmLifeLine = (LMLifeLine) nextLifeLineObject;
lifelineLayouters.add(new LifeLineHorizontalLayouter(lmLifeLine));
}
Collections.sort(lifelineLayouters, ComparableVerticalElement.COMPARATOR);
final FramesManager framesManager = new FramesManager(myLayoutModelAccess.getLayoutModel().getRootFrameContainer().getChildList());
List preparedLayouts = new ArrayList(lifelineLayouters.size());
List lmMessages = new ArrayList();
for (int i=0; i<lifelineLayouters.size(); i++) {
LifeLineHorizontalLayouter lifeLineHorizontalLayout = (LifeLineHorizontalLayouter) lifelineLayouters.get(i);
framesManager.setLifeLineIndex(i);
LifeLineHorizontalLayouter.PreparedLayout preparedLayout1 = lifeLineHorizontalLayout.scanAndPrepareLayout(framesManager, lmMessages);
preparedLayouts.add(preparedLayout1);
}
createNewLifelineCoveringFramesCache: {
myLifelineCoverinngFramesCache = new LifelineCoveringFramesCache();
for (Iterator frameInfos = framesManager.frameInfos(); frameInfos.hasNext(); ) {
FramesManager.FrameInfo next = (FrameInfo)frameInfos.next();
if (next.getMaxLifeLineIndex() == -1) {
continue;
}
LMLifeLine leftmost = ((LifeLineHorizontalLayouter) lifelineLayouters.get(next.getMinLifeLineIndex())).getLmLifeline();
LMLifeLine rightmost = ((LifeLineHorizontalLayouter) lifelineLayouters.get(next.getMaxLifeLineIndex())).getLmLifeline();
myLifelineCoverinngFramesCache.setFrameOutermostLifelines(next.getLMFrame(), leftmost, rightmost);
}
}
final LifeLineDressImpl [] lifeLineDresses = new LifeLineDressImpl [lifelineLayouters.size()];
for (int i=0; i<lifeLineDresses.length; i++) {
lifeLineDresses[i] = new LifeLineDressImpl(fullLayout);
}
int allLifeLinesLeftPos = GeometryConstants.DIAGRAM_LEFT_BORDER_SPACE + leftPos;
final List foundMessages = new ArrayList(3);
{
final List topUntiedFrames = new ArrayList(0);
class FramesAnalizer {
public void go() {
processFrameContainerRecursively(myLayoutModelAccess.getLayoutModel().getRootFrameContainer(), topUntiedFrames);
}
private void processFrameContainerRecursively(LMFrameContainer frameContainer, Collection untiedFramesOutput) {
List lmFramesList = frameContainer.getChildList();
int leftLifeLineIndex = lifeLineDresses.length;
int rigthLifeLineIndex = -1;
for (int i=0; i<lmFramesList.size(); i++) {
LMFrame lmFrame = (LMFrame) lmFramesList.get(i);
if (lmFrame.hasAnyMountingLinks()) {
processFrameRecursively(lmFrame);
} else {
untiedFramesOutput.add(lmFrame);
myLeftIndex = lifeLineDresses.length;
myRightIndex = -1;
}
if (myLeftIndex < leftLifeLineIndex) {
leftLifeLineIndex = myLeftIndex;
}
if (myRightIndex > rigthLifeLineIndex) {
rigthLifeLineIndex = myRightIndex;
}
}
myLeftIndex = leftLifeLineIndex;
myRightIndex = rigthLifeLineIndex;
collectFoundMessages(frameContainer);
}
private void processFrameRecursively(LMFrame lmFrame) {
FramesManager.FrameInfo frameInfo = framesManager.getFrameInfo(lmFrame);
List innerUntiedFrames = new ArrayList(0);
//_outermost_ frame which has just been reshaped
boolean addAsJustReshaped = false;
if (!fullLayout && lmFrame.isJustReshaped() && !myOneJustReshapedFrameAlreadyProcessed) {
addAsJustReshaped = true;
myOneJustReshapedFrameAlreadyProcessed = true;
}
processFrameContainerRecursively(lmFrame, innerUntiedFrames);
if (myLeftIndex > frameInfo.getMinLifeLineIndex()) {
myLeftIndex = frameInfo.getMinLifeLineIndex();
}
if (myRightIndex < frameInfo.getMaxLifeLineIndex()) {
myRightIndex = frameInfo.getMaxLifeLineIndex();
}
UntiedFrameHorizontalLayouter untiedFrameLayouter;
if (innerUntiedFrames.isEmpty()) {
untiedFrameLayouter = null;
} else {
untiedFrameLayouter = new UntiedFrameHorizontalLayouter(innerUntiedFrames);
}
int maxLeftBracketOffset = (myLeftIndex == frameInfo.getMinLifeLineIndex()) ?
frameInfo.getMaxLeftBraketPos() : 0;
int maxRightBracketOffset = (myRightIndex == frameInfo.getMaxLifeLineIndex()) ?
frameInfo.getMaxRightBraketPos() : 0;
LifeLineDressImpl.LeftSideFrameWrapper leftSideOnTheSameLifeline = lifeLineDresses[myLeftIndex].addLeftFrame(lmFrame, maxLeftBracketOffset, untiedFrameLayouter, addAsJustReshaped);
if (myLeftIndex != myRightIndex) {
leftSideOnTheSameLifeline = null;
}
lifeLineDresses[myRightIndex].addRightFrame(lmFrame, maxRightBracketOffset, addAsJustReshaped, leftSideOnTheSameLifeline);
}
private void collectFoundMessages(LMFrameContainer frameContainer) {
for (Iterator it = frameContainer.getFoundInvocationsList().iterator(); it.hasNext(); ) {
LMFoundInvocationOccurence foundInvocationOccurence = (LMFoundInvocationOccurence) it.next();
foundMessages.addAll(foundInvocationOccurence.getOutgoingLMMessages());
}
}
private int myLeftIndex;
private int myRightIndex;
private boolean myOneJustReshapedFrameAlreadyProcessed = false;
}
new FramesAnalizer().go();
if (!topUntiedFrames.isEmpty()) {
UntiedFrameHorizontalLayouter untiedFrameHorizontalLayouter = new UntiedFrameHorizontalLayouter(topUntiedFrames);
untiedFrameHorizontalLayouter.layout(allLifeLinesLeftPos);
allLifeLinesLeftPos += untiedFrameHorizontalLayouter.getWidth() + GeometryConstants.DIAGRAM_LEFT_BORDER_SPACE;
}
}
final int farAwayX;
{
int posX = allLifeLinesLeftPos;
for (int i=0; i<preparedLayouts.size(); i++) {
LifeLineHorizontalLayouter.PreparedLayout preparedLayout1 = (PreparedLayout) preparedLayouts.get(i);
int currentCenterPos = preparedLayout1.getCurrentCenterPos();
int newCenterPos = posX + Math.max(preparedLayout1.getLeftHalfWidth(), lifeLineDresses[i].getLeftMinSpace());
if (!fullLayout && currentCenterPos > newCenterPos) {
newCenterPos = currentCenterPos;
}
preparedLayout1.layout(newCenterPos);
lifeLineDresses[i].setMinLeftAndCenter(posX, newCenterPos);//do it before lifeLineDresses[i].getRightMinSpace()
int maxRightPos = newCenterPos + Math.max(preparedLayout1.getRightHalfWidth(), lifeLineDresses[i].getRightMinSpace());
if (i+1 < preparedLayouts.size()) {
LifeLineHorizontalLayouter.PreparedLayout nextPreparedLayout = (PreparedLayout) preparedLayouts.get(i+1);
int nextLifelineMinCurrentLeftPos = nextPreparedLayout.getCurrentCenterPos() - Math.max(nextPreparedLayout.getLeftHalfWidth(), lifeLineDresses[i+1].getLeftMinSpace());
maxRightPos = Math.max(maxRightPos, nextLifelineMinCurrentLeftPos-GeometryConstants.SPACE_BETWEEN_LIFE_LINES_HORIZONTAL);
} else {
maxRightPos = Integer.MAX_VALUE;
}
lifeLineDresses[i].setMaxRight(newCenterPos, maxRightPos);
lifeLineDresses[i].layout(newCenterPos);
assert lifeLineDresses[i].getRightSpace() <= maxRightPos;
posX = newCenterPos + Math.max(preparedLayout1.getRightHalfWidth(), lifeLineDresses[i].getRightSpace()) + GeometryConstants.SPACE_BETWEEN_LIFE_LINES_HORIZONTAL;
}
farAwayX = posX + GeometryConstants.Lifeline.MINIMAL_HORIZONTAL_DISTANCE;
}
for (Iterator it = lmMessages.iterator(); it.hasNext(); ) {
LMMessage message = (LMMessage) it.next();
message.layoutHorizontally(fullLayout);
}
for (Iterator it = foundMessages.iterator(); it.hasNext(); ) {
LMMessage message = (LMMessage) it.next();
message.layoutHorizontally(fullLayout);
}
{
int badElementXPos = farAwayX;
for (Iterator it = myLayoutModelAccess.getLayoutModel().getBadElementsList().iterator(); it.hasNext(); ) {
LMBadElement badElement = (LMBadElement) it.next();
int width = badElement.layoutAndReturnWidth(badElementXPos);
badElementXPos += width + 5;
}
return badElementXPos;
}
//System.out.println("[SDHorizontalLayout.applyConstraints] finish layout");
}
private final SdLayoutModelAccess myLayoutModelAccess;
}