0001: /*
0002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
0003: *
0004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
0005: *
0006: * The contents of this file are subject to the terms of either the GNU
0007: * General Public License Version 2 only ("GPL") or the Common
0008: * Development and Distribution License("CDDL") (collectively, the
0009: * "License"). You may not use this file except in compliance with the
0010: * License. You can obtain a copy of the License at
0011: * http://www.netbeans.org/cddl-gplv2.html
0012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
0013: * specific language governing permissions and limitations under the
0014: * License. When distributing the software, include this License Header
0015: * Notice in each file and include the License file at
0016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
0017: * particular file as subject to the "Classpath" exception as provided
0018: * by Sun in the GPL Version 2 section of the License file that
0019: * accompanied this code. If applicable, add the following below the
0020: * License Header, with the fields enclosed by brackets [] replaced by
0021: * your own identifying information:
0022: * "Portions Copyrighted [year] [name of copyright owner]"
0023: *
0024: * Contributor(s):
0025: *
0026: * The Original Software is NetBeans. The Initial Developer of the Original
0027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
0028: * Microsystems, Inc. All Rights Reserved.
0029: *
0030: * If you wish your version of this file to be governed by only the CDDL
0031: * or only the GPL Version 2, indicate your decision by adding
0032: * "[Contributor] elects to include this software in this distribution
0033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
0034: * single choice of license, a recipient has the option to distribute
0035: * your version of this file under either the CDDL, the GPL Version 2 or
0036: * to extend the choice of license to its licensees as provided above.
0037: * However, if you add GPL Version 2 code and therefore, elected the GPL
0038: * Version 2 license, then the option applies only if the new code is
0039: * made subject to such option by the copyright holder.
0040: */
0041:
0042: package org.netbeans.modules.uml.ui.products.ad.compartments.sequencediagram.lifelinepieces;
0043:
0044: import java.util.ArrayList;
0045: import java.util.Iterator;
0046: import java.util.List;
0047:
0048: import org.netbeans.modules.uml.core.metamodel.core.foundation.IElement;
0049: import org.netbeans.modules.uml.core.metamodel.core.foundation.IPresentationElement;
0050: import org.netbeans.modules.uml.core.metamodel.core.primitivetypes.IMessageKind;
0051: import org.netbeans.modules.uml.core.metamodel.diagrams.IDiagram;
0052: import org.netbeans.modules.uml.core.metamodel.dynamics.IMessage;
0053: import org.netbeans.modules.uml.core.support.Debug;
0054: import org.netbeans.modules.uml.core.support.umlsupport.ETPoint;
0055: import org.netbeans.modules.uml.core.support.umlsupport.IETPoint;
0056: import org.netbeans.modules.uml.core.support.umlsupport.IETRect;
0057: import org.netbeans.modules.uml.core.support.umlutils.ETArrayList;
0058: import org.netbeans.modules.uml.core.support.umlutils.ETList;
0059: import org.netbeans.modules.uml.ui.controls.drawingarea.IUIDiagram;
0060: import org.netbeans.modules.uml.ui.controls.drawingarea.UIDiagram;
0061: import org.netbeans.modules.uml.ui.products.ad.compartments.sequencediagram.ETLifelineCompartment;
0062: import org.netbeans.modules.uml.ui.products.ad.compartments.sequencediagram.IADLifelineCompartment;
0063: import org.netbeans.modules.uml.ui.products.ad.compartments.sequencediagram.IConnectorsCompartment;
0064: import org.netbeans.modules.uml.ui.products.ad.compartments.sequencediagram.LifelineConnectorLocation;
0065: import org.netbeans.modules.uml.ui.products.ad.drawengines.INodeDrawEngine;
0066: import org.netbeans.modules.uml.ui.support.applicationmanager.IEdgePresentation;
0067: import org.netbeans.modules.uml.ui.support.archivesupport.IProductArchiveDefinitions;
0068: import org.netbeans.modules.uml.ui.support.archivesupport.IProductArchiveElement;
0069: import org.netbeans.modules.uml.ui.support.viewfactorysupport.ICompartment;
0070: import org.netbeans.modules.uml.ui.support.viewfactorysupport.IDrawEngine;
0071: import org.netbeans.modules.uml.ui.support.viewfactorysupport.IETGraphObject;
0072: import org.netbeans.modules.uml.ui.support.viewfactorysupport.PresentationHelper;
0073: import org.netbeans.modules.uml.ui.support.viewfactorysupport.TypeConversions;
0074: import org.netbeans.modules.uml.ui.swing.drawingarea.IReconnectEdgeContext;
0075: import org.netbeans.modules.uml.ui.swing.drawingarea.ReconnectEdgeContext;
0076: import com.tomsawyer.drawing.TSConnector;
0077: import com.tomsawyer.drawing.TSDEdge;
0078: import com.tomsawyer.drawing.TSDNode;
0079: import com.tomsawyer.editor.TSEConnector;
0080: import com.tomsawyer.editor.TSEEdge;
0081: import com.tomsawyer.editor.TSENode;
0082: import com.tomsawyer.graph.TSEdge;
0083: import com.tomsawyer.graph.TSGraphObject;
0084: import com.tomsawyer.graph.TSNode; //import com.tomsawyer.jnilayout.TSEdgeDirection;
0085: import com.tomsawyer.util.TSObject;
0086:
0087: /**
0088: *
0089: * @author Trey Spiva
0090: */
0091: public abstract class ConnectorPiece extends ParentPiece {
0092:
0093: public final static int MLF_NONE = 0;
0094: public final static int MLF_TOPLEFT = 1;
0095: public final static int MLF_TOPRIGHT = 2;
0096: public final static int MLF_BOTTOMRIGHT = 4;
0097: public final static int MLF_BOTTOMLEFT = 8;
0098:
0099: private final static int ACTIVATION_CORNER_COUNT = (LifelineConnectorLocation.LCL_BOTTOMLEFT + 1);
0100: private TSConnector[] m_Connectors = new TSConnector[ACTIVATION_CORNER_COUNT];
0101:
0102: /// Strings maintained to support connectors read in from an archive
0103: ArrayList<String> m_strSourceEdgeIDs = new ArrayList<String>();
0104: ArrayList<String> m_strTargetEdgeIDs = new ArrayList<String>();
0105: private boolean m_bUpdatingConnectors = false; // Used to avoid recursion.
0106:
0107: /**
0108: * Creates and initialize a connector piece.
0109: *
0110: * @param parent
0111: * @param parentPiece
0112: * @param topLeft
0113: * @param height
0114: */
0115: public ConnectorPiece(ETLifelineCompartment parent,
0116: LifelineCompartmentPiece parentPiece, IETPoint topLeft,
0117: int height) {
0118: super (parent, parentPiece, topLeft, height);
0119:
0120: for (int i = 0; i < ACTIVATION_CORNER_COUNT; i++) {
0121: m_strSourceEdgeIDs.add("");
0122: m_strTargetEdgeIDs.add("");
0123: }
0124: }
0125:
0126: /**
0127: * Copies height, and connectors from the input piece
0128: *
0129: * @param piece [in] The piece to be copied
0130: * @return The new connector that has no edges attached.
0131: */
0132: public TSConnector copy(ConnectorPiece piece) {
0133: if (null == piece)
0134: throw new IllegalArgumentException();
0135:
0136: TSConnector openConnector = null;
0137:
0138: // These are assumed to have been set
0139: ParentPiece parent = (ParentPiece) getParentPiece();
0140:
0141: // Don't copy these:
0142: // m_Y
0143: // m_strSourceEdgeIDs
0144: // m_strTargetEdgeIDs
0145: // m_cpPresentationHelper
0146:
0147: // Perform a raw height change here, and bump the siblings (below),
0148: // after the connectors have been moved to this piece
0149: // This is because we don't want to affect
0150: // the piece that is currently attached to the edges.
0151: final int iNewHeight = piece.getHeight();
0152: final boolean bChangeHeight = (iNewHeight > getHeight());
0153: if (bChangeHeight) {
0154: parent.setHeight(iNewHeight);
0155: }
0156:
0157: // Process the corner connectors
0158: for (int iIndx = LifelineConnectorLocation.LCL_TOPLEFT; iIndx <= LifelineConnectorLocation.LCL_BOTTOMLEFT; iIndx++) {
0159: boolean bEdgesReconnected = moveConnectorEdges(
0160: piece.m_Connectors[iIndx], iIndx);
0161: if ((!bEdgesReconnected)
0162: && (piece.m_Connectors[iIndx] != null)) {
0163: // This connector is the "open" connector
0164: //assert ( null == openConnector ); // should only have one open connector
0165: openConnector = createConnector(iIndx);
0166: }
0167: }
0168:
0169: // Move the children so the diagram remains consistent
0170: for (Iterator iter = m_ListPieces.iterator(); iter.hasNext();) {
0171: ConnectorPiece child = (ConnectorPiece) iter.next();
0172:
0173: insertPiece(child);
0174: // the child is removed from the input piece below, outside this loop
0175:
0176: // Setting the height forces the grand parents children to get promoted to this child
0177: child.setHeight(child.getHeight());
0178:
0179: for (int iIndx = LifelineConnectorLocation.LCL_TOPLEFT; iIndx <= LifelineConnectorLocation.LCL_BOTTOMLEFT; iIndx++) {
0180: // Remember the connector, but remove it from the piece so we can reattach the connector
0181: // using the proper parent node.
0182: TSConnector connector = child.m_Connectors[iIndx];
0183: child.m_Connectors[iIndx] = null;
0184: child.moveConnectorEdges(connector, iIndx);
0185: }
0186: }
0187:
0188: // Remove the children from the input piece
0189: m_ListPieces.clear();
0190:
0191: // Now that the connectors have been moved to this piece,
0192: // it is safe to bump its siblings.
0193: if (bChangeHeight && (parent != null)) {
0194: parent.bumpSiblingsBelow(this , true);
0195: }
0196:
0197: // Clean up both nodes
0198: getParent().postValidateNode();
0199: piece.getParent().postValidateNode();
0200:
0201: return openConnector;
0202: }
0203:
0204: /**
0205: * Returns true when it is ok to finish a message on this piece
0206: */
0207: public abstract boolean canFinishMessage(int iTop);
0208:
0209: /**
0210: * Test if it is ok to update the input connector location for this piece.
0211: *
0212: * @param corner The corner that is to be updated. Must be on of the values
0213: * in the interface LifelineConnectorLocation
0214: * @return <code>true</code> if the corner can be updated.
0215: * @see LifelineConnectorLocation
0216: */
0217: public abstract boolean canUpdateAssociatedPiece(int corner);
0218:
0219: /**
0220: * Returns the lifeline piece that is attached to the connector.
0221: *
0222: * @param connector The piece that has the attached piece.
0223: * @return The attached piece. <code>null</code> may be returned if
0224: * a piece is not attched to the connector.
0225: * @see CConnectorPiece#AttachConnector(Lcom.tomsawyer.drawing.TSConnector)
0226: */
0227: public static ConnectorPiece getPieceAttachedToConnector(
0228: TSConnector connector) {
0229: ConnectorPiece retVal = null;
0230:
0231: assert connector != null : "The connector is null.";
0232:
0233: if (connector != null) {
0234: Object userObject = connector.getUserObject();
0235: if (userObject instanceof ConnectorPiece) {
0236: retVal = (ConnectorPiece) userObject;
0237: }
0238: }
0239: return retVal;
0240: }
0241:
0242: /**
0243: * From the given product element, which is an edge, determine the associated
0244: * return edge.
0245: *
0246: * @param pETGraphObject The product element, which is an edge, used to
0247: * determine the return edge
0248: *
0249: * @return The return edge, or <code>null</code> if none is available
0250: */
0251: public static TSEEdge getReturnEdge(IETGraphObject pETGraphObject) {
0252: TSEEdge pEdge = null;
0253:
0254: if (pETGraphObject != null) {
0255: IElement element = TypeConversions
0256: .getElement(pETGraphObject);
0257: if (element instanceof IMessage) {
0258: IMessage message = (IMessage) element;
0259: int kind = message.getKind();
0260: switch (kind) {
0261: case IMessageKind.MK_SYNCHRONOUS: {
0262: TSEEdge pEdgeMessage = TypeConversions
0263: .getOwnerEdge(pETGraphObject);
0264: if (pEdgeMessage != null) {
0265: TSConnector pConnector = pEdgeMessage
0266: .getTargetConnector();
0267: if (pConnector != null) {
0268: ConnectorPiece piece = (ConnectorPiece) pConnector
0269: .getUserObject();
0270: if (piece != null) {
0271: pEdge = piece.getReturnEdge();
0272: }
0273: }
0274: }
0275: }
0276: break;
0277:
0278: case IMessageKind.MK_RESULT:
0279: pEdge = TypeConversions
0280: .getOwnerEdge(pETGraphObject);
0281: break;
0282:
0283: default:
0284: break;
0285: }
0286: }
0287: }
0288:
0289: return pEdge;
0290: }
0291:
0292: /**
0293: * Select all the edges associated with the product element, which is also an edge.
0294: *
0295: * @param pETGraphObject[in] The product element that must represent a TS edge
0296: */
0297: public static void selectAssociatedEdges(
0298: IETGraphObject etGraphObject) {
0299: if (etGraphObject != null) {
0300: TSEEdge edge = TypeConversions.getOwnerEdge(etGraphObject);
0301: if (edge != null) {
0302: TSConnector connector = edge.getTargetConnector();
0303: selectAssociatedEdges(connector);
0304: }
0305: }
0306: }
0307:
0308: /**
0309: * Select all the edges associated with the specified connector.
0310: *
0311: * @param pConnector[in]
0312: */
0313: protected static void selectAssociatedEdges(TSConnector connector) {
0314: if (connector != null) {
0315: ConnectorPiece piece = getPieceAttachedToConnector(connector);
0316: if (piece != null) {
0317: piece.selectAssociatedEdges();
0318: }
0319: }
0320: }
0321:
0322: /**
0323: * Select all the edges associated with this piece.
0324: */
0325: public void selectAssociatedEdges() {
0326: for (int iIndx = LifelineConnectorLocation.LCL_TOPLEFT; iIndx <= LifelineConnectorLocation.LCL_TOPRIGHT; iIndx++) {
0327: //selectEdges( m_Connectors[iIndx], true, TSEdgeDirection.TS_OUT_EDGES, true );
0328: }
0329:
0330: for (int iIndx = LifelineConnectorLocation.LCL_BOTTOMRIGHT; iIndx <= LifelineConnectorLocation.LCL_BOTTOMLEFT; iIndx++) {
0331: // Don't allow return messages to select their target piece's edges
0332: //selectEdges( m_Connectors[iIndx], false, TSEdgeDirection.TS_OUT_EDGES, true );
0333: }
0334:
0335: // Select all the edges for the children as well
0336: for (Iterator iter = m_ListPieces.iterator(); iter.hasNext();) {
0337: ParentPiece piece = (ParentPiece) iter.next();
0338: if (piece instanceof ConnectorPiece) {
0339: ConnectorPiece connectorPiece = (ConnectorPiece) piece;
0340:
0341: connectorPiece.selectAssociatedEdges();
0342: }
0343: }
0344: }
0345:
0346: /**
0347: * Select all edges that are going in the specified direction from this connector.
0348: *
0349: * @param pConnector[in] The connector used to determine the out going edges to select
0350: * @param bSelectAssociatedPieces[in] When true the pieces on the target end of the edge are used to select more edges
0351: * @param edgeDirection[in] The direction the edges must be going from the connector to be selected
0352: * @param bInvalidateEdges[in] When true, the edges will be invalidated
0353: */
0354: protected static void selectEdges(TSConnector connector,
0355: boolean bSelectAssociatedPieces, int edgeDirection, /* TSEdgeDirection.TS_OUT_EDGES */
0356: boolean bInvalidateEdges /* true */) {
0357: if (connector != null && connector.degree() > 0) {
0358: List listEdges = null;
0359:
0360: // Select all the edges going in/out to/from this connector
0361: switch (edgeDirection) {/*
0362: case TSEdgeDirection.TS_OUT_EDGES:
0363: listEdges = connector.outEdges();
0364: break;
0365: */
0366: // TODO implement the TSEdgeDirection types
0367: }
0368:
0369: if (listEdges != null) {
0370: // iterate through the list of edges
0371: Iterator iter = listEdges.iterator();
0372: while (iter.hasNext()) {
0373: // Make sure we don't get a path edge.
0374: Object pObject = iter.next();
0375:
0376: TSEEdge edge = pObject instanceof TSEEdge ? (TSEEdge) pObject
0377: : null;
0378: if (edge == null) {
0379: continue;
0380: }
0381:
0382: // select the edge, to be deleted later
0383: edge.setSelected(true);
0384:
0385: if (bInvalidateEdges) {
0386: // invalidate the edge so that the user can see what is to be deleted
0387: IETGraphObject etGraphObject = TypeConversions
0388: .getETGraphObject(edge);
0389: if (etGraphObject != null) {
0390: etGraphObject.invalidate();
0391: }
0392: }
0393:
0394: if (bSelectAssociatedPieces) {
0395: // Determine the target connector, and select its pieces
0396: TSConnector targetConnector = edge
0397: .getTargetConnector();
0398: if (targetConnector != null) {
0399: selectAssociatedEdges(targetConnector);
0400: }
0401: }
0402: }
0403: }
0404: }
0405: }
0406:
0407: /**
0408: * Return the return edge which is connected to the bottom of this piece.
0409: */
0410: public TSEEdge getReturnEdge() {
0411: TSEEdge pEdge = null;
0412:
0413: // Search the bottom corners for any connectors
0414: TSConnector connector = null;
0415: for (int iIndx = LifelineConnectorLocation.LCL_BOTTOMRIGHT; iIndx <= LifelineConnectorLocation.LCL_BOTTOMLEFT; iIndx++) {
0416: if (m_Connectors[iIndx] != null) {
0417: connector = m_Connectors[iIndx];
0418: break;
0419: }
0420: }
0421:
0422: if (connector != null) {
0423: /* jyothi
0424: List outList = connector.outEdges();
0425: if( (outList != null ) && (outList.size() > 0))
0426: {
0427: long lCnt = outList.size();
0428: if( lCnt > 0 )
0429: {
0430: Debug.assertFalse( 1 == lCnt ); // the following code assumes the count is 1
0431: Object object = outList.get(0);
0432:
0433: // Fix J1427: For some reason in the Java side it is possible to get here with
0434: // a TSPEdge that has the TSEEdge as its owner. This happens for example
0435: // when the user deletes an operation from the project tree that is a
0436: // label for a message on the SQD.
0437: {
0438: if( ! (object instanceof TSEEdge ) &&
0439: (object instanceof TSEdge) )
0440: {
0441: object = ((TSEdge)object).getOwner();
0442: }
0443: }
0444:
0445: if (object instanceof TSEEdge)
0446: {
0447: pEdge = (TSEEdge)object;
0448: }
0449: }
0450: }
0451: */
0452: }
0453:
0454: return pEdge;
0455: }
0456:
0457: /**
0458: * Creates a connector at the indicated location on this piece.
0459: *
0460: * @param lclCorner Corner of the piece where the new connector will be attached
0461: * @return The created connector
0462: */
0463: public TSConnector createConnector(int lcl) {
0464: TSConnector retVal = null;
0465:
0466: TSGraphObject gObject = getParent().getOwnerGraphObject();
0467: if (gObject instanceof TSDNode) {
0468: TSDNode node = (TSDNode) gObject;
0469:
0470: // Create and add the new connector to the node
0471: IETPoint pt = getConnectorTopOffset(lcl);
0472: if (pt != null) {
0473: TSConnector connector = node.addConnector();
0474: if (connector instanceof TSConnector) {
0475: retVal = connector;
0476: retVal.setProportionalYOffset(0.5);
0477: retVal.setConstantXOffset(pt.getX());
0478: retVal.setConstantYOffset(pt.getY());
0479: retVal.setVisible(false);
0480:
0481: attachConnector(retVal, lcl, true);
0482: }
0483: }
0484: }
0485:
0486: return retVal;
0487: }
0488:
0489: /**
0490: * Returns the edge attached to this lifeline piece's corner.
0491: *
0492: * @param lclCorner The corner that has the attached edge. The valid
0493: * values are one of the LifelineConnectorLocation values.
0494: * @return The attached edge. If an edge is not attached to the specified
0495: * corner then <code>null</code> will be returned.
0496: * @see LifelineConnectorLocation
0497: */
0498: public TSEdge getAttachedEdge(int lclCorner) {
0499: TSEdge retVal = null;
0500:
0501: TSConnector connector = getConnector(lclCorner);
0502: if (connector != null) {
0503: retVal = PresentationHelper.getConnectedEdge(connector,
0504: false);
0505: }
0506:
0507: return retVal;
0508: }
0509:
0510: /**
0511: * Finds the associated piece via the TS connector
0512: */
0513: public ConnectorPiece getAssociatedPiece(boolean invalidateEdge) {
0514: ConnectorPiece retVal = null;
0515:
0516: TSConnector connector = getAssociatedConnector(invalidateEdge);
0517: if (connector != null) {
0518: retVal = getPieceAttachedToConnector(connector);
0519: }
0520:
0521: return retVal;
0522: }
0523:
0524: /**
0525: * Finds the associated piece via the TS connector
0526: */
0527: ConnectorPiece getAssociatedPiece() {
0528: return getAssociatedPiece(false);
0529: }
0530:
0531: /**
0532: * Finds the associated piece via the TS connector
0533: */
0534: public static ConnectorPiece getAssociatedPiece(
0535: TSConnector connector, boolean invalidateEdge) {
0536: ConnectorPiece retVal = null;
0537:
0538: TSConnector assocConnector = getAssociatedConnector(connector,
0539: invalidateEdge);
0540: if (assocConnector != null) {
0541: retVal = getPieceAttachedToConnector(assocConnector);
0542: }
0543:
0544: return retVal;
0545: }
0546:
0547: /**
0548: * Finds the associated piece via the TS connector
0549: */
0550: public TSConnector getAssociatedConnector(boolean invalidateEdge) {
0551: TSConnector retVal = null;
0552:
0553: TSConnector foundConnector = null;
0554: for (int index = 0; index < m_Connectors.length; index++) {
0555: if (m_Connectors[index] != null) {
0556: foundConnector = m_Connectors[index];
0557: break;
0558: }
0559: }
0560:
0561: if (foundConnector != null) {
0562: retVal = getAssociatedConnector(foundConnector,
0563: invalidateEdge);
0564: }
0565:
0566: return retVal;
0567: }
0568:
0569: /**
0570: * Finds the associated piece via the TS connector
0571: */
0572: public static TSConnector getAssociatedConnector(
0573: TSConnector connector, boolean invalidateEdge) {
0574: TSConnector retVal = null;
0575:
0576: if (connector != null) {
0577: retVal = PresentationHelper.getConnectorOnOtherEndOfEdge(
0578: connector, invalidateEdge);
0579: }
0580:
0581: return retVal;
0582: }
0583:
0584: /**
0585: * Archive functions
0586: */
0587: public IProductArchiveElement writeToArchive(
0588: IProductArchiveElement compartmentElement) {
0589: IProductArchiveElement pieceElement = super
0590: .writeToArchive(compartmentElement);
0591: if (pieceElement != null) {
0592: writeConnectorsToArchive(pieceElement);
0593: }
0594:
0595: return pieceElement;
0596: }
0597:
0598: /**
0599: * Archive functions
0600: */
0601: public void readFromArchive(IProductArchiveElement pieceElement) {
0602: super .readFromArchive(pieceElement);
0603:
0604: readConnectorsFromArchive(pieceElement);
0605: }
0606:
0607: /**
0608: * Attach the connectors determined during readConnectorsFromArchive().
0609: */
0610: public void attachConnectors() {
0611: IDiagram diagram = getDiagram();
0612: if (diagram != null) {
0613: for (int iIndx = LifelineConnectorLocation.LCL_TOPLEFT; iIndx <= LifelineConnectorLocation.LCL_BOTTOMLEFT; iIndx++) {
0614: TSConnector connector = null;
0615: IPresentationElement presentationElement = null;
0616:
0617: final String strSourceEdgeID = m_strSourceEdgeIDs
0618: .get(iIndx);
0619: final String strTargetEdgeID = m_strTargetEdgeIDs
0620: .get(iIndx);
0621: if (strSourceEdgeID.length() > 0) {
0622: presentationElement = diagram
0623: .findPresentationElement(strSourceEdgeID);
0624: if (presentationElement instanceof IEdgePresentation) {
0625: IEdgePresentation edgePE = (IEdgePresentation) presentationElement;
0626:
0627: TSDEdge tsEdge = edgePE.getTSEdge();
0628: if (tsEdge != null) {
0629: connector = tsEdge.getSourceConnector();
0630: }
0631: }
0632: } else if (strTargetEdgeID.length() > 0) {
0633: presentationElement = diagram
0634: .findPresentationElement(strTargetEdgeID);
0635: if (presentationElement instanceof IEdgePresentation) {
0636: IEdgePresentation edgePE = (IEdgePresentation) presentationElement;
0637:
0638: TSDEdge tsEdge = edgePE.getTSEdge();
0639: if (tsEdge != null) {
0640: connector = tsEdge.getTargetConnector();
0641: }
0642: }
0643: }
0644:
0645: if ((presentationElement != null)
0646: && (connector != null)) {
0647: // Fix J1149: When reading from the archive,
0648: // we do not want the connector to update their location.
0649: attachConnector(connector, iIndx, false);
0650:
0651: // We no longer want to set the user field to null
0652: }
0653: }
0654: }
0655:
0656: // Attach all the connectors for the children as well
0657: for (Iterator iter = m_ListPieces.iterator(); iter.hasNext();) {
0658: ParentPiece piece = (ParentPiece) iter.next();
0659: if (piece instanceof ConnectorPiece) {
0660: ConnectorPiece connectorPiece = (ConnectorPiece) piece;
0661:
0662: connectorPiece.attachConnectors();
0663: }
0664: }
0665: }
0666:
0667: /**
0668: * @return True when there is a message connected to either of the top corners.
0669: */
0670: public boolean containsMessagesOnTop() {
0671: boolean retVal = false;
0672:
0673: if ((m_Connectors[LifelineConnectorLocation.LCL_TOPLEFT] != null)
0674: || (m_Connectors[LifelineConnectorLocation.LCL_TOPRIGHT] != null)) {
0675: retVal = true;
0676: }
0677:
0678: return retVal;
0679: }
0680:
0681: /**
0682: * @return True when there is a message connected to either of the bottom corners.
0683: */
0684: public boolean containsMessagesOnBottom() {
0685: boolean retVal = false;
0686:
0687: if ((m_Connectors[LifelineConnectorLocation.LCL_BOTTOMLEFT] != null)
0688: || (m_Connectors[LifelineConnectorLocation.LCL_BOTTOMRIGHT] != null)) {
0689: retVal = true;
0690: }
0691:
0692: return retVal;
0693: }
0694:
0695: /**
0696: * Attach a connector to the piece at the specified location.
0697: *
0698: * @param pConnector The connector to attach to the piece
0699: * @param lclocation The specific location on the piece to attach connector
0700: * @param bMoveConnector (added for java) indicates that the connector's location
0701: * should be move appropriately. The default behavior from should be true.
0702: *
0703: * @see ConnectorPiece#getPieceAttachedToConnector
0704: */
0705: public void attachConnector(TSConnector pConnector, int lpcCorner,
0706: boolean bMoveConnector) {
0707:
0708: if (pConnector != null) {
0709: if (m_Connectors[lpcCorner] == null) {
0710: m_Connectors[lpcCorner] = pConnector;
0711:
0712: // tell the connector the piece to which it is attached
0713: pConnector.setUserObject(this );
0714:
0715: if (bMoveConnector) {
0716: //
0717: // Move the connector now so that we don't have to rely on the draw to update its location
0718: IETPoint ptOffset = getConnectorTopOffset(lpcCorner);
0719: pConnector.setProportionalYOffset(0.5);
0720: pConnector.setProportionalXOffset(0.0);
0721:
0722: pConnector.setConstantXOffset(ptOffset.getX());
0723: pConnector.setConstantYOffset(ptOffset.getY());
0724: }
0725: } else {
0726: // TODO send message to event logger.
0727: }
0728:
0729: }
0730: }
0731:
0732: public boolean containsMessageOnTop() {
0733: boolean retVal = false;
0734:
0735: if ((m_Connectors[LifelineConnectorLocation.LCL_TOPLEFT] != null)
0736: || (m_Connectors[LifelineConnectorLocation.LCL_TOPRIGHT] != null)) {
0737: retVal = true;
0738: }
0739:
0740: return retVal;
0741: }
0742:
0743: public boolean containsMessageOnBottom() {
0744: boolean retVal = false;
0745:
0746: if ((m_Connectors[LifelineConnectorLocation.LCL_BOTTOMLEFT] != null)
0747: || (m_Connectors[LifelineConnectorLocation.LCL_BOTTOMRIGHT] != null)) {
0748: retVal = true;
0749: }
0750:
0751: return retVal;
0752: }
0753:
0754: /**
0755: * Return the location of the input connector on this piece.
0756: *
0757: * @param connector The reference connector.
0758: * @return The location of the connector. Valid values are one of the
0759: * LifelineConnectorLocation values. If the connector is not
0760: * managed by the ConnectorPiece instance then
0761: * LifelineConnectorLocation.LCL_UNKNOWN is returned.
0762: * @see LifelineConnectorLocation
0763: */
0764: public int getLocation(TSConnector connector) {
0765: int retVal = LifelineConnectorLocation.LCL_UNKNOWN;
0766:
0767: double xCenter = connector.getCenterX();
0768: double yCenter = connector.getCenterY();
0769:
0770: for (int index = 0; index < m_Connectors.length; index++) {
0771: TSConnector curConnector = m_Connectors[index];
0772: if (curConnector != null) {
0773: if ((xCenter == curConnector.getCenterX())
0774: && (yCenter == curConnector.getCenterY())) {
0775: retVal = index;
0776: break;
0777: }
0778: }
0779: }
0780:
0781: return retVal;
0782: }
0783:
0784: /*
0785: * (non-Javadoc)
0786: * @see org.netbeans.modules.uml.ui.products.ad.compartments.sequencediagram.lifelinepieces.LifelineCompartmentPiece#setY(long)
0787: */
0788: public void setY(long y) {
0789: if (this .getY() != (int) y) {
0790: super .setY(y);
0791:
0792: // Only update the connectors if y isn't the same.
0793: updateConnectors();
0794: updateChildrenConnectors();
0795: }
0796: }
0797:
0798: /**
0799: * Set the height of this piece. All siblings below this piece will also
0800: * be adjusted.
0801: */
0802: public void setHeight(int height) {
0803: int delta = height - getHeight();
0804:
0805: super .setHeight(height);
0806:
0807: updateConnectors(LifelineConnectorLocation.LCL_BOTTOMRIGHT,
0808: LifelineConnectorLocation.LCL_BOTTOMLEFT);
0809:
0810: // We were updating children connectors here, but this was causing problems
0811: // when we had messages coming back to the activation bar.
0812: // Example problem:
0813: // 3 lifelines: sync msg 1-2, sync msg 2-3, syn msg from 3-1
0814: // Draw a sync msg just above the 1-2 msg, so that the 1-2 moves down.
0815: // The problem seen was that the result msg from 3-1 was slanted.
0816:
0817: if (delta > 0) {
0818: LifelineCompartmentPiece piece = getParentPiece();
0819: if (piece instanceof ParentPiece) {
0820: ParentPiece parentPiece = (ParentPiece) piece;
0821: parentPiece.bumpSiblingsBelow(this , true);
0822: }
0823: }
0824: }
0825:
0826: /**
0827: * Special function to indicate this piece's height changed because siblings
0828: * have changed
0829: *
0830: * @param bottom The new location of the bottom part of the piece.
0831: */
0832: public void grow(int bottom) {
0833: // We need to make sure we only grow each piece once
0834: // A problem occured on a State Farm SQD where we could not move a
0835: // message a large distance
0836: // Issue: W10426
0837:
0838: RecursiveHelper helper = null;
0839: try {
0840: helper = new RecursiveHelper("Grow");
0841: if (RecursiveHelper.isOkToUsePiece("Grow", this )) {
0842: super .grow(bottom);
0843: updateConnectors(
0844: LifelineConnectorLocation.LCL_BOTTOMRIGHT,
0845: LifelineConnectorLocation.LCL_BOTTOMLEFT);
0846: }
0847: } finally {
0848: if (helper != null) {
0849: helper.done();
0850: }
0851: }
0852: }
0853:
0854: /**
0855: * Updates the TS connectors moving them to their proper location within the
0856: * parent node.
0857: *
0858: * @see LifelineConnectorLocation
0859: */
0860: public void updateConnectors() {
0861: updateConnectors(LifelineConnectorLocation.LCL_TOPLEFT,
0862: LifelineConnectorLocation.LCL_BOTTOMLEFT);
0863: }
0864:
0865: /**
0866: * Updates the TS connectors moving them to their proper location within the
0867: * parent node. The connectors set to the location of the pieces.
0868: *
0869: * @param lclBegin The start corner to update. Will be one of the values
0870: * of LifelineConnectorLocation.
0871: * @param lclEnd The end corner to update.Will be one of the values
0872: * of LifelineConnectorLocation.
0873: *
0874: * @see LifelineConnectorLocation
0875: */
0876: public void updateConnectors(int lclBegin, int lclEnd) {
0877: updateConnectors(LifelineConnectorLocation.LCL_TOPLEFT,
0878: LifelineConnectorLocation.LCL_BOTTOMLEFT, 0, 0);
0879: }
0880:
0881: /**
0882: * Updates the TS connectors moving them to their proper location within the
0883: * parent node. The connectors are offset by the xDelta, and yDelta
0884: * values. The additional offset is needed for when the top of a lifeline
0885: * moves. Since the entire node moves, the pieces are in the same relative
0886: * positions, however the connectors on the opposite end of the message
0887: * need to be updated.
0888: *
0889: * @param lclBegin The start corner to update. Will be one of the values
0890: * of LifelineConnectorLocation.
0891: * @param lclEnd The end corner to update.Will be one of the values
0892: * of LifelineConnectorLocation.
0893: * @param xDelta The x offset.
0894: * @param yDelta the y offset.
0895: *
0896: * @see LifelineConnectorLocation
0897: */
0898: public void updateConnectors(int lclBegin, int lclEnd, int xDelta,
0899: int yDelta) {
0900: // Check if we actually have connectors. This will happen when setting
0901: // the height in the constructor.
0902: if (m_Connectors != null && !m_bUpdatingConnectors) {
0903: m_bUpdatingConnectors = true;
0904:
0905: for (int index = lclBegin; index <= lclEnd; index++) {
0906: TSConnector curConnector = m_Connectors[index];
0907: if (curConnector != null) {
0908: double xOrigOffset = curConnector
0909: .getConstantXOffset();
0910: double yOrigOffset = curConnector
0911: .getConstantYOffset();
0912:
0913: IETPoint offset = getConnectorTopOffset(index);
0914: if (((offset.getY() + yDelta) != yOrigOffset)
0915: || ((offset.getX() + xDelta) != xOrigOffset)) {
0916: curConnector.setProportionalYOffset(0.5);
0917: curConnector
0918: .setConstantXOffset((offset.getX() + xDelta));
0919: curConnector.setConstantYOffset(offset.getY()
0920: + yDelta);
0921:
0922: if (canUpdateAssociatedPiece(index) == true) {
0923: // UPDATE, if we get the tool working in CSmartDragTool::UpdateDraggingGraphObjects()
0924: // where the invalidate does not have to be the whole diagram.
0925: // Then we will have to invalidate the edge here. So far
0926: // there is no other reason to invalidate.
0927:
0928: ConnectorPiece associatedPiece = getAssociatedPiece(
0929: curConnector, false);
0930: if (associatedPiece != null) {
0931: if ((index == LifelineConnectorLocation.LCL_TOPLEFT)
0932: || (index == LifelineConnectorLocation.LCL_TOPRIGHT)) {
0933: associatedPiece
0934: .setLogicalTop(getLogicalTop());
0935: } else {
0936: associatedPiece
0937: .setLogicalBottom(getLogicalBottom());
0938: }
0939: } else {
0940: // Since there is no associated piece, the assume is that
0941: // the connectors are to a gate compartment
0942: TSConnector assocConnector = getAssociatedConnector(false);
0943: if (assocConnector != null) {
0944: IDrawEngine engine = TypeConversions
0945: .getDrawEngine(assocConnector);
0946:
0947: ICompartment compartment = TypeConversions
0948: .getCompartment(
0949: assocConnector,
0950: IConnectorsCompartment.class);
0951:
0952: // If there is no piece, we must be on a create message
0953: // So, we need the ILifelineNameCompatment
0954: compartment = engine
0955: .findCompartmentByCompartmentID("LifelineNameCompartment");
0956:
0957: if (compartment instanceof IConnectorsCompartment) {
0958: double origPosition = assocConnector
0959: .getCenterY();
0960:
0961: IConnectorsCompartment connectors = (IConnectorsCompartment) compartment;
0962: connectors
0963: .updateConnectors(null);
0964:
0965: ParentPiece parent = (ParentPiece) getParentPiece();
0966:
0967: IADLifelineCompartment lifelineComp = (IADLifelineCompartment) engine
0968: .findCompartmentByCompartmentID("ADLifelineCompartment");
0969: double delta = origPosition
0970: - assocConnector
0971: .getCenterY();
0972: lifelineComp
0973: .movingCreate((int) delta);
0974:
0975: if (origPosition >= assocConnector
0976: .getCenterY()) {
0977: parent.bumpSiblingsBelow(
0978: this , true);
0979: } else {
0980: parent
0981: .bumpSiblingsAbove(this );
0982: }
0983: }
0984: }
0985: }
0986: }
0987: }
0988: }
0989: }
0990: }
0991:
0992: m_bUpdatingConnectors = false;
0993:
0994: }
0995:
0996: /**
0997: * Updates the TS connectors moving them to their proper location within the parent node
0998: * This routine is only used during a resize, so associated pieces are not updated.
0999: */
1000: public void updateConnectorsViaTopCenter() {
1001: RecursiveHelper helper = null;
1002: try {
1003: helper = new RecursiveHelper("UpdateConnectorsViaTopCenter");
1004: if (RecursiveHelper.isOkToUsePiece(
1005: "UpdateConnectorsViaTopCenter", this )) {
1006: for (int index = LifelineConnectorLocation.LCL_TOPLEFT; index <= LifelineConnectorLocation.LCL_BOTTOMLEFT; index++) {
1007: TSConnector curConnector = getConnector(index);
1008: if (curConnector != null) {
1009: // Move the connector now so that we don't have to rely on the
1010: // draw to update its location
1011: IETPoint ptOffset = getConnectorTopOffset(index);
1012: curConnector.setProportionalYOffset(0.5);
1013: curConnector.setProportionalXOffset(0);
1014:
1015: curConnector
1016: .setConstantXOffset(ptOffset.getX());
1017: curConnector
1018: .setConstantYOffset(ptOffset.getY());
1019: }
1020: }
1021:
1022: ETList<ParentPiece> pieces = getPieces();
1023: for (Iterator<ParentPiece> iter = pieces.iterator(); iter
1024: .hasNext();) {
1025: ParentPiece curPiece = iter.next();
1026: if (curPiece instanceof ConnectorPiece) {
1027: ConnectorPiece connector = (ConnectorPiece) curPiece;
1028: connector.updateConnectorsViaTopCenter();
1029: }
1030: }
1031: }
1032: } finally {
1033: if (helper != null) {
1034: helper.done();
1035: }
1036: }
1037: }
1038:
1039: /**
1040: * Updates the TS connectors moving them to their proper location within the parent node
1041: * This routine is only used during a resize, so associated pieces are not updated.
1042: */
1043: public void updateConnectorsViaBottomCenter() {
1044: RecursiveHelper helper = null;
1045: try {
1046: helper = new RecursiveHelper(
1047: "UpdateConnectorsViaBottomCenter");
1048: if (RecursiveHelper.isOkToUsePiece(
1049: "UpdateConnectorsViaBottomCenter", this )) {
1050: for (int index = LifelineConnectorLocation.LCL_TOPLEFT; index <= LifelineConnectorLocation.LCL_BOTTOMLEFT; index++) {
1051: TSConnector curConnector = getConnector(index);
1052: if (curConnector != null) {
1053: // Move the connector now so that we don't have to rely on the
1054: // draw to update its location
1055: IETPoint ptOffset = getConnectorBottomOffset(index);
1056: curConnector.setProportionalYOffset(-0.5);
1057: curConnector.setProportionalXOffset(0);
1058:
1059: curConnector
1060: .setConstantXOffset(ptOffset.getX());
1061: curConnector
1062: .setConstantYOffset(ptOffset.getY());
1063: }
1064: }
1065:
1066: ETList<ParentPiece> pieces = getPieces();
1067: for (Iterator<ParentPiece> iter = pieces.iterator(); iter
1068: .hasNext();) {
1069: ParentPiece curPiece = iter.next();
1070: if (curPiece instanceof ConnectorPiece) {
1071: ConnectorPiece connector = (ConnectorPiece) curPiece;
1072: connector.updateConnectorsViaTopCenter();
1073: }
1074: }
1075: }
1076: } finally {
1077: if (helper != null) {
1078: helper.done();
1079: }
1080: }
1081: }
1082:
1083: /**
1084: * Updates the TS connectors of all the children
1085: */
1086: public void updateChildrenConnectors() {
1087: // Attach all the connectors for the children as well
1088: ETList<ParentPiece> pieces = getPieces();
1089: for (Iterator<ParentPiece> iter = pieces.iterator(); iter
1090: .hasNext();) {
1091: ParentPiece curPiece = iter.next();
1092: if (curPiece instanceof ConnectorPiece) {
1093: ConnectorPiece cPiece = (ConnectorPiece) curPiece;
1094:
1095: cPiece.updateConnectors();
1096: cPiece.updateChildrenConnectors();
1097: }
1098: }
1099: }
1100:
1101: /**
1102: * Validate the lifeline and all its child pieces
1103: */
1104: public boolean validate() {
1105: // Ensure that the y value is not too small
1106: super .setY(getY());
1107:
1108: for (int indx = LifelineConnectorLocation.LCL_TOPLEFT; indx <= LifelineConnectorLocation.LCL_BOTTOMLEFT; indx++) {
1109: if (m_Connectors[indx] != null) {
1110: // Determine if there is an edge connected to this connector
1111: TSEdge edge = PresentationHelper.getConnectedEdge(
1112: m_Connectors[indx], false);
1113: if (edge == null) {
1114: IDrawEngine drawEngine = getDrawEngine();
1115: if (drawEngine instanceof INodeDrawEngine) {
1116: INodeDrawEngine nodeEngine = (INodeDrawEngine) drawEngine;
1117:
1118: TSENode node = nodeEngine.getNode();
1119: if (node != null) {
1120: try {
1121: node.remove(m_Connectors[indx]);
1122: } catch (RuntimeException exception) {
1123: // Tom Sawyer will throw a RuntimeException if the
1124: // node does not actually contain the connector.
1125: // This can happen during a delete i.e. The connector
1126: // has already been removed from the node before the
1127: // validate was called.
1128: }
1129: }
1130: }
1131:
1132: m_Connectors[indx] = null;
1133: }
1134: }
1135: }
1136:
1137: // Why do we need to update connectors here?
1138: // TEST updateConnectors();
1139:
1140: boolean hasChildren = super .validate();
1141:
1142: return (hasChildren || hasMessagesAttached());
1143: }
1144:
1145: /**
1146: * Delete an edge, its connectors, and any pieces attached to the target of
1147: * the edge.
1148: *
1149: * @param edge The product element that must represent a TS edge to be
1150: * deleted.
1151: */
1152: public static void deleteEdge(IETGraphObject edge) {
1153: if (edge != null) {
1154: TSEdge tsEdge = TypeConversions.getOwnerEdge(edge);
1155: deleteEdge(tsEdge);
1156: }
1157: }
1158:
1159: /**
1160: * Delete an edge, its connectors, and any pieces attached to the target of
1161: * the edge.
1162: *
1163: * @param pEdge The TS edge to be deleted
1164: */
1165: public static void deleteEdge(TSEdge edge) {
1166: if (edge instanceof TSDEdge) {
1167: TSDEdge connectorEdge = (TSDEdge) edge;
1168:
1169: // Delete both the source and target pieces
1170: TSConnector connector = connectorEdge.getSourceConnector();
1171: deletePieceAttachedToConnector(connector);
1172: deleteConnectorFromNode(connector);
1173:
1174: connector = connectorEdge.getTargetConnector();
1175: deletePieceAttachedToConnector(connector);
1176: deleteConnectorFromNode(connector);
1177: }
1178: }
1179:
1180: /**
1181: * Find all the messages from this piece and all its associated messages.
1182: */
1183: public void getPropagatedMessages(ETList<IMessage> messages) {
1184: if (null == messages)
1185: throw new IllegalArgumentException();
1186:
1187: TSEEdge topEdge = findTopEdge();
1188: if (topEdge != null) {
1189: IElement element = TypeConversions.getElement(topEdge);
1190: if (element instanceof IMessage) {
1191: messages.add((IMessage) element);
1192: }
1193: }
1194:
1195: // The activation bar and suspension area classes get the rest of the messagess
1196: }
1197:
1198: //**************************************************
1199: // Helper Methods
1200: //**************************************************
1201:
1202: /**
1203: * Deletes the connector from its owner node.
1204: *
1205: * @param connector The connector to be deleted from its owner node
1206: */
1207: protected static void deleteConnectorFromNode(TSConnector connector) {
1208: if (connector != null) {
1209: TSGraphObject gObject = connector.getOwner();
1210: if (gObject instanceof TSENode) {
1211: TSENode node = (TSENode) gObject;
1212: if ((node != null) && (connector.getOwner() == node)) {
1213: try {
1214: node.remove(connector);
1215: } catch (RuntimeException exception) {
1216: // Tom Sawyer will throw a RuntimeException if the
1217: // node does not actually contain the connector.
1218: // This can happen during a delete i.e. The connector
1219: // has already been removed from the node before the
1220: // validate was called.
1221: //
1222: // We should never get here because of the owner check.
1223: Debug.assertFalse(false, exception
1224: .getLocalizedMessage());
1225: }
1226: }
1227: }
1228: }
1229: }
1230:
1231: /**
1232: * Delete the piece associated with the connector.
1233: *
1234: * @param connector The connector that is about to be deleted.
1235: */
1236: protected static void deletePieceAttachedToConnector(
1237: TSConnector connector) {
1238: if (connector != null) {
1239: Object userObject = connector.getUserObject();
1240: if (userObject instanceof LifelineCompartmentPiece) {
1241: LifelineCompartmentPiece piece = (LifelineCompartmentPiece) userObject;
1242: if (piece != null) {
1243: // Fix W4003: Just post a validate message to clean up the lifeline
1244: piece.getParent().postValidateNode();
1245: }
1246: }
1247: }
1248: }
1249:
1250: /**
1251: * Determines if there are any messages attached to the piece.
1252: *
1253: * @return <code>true</code> indicating that messages are attached.
1254: */
1255: protected boolean hasMessagesAttached() {
1256: int hasMessagesAttached = MLF_NONE;
1257:
1258: int[] convertIndxToMLF = { MLF_TOPLEFT, MLF_TOPRIGHT,
1259: MLF_BOTTOMRIGHT, MLF_BOTTOMLEFT };
1260:
1261: for (int iIndx = 0; iIndx < ACTIVATION_CORNER_COUNT; iIndx++) {
1262: if (m_Connectors[iIndx] != null) {
1263: hasMessagesAttached |= convertIndxToMLF[iIndx];
1264: }
1265: }
1266:
1267: return hasMessagesAttached != MLF_NONE;
1268: }
1269:
1270: /**
1271: * Finds the top most edge on this piece or any of its children
1272: */
1273: public TSEEdge findTopEdge() {
1274: // Search the bottom corners for any connectors
1275: TSConnector connector = null;
1276: for (int iIndx = LifelineConnectorLocation.LCL_TOPLEFT; iIndx <= LifelineConnectorLocation.LCL_TOPRIGHT; iIndx++) {
1277: if (m_Connectors[iIndx] != null) {
1278: connector = m_Connectors[iIndx];
1279: break;
1280: }
1281: }
1282:
1283: return getConnectorsEdge(connector);
1284: }
1285:
1286: /*
1287: * Returns true if the connector has edges connected to it, in or out.
1288: */
1289: private boolean isConnected(TSConnector originalConnector) {
1290: return originalConnector != null
1291: && originalConnector.degree() > 0;
1292: }
1293:
1294: /**
1295: * Move all the edges from the original connector to a new connector on this piece
1296: *
1297: * @param originalConnector containing possibly edges
1298: * @param lclCorner LifelineConnectorLocation to which the edges are to be connected
1299: * @return true when edges were reconnected
1300: */
1301: protected boolean moveConnectorEdges(TSConnector originalConnector,
1302: int lclCorner) {
1303: // originalConnector is allowed to be null
1304:
1305: boolean bEdgesReconnected = false;
1306:
1307: if (!isConnected(originalConnector))
1308: return false;
1309:
1310: if (originalConnector != null) {
1311: // For the following code there should be only one edge connected to the connector
1312: // So, we process accordingly
1313: TSConnector connector = null;
1314: TSDEdge tsEdge = null;
1315: TSNode oldNode = null;
1316: TSNode newNode = null;
1317:
1318: // List inEdgeList = originalConnector.inEdges();
1319:
1320: // (TS 7/12/05) Tom Sawyer's API has changed between 5.x and 6.0. They have removed
1321: // the inEdges and the outEdges and added the incidentEdges methods.
1322: // The incidentEdges will return all of the edges connected to the connector.
1323: List inEdgeList = originalConnector.incidentEdges();
1324: if (inEdgeList.size() > 0) {
1325: // Debug.assertFalse(inEdgeList.size() == 1, "The following code assumes the count is 1");
1326:
1327: // Only create the new connector when there is an edge associated with the old connector
1328: connector = createConnector(lclCorner);
1329: if (connector != null) {
1330: newNode = (TSNode) connector.getOwner();
1331:
1332: if (inEdgeList.get(0) instanceof TSDEdge) {
1333: // (TS 4/1/05) The below code now returns the graph that ownes the edge.
1334: // They use to have two constructs one for layout and the one everyone
1335: // used. Now there is only one edge type.
1336: // TSGraphObject gObject = ((TSEdge)inEdgeList.get(0)).getOwner();
1337: // if (gObject instanceof TSDEdge)
1338: {
1339: // tsEdge = (TSDEdge)gObject;
1340: tsEdge = (TSDEdge) inEdgeList.get(0);
1341: if (originalConnector.equals(tsEdge
1342: .getTargetConnector()) == true) {
1343: oldNode = tsEdge.getTargetNode();
1344: tsEdge.setTargetConnector(connector);
1345: } else {
1346: oldNode = tsEdge.getSourceNode();
1347: tsEdge.setSourceNode(newNode);
1348: tsEdge.setSourceConnector(connector);
1349: }
1350: }
1351: }
1352: }
1353: }
1354: // else if (originalConnector.outEdges().size() > 0)
1355: // {
1356: // connector = createConnector( lclCorner );
1357: // if( connector != null )
1358: // {
1359: // newNode = (TSNode)connector.getOwner();
1360: //
1361: // if (originalConnector.outEdges().get(0) instanceof TSEdge)
1362: // {
1363: // TSEdge pEdge = (TSEdge)originalConnector.outEdges().get(0);
1364: // TSGraphObject gObject = ((TSEdge)originalConnector.outEdges().get(0)).getOwner();
1365: // if (gObject instanceof TSDEdge)
1366: // {
1367: // tsEdge = (TSDEdge)gObject;
1368: // oldNode = pEdge.getSourceNode();
1369: // tsEdge.setSourceNode(newNode);
1370: // tsEdge.setSourceConnector( connector );
1371: // }
1372: // }
1373: // }
1374: // }
1375:
1376: if ((connector != null) && (tsEdge != null)
1377: && (oldNode != null) && (newNode != null)) {
1378: // Now that the TS information is all updated, process the meta data
1379: IEdgePresentation edgePE = TypeConversions
1380: .getEdgePresentation(tsEdge);
1381: if (edgePE != null) {
1382: IReconnectEdgeContext context = new ReconnectEdgeContext();
1383:
1384: context.setPreConnectNode(TypeConversions
1385: .getETNode(oldNode));
1386: context.setProposedEndNode(TypeConversions
1387: .getETNode(newNode));
1388:
1389: edgePE.reconnectLink(context);
1390:
1391: bEdgesReconnected = true;
1392: }
1393: }
1394: }
1395:
1396: return bEdgesReconnected;
1397: }
1398:
1399: /**
1400: * Returns the point where a connector should be attached, for the specified location on the piece.
1401: * This offset is calculated from the top center of the TS node in TS absolute logical units.
1402: *
1403: * @param lclocation[in] location to calculate offset from
1404: *
1405: * @return
1406: */
1407: protected IETPoint getConnectorTopOffset(int lclocation) {
1408: IETRect rectEngine = getEngineLogicalBoundingRect();
1409: double horzCenter = rectEngine.getCenterX();
1410: IETRect rectDraw = getDrawRect(1.0);
1411:
1412: ETPoint ptOffset = new ETPoint(0, 0);
1413: switch (lclocation) {
1414: case LifelineConnectorLocation.LCL_TOPLEFT:
1415: ptOffset.setX((int) (rectDraw.getLeft() - horzCenter));
1416: ptOffset.setY(-rectDraw.getTop());
1417: break;
1418:
1419: case LifelineConnectorLocation.LCL_TOPRIGHT:
1420: ptOffset.setX((int) (rectDraw.getRight() - horzCenter));
1421: ptOffset.setY(-rectDraw.getTop());
1422: break;
1423:
1424: case LifelineConnectorLocation.LCL_BOTTOMRIGHT:
1425: ptOffset.setX((int) (rectDraw.getRight() - horzCenter));
1426: ptOffset.setY(-(rectDraw.getIntY() + rectDraw
1427: .getIntHeight()));
1428: break;
1429:
1430: case LifelineConnectorLocation.LCL_BOTTOMLEFT:
1431: ptOffset.setX((int) (rectDraw.getLeft() - horzCenter));
1432: ptOffset.setY(-(rectDraw.getIntY() + rectDraw
1433: .getIntHeight()));
1434: break;
1435:
1436: default:
1437: // did we add another location?
1438: break;
1439: }
1440:
1441: return ptOffset;
1442: }
1443:
1444: /**
1445: * Returns the point where a connector should be attached, for the specified location on the piece.
1446: * This offset is calculated from the bottom center of the TS node in TS absolute logical units.
1447: *
1448: * @param lclocation location to calculate offset from
1449: * @return The connecotr.
1450: *
1451: * @see CConnectorPiece::GetConnectorTopOffset()
1452: */
1453: protected IETPoint getConnectorBottomOffset(int lclocation) {
1454: IETPoint retVal = getConnectorTopOffset(lclocation);
1455: IETRect rectEngine = getEngineLogicalBoundingRect();
1456: retVal.setY(rectEngine.getIntHeight() - (-retVal.getY()));
1457:
1458: return retVal;
1459: }
1460:
1461: /**
1462: * Retreieves the connector at a specified location. The location of the
1463: * connector is one of the LifelineConnectorLocation values.
1464: *
1465: * @param location The location of the connector to retrieve.
1466: * @return The connector at the location or <code>null</code> if a connector
1467: * is not at the location.
1468: *
1469: * @see LifelineConnectorLocation
1470: */
1471: public TSConnector getConnector(int location) {
1472: return m_Connectors[location];
1473: }
1474:
1475: /**
1476: * Save the information about the connectors to the archive.
1477: */
1478: protected void writeConnectorsToArchive(
1479: IProductArchiveElement parentElement) {
1480: if (parentElement != null) {
1481: IProductArchiveElement connectorListElement = null;
1482:
1483: for (int iIndx = LifelineConnectorLocation.LCL_TOPLEFT; iIndx <= LifelineConnectorLocation.LCL_BOTTOMLEFT; iIndx++) {
1484: if (m_Connectors[iIndx] != null) {
1485: // Determine if there is an edge connected to this connector
1486: TSDEdge tsEdge = PresentationHelper
1487: .getConnectedEdge(m_Connectors[iIndx],
1488: false);
1489: if (tsEdge != null) {
1490: IPresentationElement pe = TypeConversions
1491: .getPresentationElement(tsEdge);
1492: if (pe != null) {
1493: String strXMIID = pe.getXMIID();
1494: if (strXMIID.length() > 0) {
1495: if (null == connectorListElement) {
1496: connectorListElement = parentElement
1497: .createElement(IProductArchiveDefinitions.ADLIFELINECONNECTORLIST_STRING);
1498: }
1499:
1500: if (connectorListElement != null) {
1501: IProductArchiveElement connectorElement = connectorListElement
1502: .createElement(IProductArchiveDefinitions.ADLIFELINECONNECTOR_STRING);
1503: if (connectorElement != null) {
1504: connectorElement
1505: .addAttributeLong(
1506: IProductArchiveDefinitions.ADLIFELINECONNECTOR_LOCATION_STRING,
1507: iIndx);
1508:
1509: TSConnector source = tsEdge
1510: .getSourceConnector();
1511: final String strEnd = TypeConversions
1512: .areSameTSObjects(
1513: m_Connectors[iIndx],
1514: source) ? IProductArchiveDefinitions.ADLIFELINECONNECTOR_SOURCE_STRING
1515: : IProductArchiveDefinitions.ADLIFELINECONNECTOR_TARGET_STRING;
1516:
1517: connectorElement
1518: .addAttributeString(
1519: strEnd,
1520: strXMIID);
1521: }
1522: }
1523: }
1524: }
1525: }
1526: }
1527: }
1528: }
1529: }
1530:
1531: /**
1532: * Retrieve the information about the connectors from the archive.
1533: *
1534: * @param parentElement
1535: */
1536: protected void readConnectorsFromArchive(
1537: IProductArchiveElement parentElement) {
1538: if (parentElement != null) {
1539: IProductArchiveElement compartmentListElement = parentElement
1540: .getElement(IProductArchiveDefinitions.ADLIFELINECONNECTORLIST_STRING);
1541: if (compartmentListElement != null) {
1542: IProductArchiveElement[] compartmentElements = compartmentListElement
1543: .getElements();
1544: int nCnt = compartmentElements.length;
1545: for (int nIndx = 0; nIndx < nCnt; nIndx++) {
1546: IProductArchiveElement element = compartmentElements[nIndx];
1547:
1548: if (element != null) {
1549: int location = (int) element
1550: .getAttributeLong(IProductArchiveDefinitions.ADLIFELINECONNECTOR_LOCATION_STRING);
1551: if ((location >= LifelineConnectorLocation.LCL_TOPLEFT)
1552: && (location <= LifelineConnectorLocation.LCL_BOTTOMLEFT)) {
1553: String strSource = element
1554: .getAttributeString(IProductArchiveDefinitions.ADLIFELINECONNECTOR_SOURCE_STRING);
1555: if (strSource.length() > 0) {
1556: m_strSourceEdgeIDs.set(location,
1557: strSource);
1558: } else {
1559: String strTarget = element
1560: .getAttributeString(IProductArchiveDefinitions.ADLIFELINECONNECTOR_TARGET_STRING);
1561: if (strTarget.length() > 0) {
1562: m_strTargetEdgeIDs.set(location,
1563: strTarget);
1564: }
1565: }
1566: }
1567: }
1568: }
1569: }
1570: }
1571: }
1572:
1573: /**
1574: * Return the edge associated with this connector
1575: */
1576: protected TSEEdge getConnectorsEdge(TSConnector connector) {
1577: TSEEdge edge = null;
1578:
1579: // I (BDB) was not able to determine how dot use buildInOutEdges()
1580: TSDEdge tsdEdge = PresentationHelper.getConnectedEdge(
1581: connector, false);
1582: if (tsdEdge instanceof TSEEdge) {
1583: edge = (TSEEdge) tsdEdge;
1584: }
1585:
1586: return edge;
1587: }
1588:
1589: protected int getBottomBound() {
1590: int retVal = super .getBottomBound();
1591:
1592: //getDrawTop
1593: if ((getHeight() == 0)
1594: && (getLifelinePiecesKind() == LifelinePiecesKind.LPK_SUSPENSION)) {
1595: TSConnector connector = getAssociatedConnector(false);
1596: if ((connector != null)
1597: && (getPieceAttachedToConnector(connector) == null)) {
1598: // Since we do not have an associated piece, the assumption is
1599: // that we are connected to a gate. Therefore you the draw engine
1600: // head instead.
1601: retVal = getDETop();
1602: }
1603: }
1604:
1605: return retVal;
1606: }
1607:
1608: public void moveConnectorsBy(int delta,
1609: boolean updateAssociatedPieces) {
1610:
1611: updateConnectors(LifelineConnectorLocation.LCL_TOPLEFT,
1612: LifelineConnectorLocation.LCL_BOTTOMLEFT, 0, delta);
1613:
1614: for (ParentPiece child : getPieces()) {
1615: if (child instanceof ConnectorPiece) {
1616: ConnectorPiece connectorPiece = (ConnectorPiece) child;
1617: connectorPiece.moveConnectorsBy(delta,
1618: updateAssociatedPieces);
1619: }
1620: }
1621: }
1622: }
|