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.drawengines;
043:
044: import java.awt.event.ActionEvent;
045: import java.awt.event.MouseEvent;
046: import java.util.ArrayList;
047: import java.util.List;
048:
049: import java.awt.Color;
050: import java.awt.Dimension;
051: import java.awt.Point;
052: import java.awt.Shape;
053: import java.awt.Stroke;
054:
055: import java.awt.Rectangle;
056:
057: import javax.accessibility.Accessible;
058: import javax.accessibility.AccessibleContext;
059: import javax.accessibility.AccessibleRole;
060:
061: //import com.tomsawyer.util.TSRect;
062: import com.tomsawyer.drawing.geometry.TSRect; //import com.tomsawyer.util.TSTransform;
063: import com.tomsawyer.editor.TSTransform; //import com.tomsawyer.util.TSConstPoint;
064: import com.tomsawyer.drawing.geometry.TSConstPoint; //import com.tomsawyer.util.TSConstRect;
065: import com.tomsawyer.drawing.geometry.TSConstRect;
066: import com.tomsawyer.drawing.TSPEdge;
067: import com.tomsawyer.drawing.TSPNode;
068: import com.tomsawyer.editor.TSEObject;
069: import com.tomsawyer.editor.TSENode;
070: import com.tomsawyer.editor.TSEEdge;
071: import com.tomsawyer.editor.TSEObjectUI;
072: import com.tomsawyer.editor.ui.TSEEdgeUI;
073: import com.tomsawyer.editor.TSEColor; //import com.tomsawyer.editor.TSEWindowInputState;
074: import com.tomsawyer.editor.TSEWindowInputTool;
075:
076: import com.tomsawyer.editor.command.TSEReconnectEdgeCommand;
077: import com.tomsawyer.editor.graphics.TSEGraphics;
078: import com.tomsawyer.editor.ui.TSERectangularUI;
079: import com.tomsawyer.editor.TSEConnector; //import com.tomsawyer.editor.state.TSEReconnectEdgeState;
080: import com.tomsawyer.editor.tool.TSEReconnectEdgeTool;
081: import com.tomsawyer.graph.TSGraphObject;
082:
083: import org.netbeans.modules.uml.core.metamodel.core.foundation.IElement;
084: import org.netbeans.modules.uml.core.metamodel.core.foundation.INamedElement;
085: import org.netbeans.modules.uml.core.support.umlsupport.ETRect;
086: import org.netbeans.modules.uml.core.support.umlsupport.IETPoint;
087: import org.netbeans.modules.uml.core.support.umlsupport.IETRect;
088: import org.netbeans.modules.uml.common.generics.ETPairT;
089: import org.netbeans.modules.uml.common.generics.IteratorT;
090:
091: import org.netbeans.modules.uml.ui.support.accessibility.UMLAccessibleRole;
092: import org.netbeans.modules.uml.ui.support.umltsconversions.RectConversions;
093: import org.netbeans.modules.uml.ui.support.viewfactorysupport.ETRectEx;
094: import org.netbeans.modules.uml.ui.support.viewfactorysupport.IDrawEngine;
095: import org.netbeans.modules.uml.ui.support.viewfactorysupport.IDrawInfo;
096: import org.netbeans.modules.uml.ui.support.viewfactorysupport.IETEdge;
097: import org.netbeans.modules.uml.ui.support.viewfactorysupport.IETGraphObject;
098: import org.netbeans.modules.uml.ui.support.viewfactorysupport.IETNode;
099: import org.netbeans.modules.uml.ui.support.viewfactorysupport.IEdgeDrawEngine;
100: import org.netbeans.modules.uml.ui.support.viewfactorysupport.DrawEngineArrowheadKindEnum;
101: import org.netbeans.modules.uml.ui.support.viewfactorysupport.DrawEngineLineKindEnum;
102: import org.netbeans.modules.uml.ui.support.viewfactorysupport.IETArrowHead;
103: import org.netbeans.modules.uml.ui.support.viewfactorysupport.ILabelManager;
104: import org.netbeans.modules.uml.ui.support.viewfactorysupport.ISupportEnums;
105: import org.netbeans.modules.uml.ui.support.viewfactorysupport.MetaModelHelper;
106: import org.netbeans.modules.uml.ui.support.viewfactorysupport.TSLabelKind;
107: import org.netbeans.modules.uml.ui.support.viewfactorysupport.TypeConversions;
108: import org.netbeans.modules.uml.ui.controls.drawingarea.GetHelper;
109: import org.netbeans.modules.uml.ui.controls.drawingarea.ISwapEdgeEndsAction;
110: import org.netbeans.modules.uml.ui.controls.drawingarea.SwapEdgeEndsAction;
111: import org.netbeans.modules.uml.ui.products.ad.ADDrawEngines.IADDrawEngineButtonHandler;
112: import org.netbeans.modules.uml.ui.products.ad.application.IMenuManager;
113: import org.netbeans.modules.uml.ui.products.ad.application.action.ContextMenuActionClass;
114: import org.netbeans.modules.uml.ui.products.ad.graphobjects.ETEdge;
115: import org.netbeans.modules.uml.ui.products.ad.viewfactory.ETArrowHeadFactory;
116: import org.netbeans.modules.uml.ui.products.ad.viewfactory.ETGenericEdgeUI;
117: import org.netbeans.modules.uml.ui.products.ad.viewfactory.IETGraphObjectUI;
118: import org.netbeans.modules.uml.core.support.umlsupport.ETPoint;
119: import org.netbeans.modules.uml.core.support.umlutils.ETArrayList;
120: import org.netbeans.modules.uml.core.support.umlutils.ETList;
121:
122: import org.netbeans.modules.uml.ui.support.applicationmanager.IEdgePresentation;
123: import org.netbeans.modules.uml.ui.support.applicationmanager.ILabelPresentation;
124: import org.netbeans.modules.uml.ui.support.contextmenusupport.IProductContextMenu;
125: import org.netbeans.modules.uml.ui.support.contextmenusupport.IProductContextMenuItem;
126: import org.netbeans.modules.uml.ui.swing.drawingarea.IDrawingAreaControl;
127:
128: import org.netbeans.modules.uml.core.metamodel.core.foundation.IPresentationElement;
129: import org.netbeans.modules.uml.ui.support.viewfactorysupport.ETPointEx;
130:
131: /*
132: *
133: * @author KevinM
134: *
135: */
136: public abstract class ETEdgeDrawEngine extends ETDrawEngine implements
137: IEdgeDrawEngine {
138: protected static ETStrokeCache m_stokeCache = new ETStrokeCache();
139: private int m_nBorderStringID = -1;
140:
141: public void doDraw(IDrawInfo pDrawInfo) {
142: if (this .simpleDrawEdge(pDrawInfo, getLineKind()) == false) {
143: drawEdge(pDrawInfo, this .getStartArrowKind(), this
144: .getEndArrowKind(), getLineKind());
145: }
146: }
147:
148: protected IElement getNodeElement(TSENode tsNode) {
149: IETGraphObjectUI nodeUI = tsNode != null ? (IETGraphObjectUI) tsNode
150: .getUI()
151: : null;
152: return nodeUI != null ? nodeUI.getModelElement() : null;
153: }
154:
155: /*
156: * Returns the source Element
157: */
158: protected IElement getSourceElement() {
159: return getNodeElement(getSourceNode());
160: }
161:
162: /*
163: * Returns the Target Element.
164: */
165: protected IElement getTargetElement() {
166: return getNodeElement(getTargetNode());
167: }
168:
169: /*
170: * Returns a rectangle that bounds the source clipping point of this edge in logical units.
171: */
172: protected IETRect getSourcePtBounds() {
173: TSConstPoint centerPt = getEdge().getSourceClippingPoint();
174: double reconnectSenitivity = getGraphWindow()
175: .getPreferences()
176: .getDoubleValue(
177: com.tomsawyer.editor.TSEPreferences.RECONNECT_EDGE_SENSITIVITY);
178: TSRect rect = new TSRect();
179: rect.setBoundsFromCenter(centerPt.getX(), centerPt.getY(),
180: reconnectSenitivity, reconnectSenitivity);
181: return RectConversions.newETRect(rect);
182: }
183:
184: /*
185: * Returns a rectangle that bounds the target clipping point of this edge in logical units.
186: */
187: protected IETRect getTargetPtBounds() {
188: TSConstPoint centerPt = getEdge().getTargetClippingPoint();
189: double reconnectSenitivity = getGraphWindow()
190: .getPreferences()
191: .getDoubleValue(
192: com.tomsawyer.editor.TSEPreferences.RECONNECT_EDGE_SENSITIVITY);
193: TSRect rect = new TSRect();
194: rect.setBoundsFromCenter(centerPt.getX(), centerPt.getY(),
195: reconnectSenitivity, reconnectSenitivity);
196: return RectConversions.newETRect(rect);
197: }
198:
199: /*
200: * Returns true if the user clicked near the one of ends, pos must be in logical units.
201: */
202: protected boolean hitEndPoint(IETPoint pPos) {
203: return getTargetPtBounds().contains(pPos)
204: || getSourcePtBounds().contains(pPos);
205: }
206:
207: /*
208: * Returns true if we are currently reconnecting this drawEngines parent UI's owner edge.
209: */
210: protected boolean isReconnecting() {
211: // return this.getUI().getDrawingArea().getGraphWindow().getCurrentState() instanceof TSEReconnectEdgeState;
212: return this .getUI().getDrawingArea().getGraphWindow()
213: .getCurrentTool() instanceof TSEReconnectEdgeTool;
214: }
215:
216: /*
217: * Returns true if we are currently reconnecting the Target Node of this parents UI owner edge.
218: */
219: protected boolean isReconnectingTarget() {
220: // TSEReconnectEdgeState state = isReconnecting() ? (TSEReconnectEdgeState)this.getUI().getDrawingArea().getGraphWindow().getCurrentState() : null;
221: TSEReconnectEdgeTool state = isReconnecting() ? (TSEReconnectEdgeTool) this
222: .getUI().getDrawingArea().getGraphWindow()
223: .getCurrentTool()
224: : null;
225: if (state != null) {
226: return !state.isReconnectingSource();
227: } else {
228: return false;
229: }
230: }
231:
232: /*
233: * Hit testing function, pt must be in logical units.
234: */
235: public IETGraphObjectUI getUIAt(IETPoint pt) {
236: // TSEWindowInputState state = (TSEWindowInputState)this.getUI().getDrawingArea().getGraphWindow().getCurrentState();
237: // TSEWindowInputTool state = (TSEWindowInputTool)this.getUI().getDrawingArea().getGraphWindow().getCurrentState();
238: TSEWindowInputTool tool = (TSEWindowInputTool) this .getUI()
239: .getDrawingArea().getGraphWindow().getCurrentTool();
240:
241: // TSEObject obj = state.getObjectAt(new TSConstPoint(pt.getX(), pt.getY()), null, this.getUI().getDrawingArea().getGraphWindow().getGraph());
242: TSEObject obj = tool.getHitTesting().getGraphObjectAt(
243: new TSConstPoint(pt.getX(), pt.getY()),
244: this .getUI().getDrawingArea().getGraphWindow()
245: .getGraph(), true);
246:
247: /*
248: * We don't want to return ourselves.
249: */
250: if (getEdge() == obj) {
251: // obj = state.getObjectAt(new TSConstPoint(pt.getX(), pt.getY()), getEdge(), this.getUI().getDrawingArea().getGraphWindow().getGraph());
252: obj = tool.getHitTesting().getGraphObjectAt(
253: new TSConstPoint(pt.getX(), pt.getY()),
254: this .getUI().getDrawingArea().getGraphWindow()
255: .getGraph(), true);
256: }
257: return obj != null && obj.getUI() instanceof IETGraphObjectUI ? (IETGraphObjectUI) obj
258: .getUI()
259: : null;
260: }
261:
262: public boolean handleLeftMouseButton(MouseEvent pEvent) {
263: this .postInvalidate();
264: return false;
265: }
266:
267: public boolean handleLeftMouseBeginDrag(IETPoint pStartPos,
268: IETPoint pCurrentPos) {
269: return false;
270: }
271:
272: public boolean handleLeftMouseButtonDoubleClick(MouseEvent pEvent) {
273: this .postInvalidate();
274: return false;
275: }
276:
277: public boolean handleLeftMouseDrag(IETPoint pStartPos,
278: IETPoint pCurrentPos) {
279: this .postInvalidate();
280: return !getAllowReconnection();
281: }
282:
283: public boolean handleLeftMouseDrop(IETPoint pCurrentPos,
284: List pElements, boolean bMoving) {
285: return false;
286: }
287:
288: public boolean handleRightMouseButton(MouseEvent pEvent) {
289: return false;
290: }
291:
292: public boolean getAllowReconnection() {
293: return !getReadOnly();
294: }
295:
296: public TSEColor getColor() {
297: return new TSEColor(getColor(m_nBorderStringID));
298: }
299:
300: public TSEColor getSelectedColor() {
301: return getEdgeUI().getHighlightedColor();
302: }
303:
304: /*
305: * Returns the color depending on the state, selected or not.
306: */
307: public TSEColor getStateColor() {
308: return getEdge().isSelected() ? getSelectedColor() : getColor();
309: }
310:
311: protected IETNode getNodeFromID(int nodeID) {
312: if (this .getEdge() != null) {
313: if (getSourceNode().getClass().hashCode() == nodeID)
314: return (IETNode) getSourceNode();
315: else if (getTargetNode().getClass().hashCode() == nodeID)
316: return (IETNode) getTargetNode();
317: }
318: return null;
319: }
320:
321: /*
322: * ParamOne is the list of TSPNodes, and ParamTwo is the TSPEdges
323: */
324: protected ETPairT<List, List> getPathNodeAndEdges() {
325: ETList<TSPEdge> pathEdges = new ETArrayList<TSPEdge>();
326: ETList<TSPNode> pathNodes = new ETArrayList<TSPNode>();
327:
328: java.util.List pEdges = getEdge().pathEdges();
329: java.util.List pNodes = getEdge().pathNodes();
330: java.util.List newBendPoints = new ETArrayList<TSConstPoint>();
331: IteratorT<TSPEdge> pathEdgeIter = new IteratorT<TSPEdge>(pEdges);
332: while (pathEdgeIter.hasNext()) {
333: pathEdges.add(pathEdgeIter.next());
334: }
335:
336: IteratorT<TSPNode> pathNodeIter = new IteratorT<TSPNode>(pNodes);
337: while (pathNodeIter.hasNext()) {
338: pathNodes.add(pathNodeIter.next());
339: }
340:
341: return new ETPairT<List, List>(pathNodes, pathEdges);
342: }
343:
344: /*
345: * Used by swapEdgeEnds, we need to reverse the pathDigraph, so the order is correct.
346: * ParamOne is the Original PathNode locations,
347: * ParamTwo is the Reversed PathNode locations, used to reroute the path.
348: */
349: protected ETPairT<List, List> getReconnectEdgeBendPoints() {
350: java.util.List bendPoints = getEdge().bendPoints();
351: java.util.List newBendPoints = new ETArrayList<TSConstPoint>();
352: IteratorT<TSConstPoint> iter = new IteratorT<TSConstPoint>(
353: bendPoints);
354:
355: while (iter.hasNext()) {
356: newBendPoints.add((TSConstPoint) iter.next().clone());
357: }
358: GetHelper.reverseList(this .getGraphWindow(), newBendPoints);
359: return new ETPairT<List, List>(bendPoints, newBendPoints);
360: }
361:
362: public boolean setEdgeEnds(IETNode newSourceNode,
363: IETNode newTargetNode) {
364: IETNode oldSourceNode = (IETNode) this .getSourceNode(); //getNodeFromID(nNewSourceEndID);
365: IETNode oldTargetNode = (IETNode) this .getTargetNode(); //getNodeFromID(nNewTargetEndID);
366:
367: TSEEdge edge = this .getEdge();
368: if (edge != null) {
369: ETPairT<List, List> newPath = getReconnectEdgeBendPoints();
370: // Swap the nodes.
371: edge.setTargetNode((TSENode) newTargetNode);
372: edge.setSourceNode((TSENode) newSourceNode);
373:
374: // Reroute the pathdigraph, we have reversed the edge.
375: if (newSourceNode == oldTargetNode
376: && newTargetNode == oldSourceNode) {
377: getEdge().reroute(newPath.getParamTwo());
378: TSEEdgeUI edgeUI = (TSEEdgeUI) getEdge().getUI();
379:
380: // Turn off the arrowheads or is shows up when you reconnect it.
381: if (edgeUI != null)
382: edgeUI.setArrowType(TSEEdgeUI.NO_ARROW);
383: }
384: return true;
385: }
386: return false;
387: }
388:
389: /*
390: * (non-Javadoc)
391: * @see org.netbeans.modules.uml.ui.support.viewfactorysupport.IEdgeDrawEngine#swapEdgeEnds(int, int)
392: */
393: public long swapEdgeEnds(int nNewSourceEndID, int nNewTargetEndID) {
394: IETNode newSourceNode = (IETNode) this .getTargetNode(); //getNodeFromID(nNewSourceEndID);
395: IETNode newTargetNode = (IETNode) this .getSourceNode(); //getNodeFromID(nNewTargetEndID);
396:
397: return setEdgeEnds(newSourceNode, newTargetNode) ? 1 : 0;
398: }
399:
400: /**
401: * Posts and invalidate to the drawing area
402: */
403: protected void postSwapEdgeEnds() {
404: try {
405: TSEEdge pEdge = this .getEdge();
406:
407: if (pEdge != null) {
408: IETNode pSourceNode = (IETNode) this .getSourceNode();
409: IETNode pTargetNode = (IETNode) this .getTargetNode();
410:
411: if (pTargetNode != null && pSourceNode != null) {
412: // TO DO add an interfaces for getID, that returns the hash code.
413: int nSourceID = pTargetNode.getClass().hashCode(); //pSourceNode.getID();
414: int nTargetID = pSourceNode.getClass().hashCode(); // getID();
415:
416: ISwapEdgeEndsAction pAction = new SwapEdgeEndsAction();
417: if (pAction != null) {
418: pAction.setEdgeToSwap((IETEdge) pEdge);
419: pAction.setNewTargetEndID(nSourceID);
420: pAction.setNewSourceEndID(nTargetID);
421:
422: IDrawingAreaControl pDA = this .getDrawingArea();
423:
424: if (pDA != null) {
425: pDA.postDelayedAction(pAction);
426: postInvalidate();
427: }
428: }
429: }
430: }
431: } catch (Exception e) {
432: e.printStackTrace();
433: }
434: }
435:
436: // public void selectAllCompartments(boolean bSelected) {
437: // // TODO Auto-generated method stub
438: //
439: // }
440: //
441: // public List getCompartments() {
442: // return null;
443: // }
444: //
445: // public List getSelectedCompartments() {
446: // return null;
447: // }
448:
449: public boolean simpleDrawEdge(IDrawInfo pInfo, int nLineKind) {
450: boolean bDidDraw = false;
451: try {
452: if (pInfo != null) {
453: // Get the zoom level and if it's below 25% go ahead and draw just a line
454: if (pInfo.getOnDrawZoom() < .30f) {
455: // Don't draw at this zoom level, just draw a line
456: bDidDraw = drawEdge(
457: pInfo,
458: DrawEngineArrowheadKindEnum.DEAK_NO_ARROWHEAD,
459: DrawEngineArrowheadKindEnum.DEAK_NO_ARROWHEAD,
460: nLineKind);
461: } else {
462: bDidDraw = false;
463: }
464: }
465: } catch (Exception e) {
466: e.printStackTrace();
467: bDidDraw = false;
468: }
469: return bDidDraw;
470: }
471:
472: /*
473: * Returns the first line segment used for the arrow head rotation angle
474: */
475: public ETPairT<TSConstPoint, TSConstPoint> getFromLineSegment() {
476: TSEEdge pEdge = getEdge();
477: // assume no bends
478: List pathNodes = pEdge.pathNodes();
479: int numberOfPathNodes = pathNodes.size();
480:
481: TSConstPoint fromPt = pEdge.getTargetClippingPoint();
482: TSConstPoint toPt = pEdge.getSourceClippingPoint();
483:
484: ETPairT<TSConstPoint, TSConstPoint> pPoints = new ETPairT(
485: fromPt, toPt);
486: java.util.List bendPoints = pEdge.bendPoints();
487: if (bendPoints != null && bendPoints.size() >= 1) {
488: // Get the position of the first path node.
489: pPoints.setParamOne((TSConstPoint) bendPoints.get(0));
490: }
491: return pPoints;
492: }
493:
494: /*
495: * Returns the last line segment used for the arrow head rotation angle
496: */
497: public ETPairT<TSConstPoint, TSConstPoint> getToLineSegment() {
498: TSEEdge pEdge = getEdge();
499:
500: // assume no bends
501: TSConstPoint fromPt = pEdge.getSourceClippingPoint();
502: TSConstPoint toPt = pEdge.getTargetClippingPoint();
503:
504: ETPairT<TSConstPoint, TSConstPoint> pPoints = new ETPairT(
505: fromPt, toPt);
506: java.util.List bendPoints = pEdge.bendPoints();
507: if (bendPoints != null && bendPoints.size() >= 1) {
508: // Get the position of the last path node.
509: pPoints.setParamOne((TSConstPoint) bendPoints
510: .get(bendPoints.size() - 1));
511: }
512: return pPoints;
513: }
514:
515: public TSEEdgeUI getEdgeUI() {
516: return (TSEEdgeUI) this .getParent();
517: }
518:
519: public TSEEdge getEdge() {
520: TSEEdge retVal = null;
521:
522: if (this .getParent() != null) {
523: IETGraphObjectUI ui = getParent();
524: if (ui != null) {
525: if (ui.getOwner() instanceof TSEEdge) {
526: retVal = (TSEEdge) ui.getOwner();
527: }
528: }
529: }
530:
531: return retVal;
532: }
533:
534: public TSGraphObject getOwnerGraphObject() {
535: return getEdge();
536: }
537:
538: TSENode getSourceNode() {
539: return (TSENode) getEdge().getSourceNode();
540: }
541:
542: TSENode getTargetNode() {
543: return (TSENode) getEdge().getTargetNode();
544: }
545:
546: IETRect getSourceNodeLogicalBounds() {
547: return new ETRectEx(getSourceNodeBounds());
548: }
549:
550: IETRect getTargetNodeLogicalBounds() {
551: return new ETRectEx(getTargetNodeBounds());
552: }
553:
554: TSConstRect getSourceNodeBounds() {
555: return getSourceNode().getBounds();
556: }
557:
558: TSConstRect getTargetNodeBounds() {
559: return getTargetNode().getBounds();
560: }
561:
562: /*
563: * Draws an arrow head for a line segment.
564: */
565: protected boolean drawArrowHead(IDrawInfo pInfo,
566: int nArrowheadKind,
567: ETPairT<TSConstPoint, TSConstPoint> segment) {
568: return drawArrowHead(pInfo, nArrowheadKind, segment,
569: getStateColor());
570: }
571:
572: protected boolean drawArrowHead(IDrawInfo pInfo,
573: int nArrowheadKind,
574: ETPairT<TSConstPoint, TSConstPoint> segment, TSEColor color) {
575: if (nArrowheadKind == DrawEngineArrowheadKindEnum.DEAK_NO_ARROWHEAD) {
576: return true; // success.
577: }
578:
579: try {
580: return drawArrowHead(pInfo,
581: createArrowHead(nArrowheadKind), segment, color);
582: } catch (Exception e) {
583: e.printStackTrace();
584: return false;
585: }
586: }
587:
588: protected boolean drawArrowHead(IDrawInfo pInfo,
589: IETArrowHead pArrowHead,
590: ETPairT<TSConstPoint, TSConstPoint> segment, TSEColor color) {
591: return pArrowHead != null
592: && pArrowHead.draw(pInfo, segment.getParamOne(),
593: segment.getParamTwo(), getStateColor());
594: }
595:
596: /*
597: * Arrowhead factory.
598: */
599: protected IETArrowHead createArrowHead(int nArrowheadKind) {
600: return ETArrowHeadFactory.create(nArrowheadKind);
601: }
602:
603: /*
604: * Drawing data.
605: */
606:
607: protected int getPenWidth() {
608: return 1;
609: }
610:
611: protected int getLineKind() {
612: return DrawEngineLineKindEnum.DELK_SOLID;
613: }
614:
615: protected int getStartArrowKind() {
616: return DrawEngineArrowheadKindEnum.DEAK_NO_ARROWHEAD;
617: }
618:
619: protected int getEndArrowKind() {
620: return DrawEngineArrowheadKindEnum.DEAK_FILLED;
621: }
622:
623: /*
624: * Returns the Pen or Stroke used to draw the Path Digraph.
625: */
626: protected Stroke getLineStroke(int nLineKind, float width) {
627: return m_stokeCache.getStroke(nLineKind, width);
628: }
629:
630: /*
631: * Draws the Path Diagraph (LineSegments) and any visible path nodes.
632: */
633: protected void drawPathDigraph(IDrawInfo pInfo,
634: IETArrowHead pFromArrow, IETArrowHead pToArrow) {
635: getEdgeUI().drawPath(pInfo.getTSEGraphics());
636: }
637:
638: /*
639: * Main drawing function
640: */
641: public boolean drawEdge(IDrawInfo pInfo, int nStartArrowheadKind,
642: int nEndArrowheadKind, int nLineKind) { // DrawEngineLineKindEnum
643: TSEEdge pEdge = getEdge();
644: if (pEdge == null) {
645: return false;
646: }
647:
648: TSEEdgeUI edgeUI = (TSEEdgeUI) pEdge.getUI();
649:
650: TSEColor stateColor = this .getStateColor();
651: TSEGraphics dc = pInfo.getTSEGraphics();
652:
653: dc.setColor(stateColor);
654:
655: int penWidth = getPenWidth();
656:
657: // Select the pen, but save off the current one first.
658: Stroke prevPen = dc.getStroke();
659: dc.setStroke(this .getLineStroke(nLineKind, penWidth));
660:
661: IETArrowHead pFromArrow = createArrowHead(nStartArrowheadKind);
662: IETArrowHead pToArrow = createArrowHead(nEndArrowheadKind);
663:
664: drawPathDigraph(pInfo, pFromArrow, pToArrow); // Draw the path diagraph.
665:
666: // Arrows always have a solid Stroke.
667: if (nLineKind != DrawEngineLineKindEnum.DELK_SOLID) {
668: dc.setStroke(getLineStroke(
669: DrawEngineLineKindEnum.DELK_SOLID, penWidth));
670: }
671:
672: // Draw the Arrow Heads
673: drawArrowHead(pInfo, pFromArrow, this .getFromLineSegment(),
674: stateColor);
675: drawArrowHead(pInfo, pToArrow, this .getToLineSegment(),
676: stateColor);
677:
678: // Restore the previous pen.
679: pInfo.getTSEGraphics().setStroke(prevPen);
680:
681: return true;
682: }
683:
684: public String getPresentationType() {
685: return "EdgePresentation"; // TODO Override this in derived classes for association's etc.
686: }
687:
688: public IEdgePresentation getIEdgePresentation() {
689: return getPresentation() instanceof IEdgePresentation ? (IEdgePresentation) getPresentation()
690: : null;
691: }
692:
693: /*
694: * Returns a Transformed IETPoint it graph based world coordinance.
695: */
696: protected IETPoint getETPoint(MouseEvent pEvent) {
697: // TSEWindowInputState state = (TSEWindowInputState)this.getUI().getDrawingArea().getGraphWindow().getCurrentState();
698: TSEWindowInputTool state = (TSEWindowInputTool) this .getUI()
699: .getDrawingArea().getGraphWindow().getCurrentTool();
700:
701: return new ETPointEx(state.getNonalignedWorldPoint(pEvent));
702: }
703:
704: public String getMetaTypeInitString() {
705: return null;
706: }
707:
708: /**
709: * Adds a stereotype and or name label pullright to the context menu
710: *
711: * @param nKind [in] The kind of standard label to add
712: * @param pContextMenu[in] The context menu about to be displayed
713: */
714: public void addStandardLabelsToPullright(int kind,
715: IMenuManager manager) {
716: if (kind == StandardLabelKind.SLK_STEREOTYPE
717: || kind == StandardLabelKind.SLK_ALL) {
718: addStereotypeLabelPullright(this , manager);
719: }
720: if (kind == StandardLabelKind.SLK_NAME
721: || kind == StandardLabelKind.SLK_ALL) {
722: IElement pEle = getFirstModelElement();
723: if (pEle != null && pEle instanceof INamedElement) {
724: addNameLabelPullright(this , manager);
725: }
726: }
727: }
728:
729: /**
730: * Handles the stereotype and name sensitivity and check
731: *
732: * @param pContextMenu [in] The parent context menu that was displayed.
733: * @param pMenuItem [in] The button that the sensitivity is being requested for
734: * @param buttonKind [in] The ID of the button above. This ID is the one used when creating the button.
735: * @param bHandled [out] true if the button happened to be a stereotype and we set its state
736: */
737: protected boolean handleStandardLabelSensitivityAndCheck(String id,
738: ContextMenuActionClass pClass) {
739: boolean handled = false;
740: ILabelManager labelMgr = getLabelManager();
741: boolean isReadOnly = isParentDiagramReadOnly();
742: if (id.equals("MBK_SHOW_STEREOTYPE")) {
743: boolean isDisplayed = labelMgr
744: .isDisplayed(TSLabelKind.TSLK_STEREOTYPE);
745: pClass.setChecked(isDisplayed);
746:
747: handled = isReadOnly ? false : true;
748: } else if (id.equals("MBK_SHOW_NAME_LABEL")) {
749: boolean isDisplayed = labelMgr
750: .isDisplayed(TSLabelKind.TSLK_NAME);
751: pClass.setChecked(isDisplayed);
752:
753: handled = isReadOnly ? false : true;
754: }
755: return handled;
756: }
757:
758: /**
759: * Handles the stereotype and name selections
760: *
761: * @param pContextMenu[in] The context menu that was displayed to the user
762: * @param pMenuItem[in] The menu that was just selected
763: * @param bHandled[out] true if the stereotype selection was handled
764: */
765: protected boolean handleStandardLabelSelection(ActionEvent e,
766: String id) {
767: boolean handled = false;
768: IDrawingAreaControl pDiagram = getDrawingArea();
769: ILabelManager labelMgr = getLabelManager();
770: if (pDiagram != null) {
771: if (id.equals("MBK_SHOW_STEREOTYPE")) {
772: if (labelMgr != null) {
773: boolean isDisplayed = labelMgr
774: .isDisplayed(TSLabelKind.TSLK_STEREOTYPE);
775: labelMgr.showLabel(TSLabelKind.TSLK_STEREOTYPE,
776: isDisplayed ? false : true);
777: }
778: pDiagram.refresh(false);
779: handled = true;
780: } else if (id.equals("MBK_SHOW_NAME_LABEL")) {
781: if (labelMgr != null) {
782: boolean isDisplayed = labelMgr
783: .isDisplayed(TSLabelKind.TSLK_NAME);
784: labelMgr.showLabel(TSLabelKind.TSLK_NAME,
785: isDisplayed ? false : true);
786: if (!isDisplayed) {
787: IPresentationElement pPE = labelMgr
788: .getLabel(TSLabelKind.TSLK_NAME);
789: if (pPE != null
790: && pPE instanceof ILabelPresentation) {
791: pDiagram
792: .postEditLabel((ILabelPresentation) pPE);
793: }
794: }
795: }
796: pDiagram.refresh(false);
797: handled = true;
798: }
799: }
800: return handled;
801: }
802:
803: public String getDrawEngineID() {
804: return "EdgeDrawEngine";
805: }
806:
807: /**
808: * Handles the stereotype sensitivity and check
809: *
810: * @param pContextMenu [in] The parent context menu that was displayed.
811: * @param pMenuItem [in] The button that the sensitivity is being requested for
812: * @param buttonKind [in] The ID of the button above. This ID is the one used when creating the button.
813: * @param bHandled [out] true if the button happened to be a stereotype and we set its state
814: */
815: public boolean handleStereotypeSensitivityAndCheck(
816: IProductContextMenu pContextMenu,
817: IProductContextMenuItem pMenuItem, int buttonKind) {
818: boolean bHandled = false;
819: try {
820:
821: ILabelManager pLabelManager = getLabelManager();
822: switch (buttonKind) {
823: case IADDrawEngineButtonHandler.MBK_SHOW_STEREOTYPE: {
824: // Set the check state
825: boolean bIsDisplayed = pLabelManager
826: .isDisplayed(TSLabelKind.TSLK_STEREOTYPE);
827: pMenuItem.setChecked(bIsDisplayed);
828:
829: // Set the sensitivities
830: pMenuItem
831: .setSensitive(parentDiagramIsReadOnly() ? false
832: : true);
833:
834: bHandled = true;
835: }
836: break;
837: }
838: } catch (Exception e) {
839: e.printStackTrace();
840: }
841: return bHandled;
842: }
843:
844: /*
845: * Return a pointer to the IEdgePresentation.
846: */
847: public IEdgePresentation getEdgePresentationElement() {
848: IPresentationElement pe = getPresentationElement();
849: if (pe instanceof IEdgePresentation) {
850: return (IEdgePresentation) pe;
851: }
852: return null;
853: }
854:
855: /*
856: * (non-Javadoc)
857: * @see org.netbeans.modules.uml.ui.support.viewfactorysupport.IEdgeDrawEngine#verifyEdgeEnds()
858: */
859: public void verifyEdgeEnds() {
860: }
861:
862: /*
863: * (non-Javadoc)
864: * @see org.netbeans.modules.uml.ui.support.viewfactorysupport.IEdgeDrawEngine#getLineColor()
865: */
866: public Color getLineColor() {
867: return this .getColor().getColor();
868: }
869:
870: public int setLineColor(String resourceName, int r, int g, int b) {
871: return setLineColor(resourceName, new Color(r, g, b));
872: }
873:
874: public int setLineColor(String resourceName, Color color) {
875: if (color != null) {
876: m_nBorderStringID = m_ResourceUser.setResourceStringID(
877: m_nBorderStringID, resourceName, color.getRGB());
878: TSEEdgeUI ui = m_nBorderStringID >= 0
879: && getUI() instanceof TSEEdgeUI ? (TSEEdgeUI) getUI()
880: : null;
881: if (ui != null) {
882: ui.setLineColor(new TSEColor(
883: getColor(m_nBorderStringID)));
884: }
885: }
886:
887: return m_nBorderStringID;
888: }
889:
890: /*
891: * Hides the m_resourceUser lookup.
892: */
893: public Color getColor(int colorID) {
894: return new Color(m_ResourceUser.getCOLORREFForStringID(colorID));
895: }
896:
897: /* (non-Javadoc)
898: * @see org.netbeans.modules.uml.ui.support.viewfactorysupport.IDrawEngine#performDeepSynch()
899: */
900: public long performDeepSynch() {
901: long retVal = 0;
902: try {
903: retVal = super .performDeepSynch();
904:
905: // Since we're an edge call a routine to verify that the Target and Source
906: // nodes are correct so that when we right click the parent/child relationships
907: // are correct.
908: this .verifyEdgeEnds();
909: } catch (Exception e) {
910: e.printStackTrace();
911: }
912: return retVal;
913: }
914:
915: /* (non-Javadoc)
916: * @see org.netbeans.modules.uml.ui.support.viewfactorysupport.IDrawEngine#postLoad()
917: */
918: public long postLoad() {
919:
920: // //NL Currently label info is not read from the archive. As a result the labels get deleted in
921: // // postLoadVerification because there not loaded with presentation element.
922: // // Until readFromArchive is complete, the following provides a workaround for
923: // // initializing the labels with PEs and attaching them to their parent edge model elements
924: // //
925: // ILabelManager labelMgr = getLabelManager();
926: // if (labelMgr != null)
927: // {
928: // labelMgr.resetLabels();
929: // }
930:
931: return 0;
932:
933: }
934:
935: /////////////
936: // Accessible
937: /////////////
938:
939: AccessibleContext accessibleContext;
940:
941: public AccessibleContext getAccessibleContext() {
942: if (accessibleContext == null) {
943: accessibleContext = new AccessibleETEdgeDrawEngine();
944: }
945: return accessibleContext;
946: }
947:
948: public class AccessibleETEdgeDrawEngine extends
949: AccessibleETDrawEngine {
950:
951: public String getAccessibleDescription() {
952: if (getIEdgePresentation() != null) {
953: IDrawEngine toEng = getIEdgePresentation()
954: .getEdgeToDrawEngine();
955: IDrawEngine fromEng = getIEdgePresentation()
956: .getEdgeFromDrawEngine();
957:
958: if (toEng != null && toEng instanceof Accessible
959: && fromEng != null
960: && fromEng instanceof Accessible) {
961: AccessibleContext toCtx = ((Accessible) toEng)
962: .getAccessibleContext();
963: AccessibleContext fromCtx = ((Accessible) fromEng)
964: .getAccessibleContext();
965: if (toCtx != null && fromCtx != null) {
966: // TBD!!! to resource-bundle-ize
967: return getAccessibleName() + " from "
968: + fromCtx.getAccessibleName() + " to "
969: + toCtx.getAccessibleName();
970: }
971: }
972: }
973: return super .getAccessibleDescription();
974: }
975:
976: public AccessibleRole getAccessibleRole() {
977: return UMLAccessibleRole.UML_EDGE;
978: }
979:
980: ////////////////////////////////
981: // interface AccessibleComponent
982: ////////////////////////////////
983:
984: public java.awt.Color getForeground() {
985: return getLineColor();
986: }
987:
988: public void setForeground(java.awt.Color color) {
989: ;
990: }
991:
992: }
993:
994: }
|