package org.eclipse.uml2.diagram.sequence.internal.layout.horizontal; import java.util.ArrayList; import java.util.Collection; 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.abstractgde.AbsNode; import org.eclipse.uml2.diagram.sequence.internal.layout.horizontal.FramesManager.FrameInfo; import org.eclipse.uml2.diagram.sequence.internal.layout.model.LMExecutionOccurence; import org.eclipse.uml2.diagram.sequence.internal.layout.model.LMFrame; import org.eclipse.uml2.diagram.sequence.internal.layout.model.LMLifeLine; import org.eclipse.uml2.diagram.sequence.internal.layout.model.LMLifeLineBracket; import org.eclipse.uml2.diagram.sequence.internal.layout.model.LMMountingLink; import org.eclipse.uml2.diagram.sequence.internal.layout.model.LMMountingRegion; import org.eclipse.uml2.diagram.sequence.internal.layout.model.LMSendMessageEnd; import org.eclipse.uml2.diagram.sequence.internal.layout.model.LMSimpleLifeLineBracket; /** * */ class LifeLineHorizontalLayouter implements ComparableVerticalElement { LifeLineHorizontalLayouter(LMLifeLine lifeLine) { myLMLifeLine = lifeLine; } public int getX() { return myLMLifeLine.getGdeNode().getX(); } public int getWidth() { return myLMLifeLine.getGdeNode().getWidth(); } public boolean hasNoBounds() { return !myLMLifeLine.getGdeNode().isUserResized(); } LMLifeLine getLmLifeline() { return myLMLifeLine; } PreparedLayout scanAndPrepareLayout(FramesManager frameManager, Collection messagesCollection) { PerLifeLineSession perLifeLineSession = new PerLifeLineSession(frameManager, messagesCollection); return perLifeLineSession.go(); } interface PreparedLayout { int getLeftHalfWidth(); int getRightHalfWidth(); int getCurrentCenterPos(); void layout(int centerLinePos); } private final LMLifeLine myLMLifeLine; private class PerLifeLineSession { PerLifeLineSession(FramesManager frameManager, Collection messagesCollection) { myFrameManager = frameManager; myMessagesCollection = messagesCollection; } PreparedLayout go() { //System.out.println("[RecursiveLayoutSession.go] "); ShiftedBracketInfo lifeLineBracketInfo = new ShiftedBracketInfo(null, null, 0); //System.out.println("[RecursiveLayoutSession.go] lifeline brackets: "+myLMLifeLine.getChildBracketsList()); processBracketList(myLMLifeLine.getChildBracketsList().getListView(), 0, false, lifeLineBracketInfo, null); adjustRigthHalfWidth(lifeLineBracketInfo.getMaxRightPos()); // adjustLeftHalfWidth(GeometryConstants.Execution.WIDTH/2); // adjustRigthHalfWidth(GeometryConstants.Execution.WIDTH/2); //System.out.println("[RecursiveLayoutSession.go] bracket info list size: "+myBracketInfoList.size()); final int headHalfWidth = myLMLifeLine.getHeadNameWidth()/2; adjustLeftHalfWidth(headHalfWidth); adjustRigthHalfWidth(headHalfWidth); return new PreparedLayout() { public int getLeftHalfWidth() { return myLeftHalfWidth; } public int getRightHalfWidth() { return myRightHalfWidth; } public int getCurrentCenterPos() { return myLMLifeLine.getGdeNode().getX() + myLeftHalfWidth; } public void layout(int centerLinePos) { myLMLifeLine.setHorizontalPos(centerLinePos, myLeftHalfWidth, myRightHalfWidth, headHalfWidth); for (int i=0; i<myShiftedBracketInfoList.size(); i++) { ShiftedBracketInfo bracketInfo = (ShiftedBracketInfo) myShiftedBracketInfoList.get(i); LMLifeLineBracket lifeLineBracket = bracketInfo.getBracket(); int newPos = centerLinePos + bracketInfo.getOffset() - GeometryConstants.Execution.HORIZONTAL_OFFSET; //System.out.println("[LifeLineHorizontalLayouter.layout] bracket "+bracketInfo.getBracket()); //System.out.println("[LifeLineHorizontalLayouter.layout] bracketInfo.getOffset()="+bracketInfo.getOffset()); //System.out.println("[LifeLineHorizontalLayouter.go] newPos="+newPos); //System.out.println("[LifeLineHorizontalLayouter.layout] width="+width); // if (bracketInfo.getParentBracketInfo().getMaxRightPos() != bracketInfo.getMaxRightPos()) { // System.out.println("[PerLifeLineSession] go " + bracketInfo.getParentBracketInfo().getMaxRightPos()+" != "+bracketInfo.getMaxRightPos()); //$NON-NLS-1$ //$NON-NLS-2$ // } int width = bracketInfo.getWidth(); int paintableWidth = GeometryConstants.Execution.WIDTH; lifeLineBracket.getBracketHorizontalLayouter().setHorizontalPositions(newPos, paintableWidth, width); lifeLineBracket.setHorizontalPosition(newPos); //System.out.println("[RecursiveLayoutSession.go] externals: "+gdeNode.isExternalElement()); } for (int i=0; i<myCenteredBracketInfoList.size(); i++) { CenteredBracketInfo centeredBracketInfo = (CenteredBracketInfo) myCenteredBracketInfoList.get(i); //System.out.println("[LifeLineHorizontalLayouter.layout] bracket "+centeredBracketInfo.getBracket()); int width = centeredBracketInfo.getWidth(); if (width < 20) { width = 20; } int x = centeredBracketInfo.getOffset() + centerLinePos - width/2; AbsNode gdeNode = centeredBracketInfo.getBracket().getGdeNode(); //System.out.println("[LifeLineHorizontalLayouter.layout] current x = "+gdeNode.getX()); //System.out.println("[LifeLineHorizontalLayouter.layout] current width = "+gdeNode.getWidth()); gdeNode.setX(x); gdeNode.setWidth(width); //System.out.println("[LifeLineHorizontalLayouter.layout] new x = "+x); //System.out.println("[LifeLineHorizontalLayouter.layout] new width = "+width); } } }; } private void processBracketList(List subbrackets, int offset, boolean shouldShiftRight, ShiftedBracketInfo parentBracketInfo, FrameInfo currentFrameInfo) { int maxRightPos = 0; int maxLeftCentered = 0, maxRightCentered = 0; for (Iterator it = subbrackets.iterator(); it.hasNext(); ) { LMLifeLineBracket subBracket1 = (LMLifeLineBracket) it.next(); if (subBracket1 instanceof LMSimpleLifeLineBracket) { CenteredBracketInfo centeredBracketInfo = processSimpleBracket((LMSimpleLifeLineBracket)subBracket1, parentBracketInfo); maxLeftCentered = StrictMath.max(maxLeftCentered, -centeredBracketInfo.getLeftBorderPos()); maxRightCentered = StrictMath.max(maxRightCentered, centeredBracketInfo.getRightBorderPos()); } else { ShiftedBracketInfo subBracketInfo = processBracket(subBracket1, offset, shouldShiftRight, parentBracketInfo); if (subBracketInfo.getMaxRightPos() > maxRightPos) { maxRightPos = subBracketInfo.getMaxRightPos(); } } subBracket1.updateBracketConsistentState(); } if (currentFrameInfo != null) { //in case there are no subbrackets we should take into account parent bracket prominence int maxRightProminence = Math.max(parentBracketInfo.getMaxRightPos(), Math.max(maxRightPos, maxRightCentered)); //if this frame lies on an execution then it should be prominent to the left //enough to include left side of the bottommost execution under this frame //(this execution lies on a lifeline actually). int maxLeftProminence = Math.max(GeometryConstants.Execution.WIDTH - GeometryConstants.Execution.HORIZONTAL_OFFSET, maxLeftCentered); //if the lifeline's head is inside frame, then make the frame wide enough to contain the head (#28344) //here is an assumption that vertical layout has already worked if (currentFrameInfo.getLMFrame().getGdeNode().getY() <= myLMLifeLine.getGdeNode().getY() && myLMLifeLine.getHeadHeight() <= currentFrameInfo.getLMFrame().getGdeNode().getHeight()) { int headHalfWidth = myLMLifeLine.getHeadNameWidth()/2; maxLeftProminence = Math.max(maxLeftProminence, headHalfWidth); maxRightProminence = Math.max(maxLeftProminence, headHalfWidth); } currentFrameInfo.setMaxBracketPos(myFrameManager.getLifeLineIndex(), maxLeftProminence, maxRightProminence); } adjustLeftHalfWidth(maxLeftCentered); adjustRigthHalfWidth(maxRightCentered); parentBracketInfo.adjustMaxRightPos(maxRightPos); } private CenteredBracketInfo processSimpleBracket(LMSimpleLifeLineBracket bracket, ShiftedBracketInfo parentBracketInfo) { CenteredBracketInfo centeredBracketInfo = new CenteredBracketInfo(bracket, parentBracketInfo.getOffset()); addCenteredBracketInfo(centeredBracketInfo); return centeredBracketInfo; } private ShiftedBracketInfo processBracket(LMLifeLineBracket bracket, int offset, boolean shouldShiftRight, ShiftedBracketInfo parentBracketInfo) { //System.out.println("[RecursiveLayoutSession.processBracket] >>> "+bracket); if (bracket instanceof LMExecutionOccurence) { if (shouldShiftRight && ! ((LMExecutionOccurence) bracket).hasNoDuration()) { offset += GeometryConstants.Execution.HORIZONTAL_OFFSET; } shouldShiftRight = ! ((LMExecutionOccurence) bracket).hasNoDuration(); //shouldShiftRight = true; } ShiftedBracketInfo shiftedBracketInfo = new ShiftedBracketInfo(bracket, parentBracketInfo, offset); shiftedBracketInfo.adjustMaxRightPos(offset - GeometryConstants.Execution.HORIZONTAL_OFFSET + GeometryConstants.Execution.WIDTH); addShiftedBracketInfo(shiftedBracketInfo); if (bracket instanceof LMSendMessageEnd) { LMSendMessageEnd sendMessageEnd = (LMSendMessageEnd) bracket; collectLMMessages(sendMessageEnd); } LMFrame mountedFrame = null; if (bracket instanceof LMMountingRegion) { LMMountingRegion mountingRegion = (LMMountingRegion) bracket; LMMountingLink mountingLink = mountingRegion.getMountingLink(); //System.out.println("[RecursiveLayoutSession.processBracket] mounting link="+mountingLink); if (mountingLink != null) { mountedFrame = mountingLink.getFrame(); //System.out.println("[RecursiveLayoutSession.processBracket] mountedFrame="+mountedFrame); } } FrameInfo frameInfo = null; if (mountedFrame != null) { frameInfo = myFrameManager.frameReferenceStarted(mountedFrame); } try { processBracketList(bracket.getChildBracketsList().getListView(), offset, shouldShiftRight, shiftedBracketInfo, frameInfo); } finally { if (mountedFrame != null) { myFrameManager.frameReferenceFinished(mountedFrame); } } //System.out.println("[RecursiveLayoutSession.processBracket] <<<"); return shiftedBracketInfo; } private void collectLMMessages(LMSendMessageEnd sendMessageEnd) { Collection outgoingMessages = sendMessageEnd.getOutgoingLMMessages(); //System.out.println("[RecursiveLayoutSession.processBracket] outgoing messages: "+outgoingMessages+" from "+sendMessageEnd); myMessagesCollection.addAll(outgoingMessages); } private void addShiftedBracketInfo(ShiftedBracketInfo shiftedBracketInfo) { myShiftedBracketInfoList.add(shiftedBracketInfo); } private void addCenteredBracketInfo(CenteredBracketInfo centeredBracketInfo) { myCenteredBracketInfoList.add(centeredBracketInfo); } private void adjustLeftHalfWidth(int leftHalfWidth) { if (myLeftHalfWidth < leftHalfWidth) { myLeftHalfWidth = leftHalfWidth; } } private void adjustRigthHalfWidth(int rigthHalfWidth) { if (myRightHalfWidth < rigthHalfWidth) { myRightHalfWidth = rigthHalfWidth; } } private final FramesManager myFrameManager; private final Collection myMessagesCollection; private final List myShiftedBracketInfoList = new ArrayList(); private final List myCenteredBracketInfoList = new ArrayList(); private int myLeftHalfWidth = 0; private int myRightHalfWidth = 0; } private static class ShiftedBracketInfo { ShiftedBracketInfo(LMLifeLineBracket lmLifeLineBracket, ShiftedBracketInfo parentBracketInfo, int offset) { myBracket = lmLifeLineBracket; myParentBracketInfo = parentBracketInfo; myMaxRightPos = 0; myOffset = offset; } public ShiftedBracketInfo getParentBracketInfo() { return myParentBracketInfo; } public LMLifeLineBracket getBracket() { return myBracket; } int getOffset() { return myOffset; } private final LMLifeLineBracket myBracket; private final ShiftedBracketInfo myParentBracketInfo; private final int myOffset; private int myMaxRightPos; int getWidth() { return myMaxRightPos - (myOffset - GeometryConstants.Execution.HORIZONTAL_OFFSET); } int getMaxRightPos() { return myMaxRightPos; } void adjustMaxRightPos(int rightPos) { if (myMaxRightPos < rightPos) { myMaxRightPos = rightPos; } } } private static class CenteredBracketInfo { CenteredBracketInfo(LMSimpleLifeLineBracket simpleLifeLineBracket, int offset) { mySimpleLifeLineBracket = simpleLifeLineBracket; myOffset = offset; } public int getLeftBorderPos() { return myOffset - getWidth() / 2; } public int getRightBorderPos() { return myOffset + getWidth() / 2; } int getWidth() { return mySimpleLifeLineBracket.getPreferedWidth(); } int getOffset() { return myOffset; } LMSimpleLifeLineBracket getBracket() { return mySimpleLifeLineBracket; } private final LMSimpleLifeLineBracket mySimpleLifeLineBracket; private final int myOffset; } }