001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.modules.uml.ui.products.ad.diagramengines.sequencediagram;
043:
044: import java.awt.Color;
045: import java.awt.event.MouseEvent;
046: import java.util.Iterator;
047:
048: import org.netbeans.modules.uml.core.metamodel.core.foundation.IElement;
049: import org.netbeans.modules.uml.core.metamodel.core.foundation.IPresentationElement;
050: import org.netbeans.modules.uml.core.metamodel.core.primitivetypes.IMessageKind;
051: import org.netbeans.modules.uml.core.metamodel.diagrams.IDiagram;
052: import org.netbeans.modules.uml.core.metamodel.diagrams.IGraphEventKind;
053: import org.netbeans.modules.uml.core.metamodel.dynamics.IMessage;
054: import org.netbeans.modules.uml.core.metamodel.infrastructure.coreinfrastructure.IClassifier;
055: import org.netbeans.modules.uml.core.metamodel.infrastructure.coreinfrastructure.IFeature;
056: import org.netbeans.modules.uml.core.metamodel.infrastructure.coreinfrastructure.IOperation;
057: import org.netbeans.modules.uml.core.support.Debug;
058: import org.netbeans.modules.uml.core.support.umlsupport.ETRect;
059: import org.netbeans.modules.uml.core.support.umlsupport.IETPoint;
060: import org.netbeans.modules.uml.core.support.umlsupport.IETRect;
061: import org.netbeans.modules.uml.core.support.umlutils.ETList;
062: import org.netbeans.modules.uml.core.support.umlutils.ElementLocator;
063: import org.netbeans.modules.uml.core.support.umlutils.IElementLocator;
064: import org.netbeans.modules.uml.ui.products.ad.ADDrawEngines.IADDrawEngineButtonHandler;
065: import org.netbeans.modules.uml.ui.products.ad.compartments.SmartDragHelper;
066: import org.netbeans.modules.uml.ui.products.ad.compartments.sequencediagram.lifelinepieces.ActivationBar;
067: import org.netbeans.modules.uml.ui.products.ad.compartments.sequencediagram.lifelinepieces.ConnectorPiece;
068: import org.netbeans.modules.uml.ui.products.ad.compartments.sequencediagram.IConnectorsCompartment;
069: import org.netbeans.modules.uml.ui.products.ad.compartments.sequencediagram.lifelinepieces.LifelineCompartmentPiece;
070: import org.netbeans.modules.uml.ui.products.ad.compartments.sequencediagram.lifelinepieces.LifelinePiece;
071: import org.netbeans.modules.uml.ui.products.ad.diagramengines.IADSequenceDiagEngine;
072: import org.netbeans.modules.uml.ui.products.ad.drawengines.ETDrawEngine;
073: import org.netbeans.modules.uml.ui.products.ad.drawengines.ETEdgeDrawEngine;
074: import org.netbeans.modules.uml.ui.products.ad.viewfactory.IETGraphObjectUI;
075: import org.netbeans.modules.uml.ui.support.applicationmanager.IEdgePresentation;
076: import org.netbeans.modules.uml.ui.support.applicationmanager.IGraphPresentation;
077: import org.netbeans.modules.uml.ui.support.archivesupport.IProductArchive;
078: import org.netbeans.modules.uml.ui.support.archivesupport.IProductArchiveDefinitions;
079: import org.netbeans.modules.uml.ui.support.archivesupport.IProductArchiveElement;
080: import org.netbeans.modules.uml.ui.support.viewfactorysupport.DrawEngineArrowheadKindEnum;
081: import org.netbeans.modules.uml.ui.support.viewfactorysupport.DrawEngineLineKindEnum;
082: import org.netbeans.modules.uml.ui.support.viewfactorysupport.ETRectEx;
083: import org.netbeans.modules.uml.ui.support.viewfactorysupport.ICompartment;
084: import org.netbeans.modules.uml.ui.support.viewfactorysupport.IDrawEngine;
085: import org.netbeans.modules.uml.ui.support.viewfactorysupport.IDrawInfo;
086: import org.netbeans.modules.uml.ui.support.viewfactorysupport.IETGraphObject;
087: import org.netbeans.modules.uml.ui.support.viewfactorysupport.ILabelManager;
088: import org.netbeans.modules.uml.ui.support.viewfactorysupport.INotificationTargets;
089: import org.netbeans.modules.uml.ui.support.viewfactorysupport.ISetCursorEvent;
090: import org.netbeans.modules.uml.ui.support.viewfactorysupport.ModelElementChangedKind;
091: import org.netbeans.modules.uml.ui.support.viewfactorysupport.TypeConversions;
092: import org.netbeans.modules.uml.ui.swing.drawingarea.ADGraphWindow;
093: import org.netbeans.modules.uml.ui.swing.drawingarea.IDiagramEngine;
094: import org.netbeans.modules.uml.ui.swing.drawingarea.IDrawingAreaControl;
095: import org.netbeans.modules.uml.ui.swing.drawingarea.cursors.ETHorzDragCursor;
096: import org.netbeans.modules.uml.ui.swing.drawingarea.diagramtools.SmartDragTool;
097: import com.tomsawyer.drawing.TSConnector;
098: import com.tomsawyer.editor.TSEEdge;
099: import com.tomsawyer.editor.TSEGraph;
100: import com.tomsawyer.editor.TSENode;
101: import com.tomsawyer.editor.TSEObject; //import com.tomsawyer.editor.state.TSEMoveSelectedState;
102: import com.tomsawyer.editor.tool.TSEMoveSelectedTool;
103: import com.tomsawyer.graph.TSGraphObject;
104: import com.tomsawyer.graph.TSNode; //import com.tomsawyer.util.TSConstPoint;
105: import com.tomsawyer.drawing.geometry.TSConstPoint;
106: import org.openide.util.NbPreferences;
107:
108: /**
109: * The MessageEdgeDrawEngine provides drawing support for an TSGraphObject.
110: * There is a one to one relationship between an TSGraphObject and an
111: * MessageEdgeDrawEngine.
112: *
113: * @author Trey Spiva
114: */
115: public class MessageEdgeDrawEngine extends ETEdgeDrawEngine implements
116: IMessageEdgeDrawEngine {
117: private final static String MDE_SHOW = "Show";
118: private final static String MDE_SHOWMESSAGETYPE = "ShowMessageType";
119:
120: /**
121: * Stores the type of line to draw. Return messages will draw dashed lines
122: * all other messages will be solid.
123: */
124: private int m_LineKind = DrawEngineLineKindEnum.DELK_UNKNOWN;
125:
126: private boolean m_IsMessageToSelf = false;
127:
128: private boolean m_Show = true;
129:
130: private int m_ShowMessageType = -1;
131:
132: private LifelinePiece m_PieceSelf = null;
133: // private MessageRelocator m_MessageRelocator = null;
134: private final static int FUDGE_DRAW_ENGINE_ABOVE = 2;
135: private final static int ACTIVATION_BAR_BUFFER = 10;
136:
137: /**
138: * Stores the type of arrow head to display. The arrow head is determined
139: * by the model type.
140: */
141: private int m_ArrowHeadKind = DrawEngineArrowheadKindEnum.DEAK_NO_ARROWHEAD;
142:
143: public MessageEdgeDrawEngine() {
144: }
145:
146: public String getElementType() {
147: String type = super .getElementType();
148: if (type == null) {
149: type = new String("Message");
150: }
151: return type;
152: }
153:
154: /**
155: * This is the name of the drawengine used when storing and reading from
156: * the product archive
157: *
158: * @return A unique identifier for this draw engine. Used when persisting
159: * to the etlp file.
160: */
161: public String getDrawEngineID() {
162: return "MessageEdgeDrawEngine";
163: }
164:
165: private static SmartDragHelper m_smartDragHelper = null;
166:
167: /* (non-Javadoc)
168: * @see org.netbeans.modules.uml.ui.support.viewfactorysupport.IDrawEngine#handleLeftMouseButtonPressed(org.netbeans.modules.uml.core.support.umlsupport.IETPoint, java.awt.event.MouseEvent )
169: */
170: public boolean handleLeftMouseButtonPressed(MouseEvent pEvent) {
171: IDrawingAreaControl daCtrl = getDrawingArea();
172: ADGraphWindow graphWindow = daCtrl != null ? daCtrl
173: .getGraphWindow() : null;
174:
175: SmartDragTool dragTool = createSmartDragTool(pEvent);
176:
177: if (dragTool != null) {
178: m_smartDragHelper = new SmartDragHelper("Layout");
179:
180: TSEEdge edge = this .getEdge();
181:
182: if (m_IsMessageToSelf) {
183: if (m_PieceSelf == null)
184: initializePieceSelf(edge);
185: dragTool.setDraggingPiece(m_PieceSelf,
186: getMessageKind() != IMessageKind.MK_RESULT);
187: } else {
188: dragTool.setDraggingEdge(edge, 0);
189: }
190:
191: dragTool
192: .setDragRestrictionType(SmartDragTool.DR.VERTICAL_MOVE_ONLY);
193:
194: IDiagram diagram = getDiagram();
195: if (diagram != null) {
196: IDiagramEngine diagramEngine = TypeConversions
197: .getDiagramEngine(diagram);
198: IADSequenceDiagEngine sqdEngine = null;
199: if (diagramEngine instanceof IADSequenceDiagEngine)
200: sqdEngine = (IADSequenceDiagEngine) diagramEngine;
201:
202: if (sqdEngine != null) {
203: final IETRect rectThisMessage = getLogicalBoundingRect();
204:
205: IDrawEngine engine = sqdEngine
206: .findFirstDrawEngineAbove("Message",
207: rectThisMessage.getTop()
208: + FUDGE_DRAW_ENGINE_ABOVE);
209:
210: if (engine != null) {
211: final IETRect rectAboveMessage = TypeConversions
212: .getLogicalBoundingRect(engine);
213:
214: int aboveMessageBottom = rectAboveMessage
215: .getBottom()
216: - (m_IsMessageToSelf ? 2 * ACTIVATION_BAR_BUFFER
217: : ACTIVATION_BAR_BUFFER);
218:
219: IETRect rect = new ETRect(
220: Integer.MIN_VALUE / 2,
221: aboveMessageBottom, Integer.MAX_VALUE,
222: Integer.MAX_VALUE / 2);
223:
224: dragTool.setRestrictedArea(rect);
225: }
226: }
227: }
228: //graphWindow.getCurrentState().setState(dragTool);
229: graphWindow.getCurrentTool().setTool(dragTool);
230: dragTool.onMousePressed(pEvent);
231: }
232:
233: return true;
234: }
235:
236: /**
237: * Activate the smart drag tool so we can move the edges up and down, maintaining their
238: * horizontal alignment.
239: *
240: * @param pMouseEvent [in] Information about the event that just occured
241: * @param pTool [out] Return a tool here to make it the current tool on the GET
242: * @param bHandled [out] true to cancel the event. This indicates we handled it.
243: */
244: public boolean handleSetCursor(ISetCursorEvent event) {
245: if (null == event)
246: throw new IllegalArgumentException();
247:
248: // TODO support using the control key
249: // if( getAsyncKeyState( VK_CONTROL ))
250: // {
251: // event.setCursor( afxGetApp().loadCursor( IDC_SPLIT_V_MOVE ));
252: // }
253: // else
254: {
255: event.setCursor(ETHorzDragCursor.getCursor());
256: }
257:
258: return true;
259: }
260:
261: /**
262: * Tells the draw engine to write its data to the IProductArchive
263: *
264: * @param productArchive [in] The archive we're saving to
265: * @param parentElement [in] The current element, or parent for any new attributes or elements.
266: */
267: public long writeToArchive(IProductArchive productArchive,
268: IProductArchiveElement parentElement) {
269: if (null == productArchive)
270: throw new IllegalArgumentException();
271: if (null == parentElement)
272: throw new IllegalArgumentException();
273:
274: super .writeToArchive(productArchive, parentElement);
275:
276: IProductArchiveElement engineElement = parentElement
277: .getElement(IProductArchiveDefinitions.ENGINENAMEELEMENT_STRING);
278: if (engineElement != null) {
279: engineElement
280: .addAttributeBool(
281: IProductArchiveDefinitions.MESSAGEEDGEENGINE_ISSELFTOMESSAGE_BOOL,
282: m_IsMessageToSelf);
283:
284: if (!m_Show) {
285: engineElement.addAttributeBool(MDE_SHOW, m_Show);
286: }
287:
288: engineElement.addAttributeLong(MDE_SHOWMESSAGETYPE,
289: m_ShowMessageType);
290: }
291:
292: return 0;
293: }
294:
295: /**
296: * Tells the draw engine to read its data to the IProductArchive
297: *
298: * @param productArchive [in] The archive we're reading from
299: * @param pEngineElement [in] The element where this draw engine's information should exist.
300: */
301: public long readFromArchive(IProductArchive productArchive,
302: IProductArchiveElement parentElement) {
303: if (null == productArchive)
304: throw new IllegalArgumentException();
305: if (null == parentElement)
306: throw new IllegalArgumentException();
307:
308: super .readFromArchive(productArchive, parentElement);
309:
310: // Fix W6942: No need to use the member function here
311: m_IsMessageToSelf = parentElement
312: .getAttributeBool(IProductArchiveDefinitions.MESSAGEEDGEENGINE_ISSELFTOMESSAGE_BOOL);
313:
314: m_Show = parentElement.getAttributeBool(MDE_SHOW, m_Show);
315:
316: m_ShowMessageType = (int) parentElement
317: .getAttributeLong(MDE_SHOWMESSAGETYPE);
318:
319: return 0;
320: }
321:
322: /**
323: * Performs the rendering of the message.
324: */
325: public void doDraw(IDrawInfo drawInfo) {
326: if (m_Show) {
327: super .doDraw(drawInfo);
328: }
329: }
330:
331: /**
332: * The rectangle used for last drawing operation, in logical coordinates
333: */
334: public IETRect getLogicalBoundingRect(boolean bIncludeLabels) {
335: // parameters checked by super.getLogicalBoundingRect()
336: IETRect rectBounding = super
337: .getLogicalBoundingRect(bIncludeLabels);
338:
339: if (rectBounding.getIntHeight() == 0) {
340: // atempt to take the arrow head into account
341: rectBounding.setTop(rectBounding.getTop() + 5);
342: rectBounding.setBottom(rectBounding.getBottom() - 5);
343: }
344:
345: return rectBounding;
346: }
347:
348: /* (non-Javadoc)
349: * @see org.netbeans.modules.uml.ui.support.viewfactorysupport.IDrawEngine#initResources()
350: */
351: public void initResources() {
352: this .setLineColor("messagecolor", Color.BLACK);
353: super .initResources();
354: }
355:
356: /**
357: * Notifies the node an event has been generated at the graph.
358: */
359: public void onGraphEvent(int nKind) {
360: super .onGraphEvent(nKind);
361:
362: switch (nKind) {
363: case IGraphEventKind.GEK_PRE_DELETEGATHERSELECTED:
364: onPreDeleteGatherSelected();
365: break;
366:
367: case IGraphEventKind.GEK_PRE_DELETE:
368: if (isMessageToSelf() == true) {
369: IDrawingAreaControl ctrl = getDrawingArea();
370: if (ctrl != null) {
371: TSEEdge edge = getEdge();
372: if (edge != null) {
373: // Validate the node associated with this edge to remove the activation bars
374: TSNode sourceNode = edge.getSourceNode();
375:
376: IDrawEngine engine = TypeConversions
377: .getDrawEngine(sourceNode);
378: if (engine != null) {
379: engine.validateNode();
380: }
381: }
382: }
383: }
384: break;
385:
386: default:
387: break;
388: }
389: }
390:
391: /**
392: * Notifier that the model element has changed, if available the changed
393: * IFeature is passed along.
394: */
395: public long modelElementHasChanged(INotificationTargets targets) {
396: if (targets != null) {
397: int kind = targets.getKind();
398:
399: if (ModelElementChangedKind.MECK_ELEMENTMODIFIED == kind) {
400: ILabelManager labelManager = getLabelManager();
401: if (labelManager != null) {
402: labelManager.resetLabelsText();
403: }
404: }
405: }
406: return 0;
407: }
408:
409: /**
410: * Tell the element that the model element has been deleted
411: *
412: * @param pTargets Details about what got deleted
413: * @see org.netbeans.modules.uml.ui.support.viewfactorysupport.IDrawEngine#modelElementDeleted(org.netbeans.modules.uml.ui.support.viewfactorysupport.INotificationTargets)
414: */
415: public long modelElementDeleted(INotificationTargets pTargets) {
416: IElement modelElement = pTargets.getChangedModelElement();
417: IElement pSecondaryChangedME = pTargets
418: .getSecondaryChangedModelElement();
419: IFeature pFeature = null;
420:
421: if (pSecondaryChangedME instanceof IFeature) {
422: pFeature = (IFeature) pSecondaryChangedME;
423: }
424:
425: boolean isFromFeature = false;
426:
427: // This avoids the problem of handling too many events
428: IMessage message = null;
429: if (modelElement instanceof IMessage) {
430: message = (IMessage) modelElement;
431: }
432:
433: IOperation operation = null;
434: if (modelElement instanceof IOperation) {
435: operation = (IOperation) modelElement;
436: }
437:
438: // Make sure the message being deleted is this draw engine's message
439: if (message != null) {
440: // Fix W3322: This special case is where the model element is not
441: // present for the draw engine In this case, we are assuming that
442: // the input message is OK.
443: IElement element = TypeConversions.getElement(this );
444: if (element != null) {
445: String this XMIID = element.getXMIID();
446: String messageXMIID = message.getXMIID();
447:
448: if (this XMIID.equals(messageXMIID) == false) {
449: message = null;
450: }
451: }
452: }
453:
454: if ((message == null) && (operation == null)) {
455: if (pFeature instanceof IOperation) {
456: operation = (IOperation) pFeature;
457: isFromFeature = true;
458:
459: // Fix W299: We need to detect how we got this message
460: // If the message is from a change on the SQD,
461: // then the model element won't be the message's receiving classifier.
462: // In this case we don't want anything deleted.
463: if (modelElement instanceof IClassifier) {
464: IClassifier inputClassifier = (IClassifier) modelElement;
465:
466: IElement firstElement = getFirstModelElement();
467: if (firstElement instanceof IMessage) {
468: IMessage firstMessage = (IMessage) firstElement;
469:
470: IClassifier receivingClassifier = firstMessage
471: .getReceivingClassifier();
472:
473: if (inputClassifier.isSame(receivingClassifier) == false) {
474: // Don't delete any presentation information
475: message = null;
476: operation = null;
477: isFromFeature = false;
478: }
479: }
480: }
481: }
482: }
483:
484: if ((message != null) || (operation != null)) {
485: // Fix W2745: Delete any return message associated with this message
486: final int kind = getMessageKind();
487: if (IMessageKind.MK_SYNCHRONOUS == kind) {
488: IETGraphObject graphObject = (IETGraphObject) getParentETElement();
489:
490: TSEEdge pEdgeReturn = ConnectorPiece
491: .getReturnEdge(graphObject);
492: if (pEdgeReturn != null) {
493: // Make sure the presentation element is allowed to delete its model element
494: IEdgePresentation returnGraphObject = TypeConversions
495: .getEdgePresentation(pEdgeReturn);
496: if (returnGraphObject != null) {
497: returnGraphObject.invalidate();
498:
499: pEdgeReturn.getOwnerGraph().remove(pEdgeReturn);
500: }
501: }
502: }
503:
504: // Fix W1858: Delete the pieces attached to the message.
505: ConnectorPiece.deleteEdge(getEdge());
506:
507: // Fix W3055: Delete the TS edge, if it still exists
508: // This special case is when an operation is dragged out of the class,
509: // which is the representing classifier of the lifeline
510: // See also CAxDrawingAreaControl::ElementDeleted()
511: if (isFromFeature == true) {
512: TSEEdge edge = getEdge();
513: if (edge != null) {
514: edge.getOwnerGraph().remove(edge);
515: }
516: }
517: }
518: return 0;
519: }
520:
521: /* (non-Javadoc)
522: * @see org.netbeans.modules.uml.ui.support.viewfactorysupport.IEdgeDrawEngine#getAllowReconnection()
523: */
524: public boolean getAllowReconnection() {
525: boolean bAllowReconnection = !m_IsMessageToSelf;
526:
527: if (bAllowReconnection) {
528: IElement element = getFirstModelElement();
529: if (element instanceof IMessage) {
530: IMessage message = (IMessage) element;
531:
532: int kind = message.getKind();
533:
534: bAllowReconnection = ((IMessageKind.MK_SYNCHRONOUS == kind) || (IMessageKind.MK_ASYNCHRONOUS == kind));
535: }
536: }
537:
538: return bAllowReconnection;
539: }
540:
541: //**************************************************
542: // IMessageEdgeDrawEngine Implmenetations
543: //**************************************************
544:
545: /**
546: * Indicates that the message starts and ends on the same node
547: *
548: * @param bIsMessageToSelf <code>true</code> if the message start and finish
549: * nodes are the same.
550: * @see org.netbeans.modules.uml.ui.products.ad.diagramengines.sequencediagram.IMessageEdgeDrawEngine#setIsMessageToSelf(boolean)
551: */
552: public void setIsMessageToSelf(boolean bIsMessageToSelf) {
553: m_IsMessageToSelf = bIsMessageToSelf;
554: if (m_IsMessageToSelf == true) {
555: TSEEdge edge = getEdge();
556: if (edge != null) {
557: // Remember the suspension bar of the message-to-self
558: // To be used when the user drags either of the attached messages
559: initializePieceSelf(edge);
560:
561: // Determine the connector that is connected to the activation bar
562: TSConnector activationBarConnector = getActivationBarConnector(edge);
563:
564: if (activationBarConnector != null) {
565: LifelineCompartmentPiece piece = ConnectorPiece
566: .getPieceAttachedToConnector(activationBarConnector);
567: if (piece instanceof ActivationBar) {
568: ActivationBar bar = (ActivationBar) piece;
569: bar.setMessageToSelf(true);
570: }
571: }
572: }
573: } else {
574: m_PieceSelf = null;
575: }
576: }
577:
578: /**
579: * Indicates that the message starts and ends on the same node
580: *
581: * @return <code>true</code> if the message start and finish nodes are the
582: * same.
583: * @see org.netbeans.modules.uml.ui.products.ad.diagramengines.sequencediagram.IMessageEdgeDrawEngine#isMessageToSelf()
584: */
585: public boolean isMessageToSelf() {
586: boolean retVal = m_IsMessageToSelf;
587:
588: if ((retVal == true) && (m_PieceSelf != null)) {
589: initializePieceSelf(getEdge());
590: }
591:
592: return retVal;
593: }
594:
595: /* (non-Javadoc)
596: * @see org.netbeans.modules.uml.ui.products.ad.diagramengines.sequencediagram.IMessageEdgeDrawEngine#move(int, boolean)
597: */
598: public void move(double nY, boolean bDoItNow) {
599: TSEEdge ownerEdge = getEdge();
600: if (ownerEdge != null) {
601: TSConnector connector = null;
602:
603: if (!m_IsMessageToSelf) {
604: connector = ownerEdge.getTargetConnector();
605: moveConnector(connector, nY, bDoItNow);
606: connector = null;
607: }
608:
609: connector = ownerEdge.getSourceConnector();
610: moveConnector(connector, nY, bDoItNow);
611: }
612:
613: }
614:
615: /* (non-Javadoc)
616: * Set the show property.
617: *
618: * @see org.netbeans.modules.uml.ui.products.ad.diagramengines.sequencediagram.IMessageEdgeDrawEngine#setShow(boolean)
619: */
620: public void setShow(boolean bShow) {
621: m_Show = bShow;
622: }
623:
624: /* (non-Javadoc)
625: * Retrieves the show property.
626: *
627: * @see org.netbeans.modules.uml.ui.products.ad.diagramengines.sequencediagram.IMessageEdgeDrawEngine#getShow()
628: */
629: public boolean getShow() {
630: return m_Show;
631: }
632:
633: /* (non-Javadoc)
634: * Set the show messge type property.
635: * @see org.netbeans.modules.uml.ui.products.ad.diagramengines.sequencediagram.IMessageEdgeDrawEngine#setShowMessageType(int)
636: */
637: public void setShowMessageType(int type) {
638: m_ShowMessageType = type;
639: }
640:
641: /* (non-Javadoc)
642: * Retrieves the show message type property.
643: *
644: * @see org.netbeans.modules.uml.ui.products.ad.diagramengines.sequencediagram.IMessageEdgeDrawEngine#getShowMessageType()
645: */
646: public int getShowMessageType() {
647: return m_ShowMessageType;
648: }
649:
650: /* (non-Javadoc)
651: * @see org.netbeans.modules.uml.ui.products.ad.diagramengines.sequencediagram.IMessageEdgeDrawEngine#associatedResultMessage()
652: */
653: public IEdgePresentation getAssociatedResultMessage() {
654: IEdgePresentation edgePresentation = null;
655:
656: final int kind = getMessageKind();
657: switch (kind) {
658: case IMessageKind.MK_CREATE:
659: case IMessageKind.MK_SYNCHRONOUS: {
660: IETGraphObject etGraphObject = TypeConversions
661: .getETGraphObject(this );
662: TSEEdge edgeReturn = ConnectorPiece
663: .getReturnEdge(etGraphObject);
664: if (edgeReturn != null) {
665: edgePresentation = TypeConversions
666: .getEdgePresentation(edgeReturn);
667: }
668: }
669: break;
670:
671: case IMessageKind.MK_RESULT: {
672: edgePresentation = TypeConversions
673: .getEdgePresentation(this );
674: }
675: break;
676:
677: default:
678: break;
679: }
680:
681: return edgePresentation;
682: }
683:
684: /**
685: * Determines the end type of arrow head to draw from the
686: * IPresentationElement's initialization string.
687: *
688: * @return The kind of arrowhead for this message. The value will be one
689: * of the DrawEngineArrowheadKindEnum values.
690: * @see DrawEngineArrowheadKindEnum
691: */
692: protected int getEndArrowKind() {
693: initLineStyle();
694: return m_ArrowHeadKind;
695: }
696:
697: /**
698: * Determines the type of line to draw from the IPresentationElement's
699: * initialization string
700: *
701: * @return The kind of line for this message. The value will be one
702: * of the DrawEngineArrowheadKindEnum values.
703: * @see DrawEngineArrowheadKindEnum
704: */
705: protected int getLineKind() {
706: initLineStyle();
707: return m_LineKind;
708: }
709:
710: /**
711: * Determines the type of line, and arrow head to draw from the
712: * IPresentationElement's initialization string
713: */
714: protected void initLineStyle() {
715: if ((m_LineKind == DrawEngineLineKindEnum.DELK_UNKNOWN)
716: || (m_ArrowHeadKind == DrawEngineArrowheadKindEnum.DEAK_NO_ARROWHEAD)) {
717: int kind = getMessageKind();
718: switch (kind) {
719: case IMessageKind.MK_CREATE:
720: m_LineKind = DrawEngineLineKindEnum.DELK_DOT;
721: m_ArrowHeadKind = DrawEngineArrowheadKindEnum.DEAK_UNFILLEDARROW;
722: if (m_ShowMessageType < 0)
723: m_ShowMessageType = IShowMessageType.SMT_UNKNOWN;
724: break;
725: default:
726: case IMessageKind.MK_SYNCHRONOUS:
727: m_LineKind = DrawEngineLineKindEnum.DELK_SOLID;
728: m_ArrowHeadKind = DrawEngineArrowheadKindEnum.DEAK_FILLED;
729: if (m_ShowMessageType < 0)
730: m_ShowMessageType = NbPreferences.forModule(
731: MessageEdgeDrawEngine.class).getInt(
732: "UML_SQD_DEFAULT_MSG",
733: IShowMessageType.SMT_NONE);
734: break;
735: case IMessageKind.MK_ASYNCHRONOUS:
736: m_LineKind = DrawEngineLineKindEnum.DELK_SOLID;
737: m_ArrowHeadKind = DrawEngineArrowheadKindEnum.DEAK_UNFILLEDARROW;
738: if (m_ShowMessageType < 0)
739: m_ShowMessageType = NbPreferences.forModule(
740: MessageEdgeDrawEngine.class).getInt(
741: "UML_SQD_DEFAULT_MSG",
742: IShowMessageType.SMT_NONE);
743: break;
744: case IMessageKind.MK_RESULT:
745: m_LineKind = DrawEngineLineKindEnum.DELK_DOT;
746: m_ArrowHeadKind = DrawEngineArrowheadKindEnum.DEAK_FILLED;
747: if (m_ShowMessageType < 0)
748: m_ShowMessageType = IShowMessageType.SMT_UNKNOWN;
749: break;
750:
751: }
752: }
753:
754: }
755:
756: /**
757: * Determines the message kind from either the atached message, or the
758: * initialization string
759: *
760: * @return The message type. The value will be one of the IMessageKind values.
761: * @see IMessageKind
762: */
763: protected int getMessageKind() {
764: int retVal = IMessageKind.MK_SYNCHRONOUS;
765:
766: IETGraphObjectUI parent = getParent();
767: if (parent != null) {
768: IElement element = parent.getModelElement();
769: if (element instanceof IMessage) {
770: IMessage message = (IMessage) element;
771: retVal = message.getKind();
772: } else {
773: String initStr = getInitializationString();
774: int pos = initStr.indexOf(' ');
775: initStr = initStr.substring(pos + 1);
776:
777: if (initStr.equals("Message create") == true) {
778: retVal = IMessageKind.MK_CREATE;
779: } else if (initStr.equals("Message asynchronous") == true) {
780: retVal = IMessageKind.MK_ASYNCHRONOUS;
781: } else if (initStr.equals("Message result") == true) {
782: retVal = IMessageKind.MK_RESULT;
783: } else {
784: retVal = IMessageKind.MK_SYNCHRONOUS;
785: }
786: }
787:
788: }
789:
790: return retVal;
791: }
792:
793: /**
794: * Move the connector within its associated compartment
795: *
796: * @param connector[in]
797: */
798: protected void moveConnector(TSConnector connector, double nY,
799: boolean doItNow) {
800: IConnectorsCompartment compartment = (IConnectorsCompartment) TypeConversions
801: .getCompartment(connector, IConnectorsCompartment.class);
802:
803: if (compartment != null) {
804: compartment.moveConnector(connector, nY, doItNow, false);
805: }
806: }
807:
808: /**
809: * Returns the metatype of the label manager we should use
810: *
811: * @param The metatype in essentialconfig.etc that defines the label
812: * manager
813: * @return The name of the manager.
814: * @see org.netbeans.modules.uml.ui.support.viewfactorysupport.IDrawEngine#getManagerMetaType(int)
815: */
816: public String getManagerMetaType(int nManagerKind) {
817: String retVal = "";
818:
819: if (nManagerKind == ETDrawEngine.MK_LABELMANAGER) {
820: retVal = "MessageLabelManager";
821: }
822:
823: return retVal;
824: }
825:
826: /**
827: * Inializes the member m_PieceSelf
828: */
829: protected void initializePieceSelf(TSEEdge edge) {
830: if (null == edge)
831: throw new IllegalArgumentException();
832:
833: TSConnector pieceConnector = null;
834:
835: final int kind = getMessageKind();
836: switch (kind) {
837: default:
838: assert (false); // can we support this message kind w/ message-to-self?
839: // fall through
840:
841: case IMessageKind.MK_SYNCHRONOUS:
842: pieceConnector = edge.getSourceConnector();
843: break;
844:
845: case IMessageKind.MK_RESULT:
846: pieceConnector = edge.getTargetConnector();
847: break;
848: }
849:
850: // Remember the suspension bar of the message-to-self
851: // To be used when the user drags either of the attached messages
852: if (pieceConnector != null) {
853: m_PieceSelf = new LifelinePiece(pieceConnector);
854: }
855: }
856:
857: /**
858: * Handles the PreDeleteGatherSelected event by selecting the other end of a message to self
859: */
860: public void onPreDeleteGatherSelected() {
861: // Fix W7536: We need to select the "other" edge for sync, and result messages.
862: // see MessageLabelManagerImpl::OnPreDeleteGatherSelected()
863: // for a related fix. Before this fix we only did this for the message-to-self.
864:
865: IDrawingAreaControl ctrl = getDrawingArea();
866: if (ctrl != null) {
867: IMessage otherMessage = null;
868:
869: IElement element = getFirstModelElement();
870: if (element instanceof IMessage) {
871: IMessage message = (IMessage) element;
872:
873: if (message != null) {
874: int kind = message.getKind();
875: switch (kind) {
876: case IMessageKind.MK_SYNCHRONOUS:
877: otherMessage = getResultFromSender(message);
878: break;
879:
880: case IMessageKind.MK_RESULT:
881: otherMessage = message.getSendingMessage();
882: break;
883:
884: default:
885: // do nothing
886: break;
887: }
888:
889: if (otherMessage != null) {
890: ETList<IPresentationElement> elements = ctrl
891: .getAllItems2(otherMessage);
892: if (elements != null) {
893: for (Iterator<IPresentationElement> iter = elements
894: .iterator(); iter.hasNext();) {
895: IPresentationElement presentation = iter
896: .next();
897: // Debug.assertNull(presentation);//Jyothi
898:
899: if (presentation instanceof IGraphPresentation) {
900: IGraphPresentation gPresentation = (IGraphPresentation) presentation;
901: gPresentation.setSelected(true);
902: }
903: }
904: }
905: }
906: }
907: }
908: }
909: }
910:
911: /**
912: * Retrieves the result message associated with the input sending message
913: */
914: protected IMessage getResultFromSender(IMessage message) {
915: IMessage retVal = null;
916:
917: if (message != null) {
918: String xmiId = message.getXMIID();
919: if (xmiId.length() > 0) {
920: // Search the entire DOM for the class's lifeline(s)
921: IElementLocator elementLocator = new ElementLocator();
922:
923: if (elementLocator != null) {
924: String query = "../UML:Message[@sendingMessage='"
925: + xmiId + "']";
926:
927: // Use the element locator to find the model element
928: IElement element = elementLocator
929: .findSingleElementByQuery(message, query);
930: if (element != null) {
931: if (element instanceof IMessage) {
932: retVal = (IMessage) element;
933: }
934: }
935: }
936: }
937: }
938:
939: return retVal;
940: }
941:
942: // Code needed for the Java port
943:
944: /**
945: * Retrieve the connector that connects the edge to an activation bar.
946: *
947: * @param edge The edge that should connect to an activation bar.
948: * @return The Tom Sawyer connector.
949: */
950: protected TSConnector getActivationBarConnector(TSEEdge edge) {
951: TSConnector retVal = null;
952: switch (getMessageKind()) {
953: default:
954: case IMessageKind.MK_SYNCHRONOUS:
955: retVal = edge.getTargetConnector();
956: break;
957:
958: case IMessageKind.MK_RESULT:
959: retVal = edge.getSourceConnector();
960: }
961:
962: return retVal;
963: }
964:
965: /* (non-Javadoc)
966: * @see org.netbeans.modules.uml.ui.products.ad.ADDrawEngines.IADEdgeDrawEngine#createButtonHandler()
967: */
968: public IADDrawEngineButtonHandler createButtonHandler() {
969: // Not sure if this is needed
970: return null;
971: }
972:
973: //**************************************************
974: // Helper Methods
975: //**************************************************
976:
977: /**
978: * Determines the type of arrow head to draw from the IPresentationElement's
979: * initialization string.
980: *
981: * @return The kind of arrowhead for this message. The value will be one
982: * of the DrawEngineArrowheadKindEnum values.
983: * @see DrawEngineArrowheadKindEnum
984: */
985: protected int getStartArrowKind() {
986: return DrawEngineArrowheadKindEnum.DEAK_NO_ARROWHEAD;
987: }
988:
989: /* (non-Javadoc)
990: * @see org.netbeans.modules.uml.ui.support.viewfactorysupport.IDrawEngine#handleLeftMouseButtonPressed(java.awt.event.MouseEvent)
991: */
992:
993: public boolean handleLeftMouseBeginDrag(IETPoint pStartPos,
994: IETPoint pCurrentPos) {
995: return false;
996: }
997: }
|