0001: /*
0002: * The contents of this file are subject to the terms of the Common Development
0003: * and Distribution License (the License). You may not use this file except in
0004: * compliance with the License.
0005: *
0006: * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
0007: * or http://www.netbeans.org/cddl.txt.
0008: *
0009: * When distributing Covered Code, include this CDDL Header Notice in each file
0010: * and include the License file at http://www.netbeans.org/cddl.txt.
0011: * If applicable, add the following below the CDDL Header, with the fields
0012: * enclosed by brackets [] replaced by your own identifying information:
0013: * "Portions Copyrighted [year] [name of copyright owner]"
0014: *
0015: * The Original Software is NetBeans. The Initial Developer of the Original
0016: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
0017: * Microsystems, Inc. All Rights Reserved.
0018: */
0019:
0020: package org.netbeans.modules.soa.mappercore;
0021:
0022: import java.awt.Graphics;
0023: import java.awt.Graphics2D;
0024: import java.awt.Point;
0025: import java.awt.Rectangle;
0026: import java.awt.RenderingHints;
0027: import java.awt.datatransfer.DataFlavor;
0028: import java.awt.datatransfer.Transferable;
0029: import java.awt.datatransfer.UnsupportedFlavorException;
0030: import java.awt.dnd.DropTargetDragEvent;
0031: import java.awt.dnd.DropTargetDropEvent;
0032: import java.io.IOException;
0033: import java.util.HashMap;
0034: import java.util.HashSet;
0035: import java.util.Map;
0036: import java.util.Set;
0037: import javax.swing.JComponent;
0038: import javax.swing.JTree;
0039: import javax.swing.tree.TreePath;
0040: import org.netbeans.modules.soa.mappercore.dnd.DnDConstants;
0041: import org.netbeans.modules.soa.mappercore.model.Constant;
0042: import org.netbeans.modules.soa.mappercore.model.Graph;
0043: import org.netbeans.modules.soa.mappercore.model.Link;
0044: import org.netbeans.modules.soa.mappercore.model.MapperModel;
0045: import org.netbeans.modules.soa.mappercore.model.SourcePin;
0046: import org.netbeans.modules.soa.mappercore.model.TargetPin;
0047: import org.netbeans.modules.soa.mappercore.model.TreeSourcePin;
0048: import org.netbeans.modules.soa.mappercore.model.Vertex;
0049: import org.netbeans.modules.soa.mappercore.model.VertexItem;
0050: import org.netbeans.modules.soa.mappercore.utils.MapperCollection;
0051: import org.netbeans.modules.soa.mappercore.utils.MapperTreePath;
0052: import org.netbeans.modules.soa.mappercore.utils.Utils;
0053:
0054: /**
0055: *
0056: * @author anjeleevich
0057: */
0058: public class LinkTool extends MapperPropertyAccess {
0059:
0060: private JComponent sourceComponent;
0061: private JComponent targetComponent;
0062:
0063: private SourcePin sourcePin;
0064: private TargetPin targetPin;
0065:
0066: private TreePath targetPath;
0067:
0068: private int x1;
0069: private int y1;
0070: private int x2;
0071: private int y2;
0072:
0073: private boolean outgoing;
0074:
0075: private long uid = -1;
0076:
0077: private MapperCollection activePins;
0078:
0079: private TreePath oldTreePath = null;
0080: private Link oldLink = null;
0081:
0082: public LinkTool(Mapper mapper) {
0083: super (mapper);
0084: }
0085:
0086: CanvasRendererContext getCanvasRendererContext() {
0087: return new LinkToolCanvasRendererContext(this );
0088: }
0089:
0090: public SourcePin getSourcePin() {
0091: return sourcePin;
0092: }
0093:
0094: public TargetPin getTargetPin() {
0095: return targetPin;
0096: }
0097:
0098: public boolean isOutgoing() {
0099: return outgoing;
0100: }
0101:
0102: public boolean isIngoing() {
0103: return !outgoing;
0104: }
0105:
0106: public boolean isActive() {
0107: return uid >= 0;
0108: }
0109:
0110: public Link getOldLink() {
0111: return oldLink;
0112: }
0113:
0114: public TreePath getOldTreePath() {
0115: return oldTreePath;
0116: }
0117:
0118: public TreePath getTargetPath() {
0119: return targetPath;
0120: }
0121:
0122: public JComponent getSourceComponent() {
0123: return sourceComponent;
0124: }
0125:
0126: MapperCollection getActivePins() {
0127: return activePins;
0128: }
0129:
0130: private void initOld(Link oldLink, TreePath oldTreePath) {
0131: if (oldLink != null) {
0132: this .oldLink = oldLink;
0133: this .oldTreePath = oldTreePath;
0134: } else {
0135: this .oldLink = null;
0136: this .oldTreePath = null;
0137: }
0138: }
0139:
0140: public Point getSourcePoint() {
0141: if (sourcePin == null) {
0142: if (sourceComponent == null)
0143: return null;
0144: return Utils.fromScrollPane(sourceComponent, new Point(x1,
0145: y1), null);
0146: }
0147:
0148: if (sourcePin instanceof TreeSourcePin) {
0149: TreePath treePath = ((TreeSourcePin) sourcePin)
0150: .getTreePath();
0151: JTree tree = (JTree) sourceComponent;
0152:
0153: Rectangle bounds = null;
0154:
0155: while (bounds == null && treePath != null) {
0156: bounds = tree
0157: .getRowBounds(tree.getRowForPath(treePath));
0158: treePath = treePath.getParentPath();
0159: }
0160:
0161: return (bounds == null) ? new Point(0, 0) : new Point(
0162: bounds.x + bounds.width, bounds.y + bounds.height
0163: / 2);
0164: }
0165:
0166: Mapper mapper = getMapper();
0167: Canvas canvas = getCanvas();
0168: int step = mapper.getStepSize();
0169:
0170: Vertex vertex = (Vertex) sourcePin;
0171: MapperNode node = mapper.getNode(targetPath, true);
0172:
0173: Rectangle bounds = vertex.getBounds(step);
0174:
0175: int px = vertex.getPinGlobalX() * step; // bounds.x + bounds.width;
0176: int py = vertex.getPinGlobalY() * step; // bounds.y + bounds.height / 2;
0177:
0178: px = canvas.toCanvas(px);
0179: py = node.yToView(py + (step - 1) / 2) + 1;
0180:
0181: return new Point(px, py);
0182: }
0183:
0184: public JComponent getTargetComponent() {
0185: return targetComponent;
0186: }
0187:
0188: public Point getTargetPoint() {
0189: if (targetPin == null) {
0190: if (targetComponent == null)
0191: return null;
0192: return Utils.fromScrollPane(targetComponent, new Point(x2,
0193: y2), null);
0194: }
0195:
0196: Mapper mapper = getMapper();
0197: MapperNode node = mapper.getNode(targetPath, true);
0198:
0199: if (targetPin instanceof Graph) {
0200: int py = node.yToView(node.getContentCenterY());
0201: int px = mapper.getRightTree().getWidth()
0202: - node.getLabelWidth() - node.getIndent();
0203: return new Point(px, py);
0204: }
0205:
0206: Canvas canvas = mapper.getCanvas();
0207: int step = mapper.getStepSize();
0208:
0209: VertexItem item = (VertexItem) targetPin;
0210: int px = item.getGlobalX() * step;
0211: int py = (item.getGlobalY() + item.getHeight() / 2) * step;
0212:
0213: px = canvas.toCanvas(px);
0214: py = node.yToView(py + (step - 1) / 2) + 1;
0215:
0216: return new Point(px, py);
0217: }
0218:
0219: public Transferable activateIngoing(TreePath targetPath,
0220: Graph graph, Link link) {
0221: this .outgoing = false;
0222: this .uid = createUID();
0223:
0224: this .sourcePin = null;
0225: this .sourceComponent = null;
0226:
0227: this .targetPath = targetPath;
0228: this .targetPin = graph;
0229: this .targetComponent = getRightTree();
0230:
0231: this .sourcePin = null;
0232: this .sourceComponent = null;
0233:
0234: initOld(link, targetPath);
0235:
0236: this .activePins = findActivePins();
0237:
0238: return new LinkTransferable(uid);
0239: }
0240:
0241: public Transferable activateIngoing(TreePath targetPath,
0242: VertexItem item) {
0243: this .outgoing = false;
0244: this .uid = createUID();
0245:
0246: this .sourcePin = null;
0247: this .sourceComponent = null;
0248:
0249: this .targetPath = targetPath;
0250: this .targetPin = item;
0251: this .targetComponent = getCanvas();
0252:
0253: this .sourcePin = null;
0254: this .sourceComponent = null;
0255:
0256: initOld(item.getIngoingLink(), targetPath);
0257:
0258: this .activePins = findActivePins();
0259:
0260: return new LinkTransferable(uid);
0261: }
0262:
0263: public Transferable activateOutgoing(TreeSourcePin sourcePin,
0264: Link oldLink, TreePath oldTreePath) {
0265: this .outgoing = true;
0266: this .uid = createUID();
0267:
0268: this .sourcePin = sourcePin;
0269: this .sourceComponent = getLeftTree();
0270:
0271: initOld(oldLink, oldTreePath);
0272:
0273: this .targetPath = null;
0274: this .targetComponent = null;
0275: this .targetPin = null;
0276:
0277: this .activePins = findActivePins();
0278:
0279: return new LinkTransferable(uid);
0280: }
0281:
0282: public Transferable activateOutgoing(TreePath targetPath,
0283: Vertex sourcePin) {
0284: this .outgoing = true;
0285: this .uid = createUID();
0286:
0287: this .sourcePin = sourcePin;
0288: this .sourceComponent = getCanvas();
0289:
0290: initOld(sourcePin.getOutgoingLink(), targetPath);
0291:
0292: this .targetPath = targetPath;
0293: this .targetPin = null;
0294: this .targetComponent = null;
0295:
0296: this .activePins = findActivePins();
0297:
0298: return new LinkTransferable(uid);
0299: }
0300:
0301: private void reset() {
0302: uid = -1;
0303:
0304: oldLink = null;
0305: oldTreePath = null;
0306:
0307: sourcePin = null;
0308: sourceComponent = null;
0309:
0310: targetPath = null;
0311: targetPin = null;
0312: targetComponent = null;
0313:
0314: activePins = null;
0315: }
0316:
0317: private boolean isValidTransferable(Transferable transferable) {
0318: try {
0319: long transferableUID = (Long) transferable
0320: .getTransferData(LINK_DATA_FLAVOR);
0321: return (transferableUID == this .uid);
0322: } catch (Exception exception) {
0323: }
0324:
0325: return false;
0326: }
0327:
0328: public boolean drag(JComponent component, DropTargetDragEvent dtde) {
0329: if (!isActive())
0330: return false;
0331: if (!isValidTransferable(dtde.getTransferable()))
0332: return false;
0333:
0334: Canvas canvas = getCanvas();
0335: LeftTree leftTree = getLeftTree();
0336: RightTree rightTree = getRightTree();
0337:
0338: canvas.repaint();
0339: leftTree.repaint();
0340: rightTree.repaint();
0341:
0342: if (isIngoing()) {
0343: if (component == leftTree)
0344: return dragIngoing(leftTree, dtde);
0345: if (component == canvas)
0346: return dragIngoing(canvas, dtde);
0347: if (component == rightTree)
0348: return dragIngoing(rightTree, dtde);
0349: } else {
0350: if (component == leftTree)
0351: return dragOutgoing(leftTree, dtde);
0352: if (component == canvas)
0353: return dragOutgoing(canvas, dtde);
0354: if (component == rightTree)
0355: return dragOutgoing(rightTree, dtde);
0356: }
0357:
0358: throw new IllegalArgumentException("Unknown component: "
0359: + component);
0360: }
0361:
0362: public boolean dragIngoing(LeftTree tree, DropTargetDragEvent dtde) {
0363: Point point = dtde.getLocation();
0364: Point scrollPanePoint = Utils.toScrollPane(tree, point, null);
0365:
0366: this .sourceComponent = tree;
0367: this .x1 = scrollPanePoint.x;
0368: this .y1 = scrollPanePoint.y;
0369:
0370: TreeSourcePin treeSourcePin = null;
0371: TreePath treePath = tree.getPathForLocation(point.x, point.y);
0372:
0373: if (treePath != null) {
0374: MapperModel model = getMapperModel();
0375: treeSourcePin = model.getTreeSourcePin(treePath);
0376: if (treeSourcePin != null
0377: && !canConnect(model, targetPath, treeSourcePin,
0378: targetPin)) {
0379: treeSourcePin = null;
0380: }
0381: }
0382:
0383: this .sourcePin = treeSourcePin;
0384:
0385: acceptReject(dtde, treeSourcePin == null);
0386:
0387: return true;
0388: }
0389:
0390: public boolean dragIngoing(Canvas canvas, DropTargetDragEvent dtde) {
0391: Point canvasPoint = dtde.getLocation();
0392: Point scrollPanePoint = Utils.toScrollPane(canvas, canvasPoint,
0393: null);
0394:
0395: sourceComponent = canvas;
0396:
0397: MapperNode node = getNodeAt(canvasPoint.y);
0398:
0399: int step = getMapper().getStepSize();
0400:
0401: Vertex sourceVertex = null;
0402:
0403: boolean rejectDrag = false;
0404:
0405: if (node != null) {
0406: TreePath treePath = node.getTreePath();
0407:
0408: int graphX = canvas.toGraph(canvasPoint.x);
0409: int graphY = node.yToNode(canvasPoint.y);
0410:
0411: Graph graph = node.getGraph();
0412:
0413: if (!treePath.equals(targetPath)) {
0414: rejectDrag = true;
0415: } else if (graph != null && node.isGraphExpanded()) {
0416: graphY -= (step - 1) / 2;
0417: sourceVertex = findVertex(treePath, graph, graphX,
0418: graphY, step);
0419: }
0420: } else {
0421: rejectDrag = true;
0422: }
0423:
0424: x1 = scrollPanePoint.x;
0425: y1 = scrollPanePoint.y;
0426: sourceComponent = canvas;
0427: sourcePin = sourceVertex;
0428:
0429: acceptReject(dtde, rejectDrag);
0430:
0431: if (targetPin instanceof Graph)
0432: getRightTree().repaint();
0433: getCanvas().repaint();
0434: return true;
0435: }
0436:
0437: public boolean dragIngoing(RightTree tree, DropTargetDragEvent dtde) {
0438: Point point = dtde.getLocation();
0439: Point scrollPanePoint = Utils.toScrollPane(tree, point, null);
0440:
0441: this .x1 = scrollPanePoint.x;
0442: this .y1 = scrollPanePoint.y;
0443: this .sourceComponent = tree;
0444: this .sourcePin = null;
0445:
0446: dtde.rejectDrag();
0447:
0448: return true;
0449: }
0450:
0451: public boolean dragOutgoing(LeftTree tree, DropTargetDragEvent dtde) {
0452: Point point = dtde.getLocation();
0453: Point scrollPanePoint = Utils.toScrollPane(tree, point, null);
0454:
0455: this .x2 = scrollPanePoint.x;
0456: this .y2 = scrollPanePoint.y;
0457: this .targetComponent = tree;
0458: this .targetPin = null;
0459:
0460: dtde.rejectDrag();
0461:
0462: getCanvas().repaint();
0463:
0464: return true;
0465: }
0466:
0467: public boolean dragOutgoing(Canvas canvas, DropTargetDragEvent dtde) {
0468: Point canvasPoint = dtde.getLocation();
0469: Point scrollPanePoint = Utils.toScrollPane(canvas, canvasPoint,
0470: null);
0471:
0472: MapperNode node = getNodeAt(canvasPoint.y);
0473: int step = getMapper().getStepSize();
0474:
0475: VertexItem targetVertexItem = null;
0476:
0477: boolean rejectDrag = false;
0478:
0479: if (node != null) {
0480: TreePath treePath = node.getTreePath();
0481:
0482: int graphX = canvas.toGraph(canvasPoint.x);
0483: int graphY = node.yToNode(canvasPoint.y);
0484:
0485: Graph graph = node.getGraph();
0486:
0487: if (graph != null && node.isGraphExpanded()) {
0488: graphY -= (step - 1) / 2;
0489: targetVertexItem = findVertexItem(treePath, graph,
0490: graphX, graphY, step);
0491: }
0492:
0493: if (sourcePin instanceof TreeSourcePin) {
0494: targetPath = treePath;
0495: } else if (!treePath.equals(targetPath)) {
0496: rejectDrag = true;
0497: }
0498: } else {
0499: rejectDrag = true;
0500: }
0501:
0502: x2 = scrollPanePoint.x;
0503: y2 = scrollPanePoint.y;
0504: targetComponent = canvas;
0505: targetPin = targetVertexItem;
0506:
0507: if (sourcePin instanceof TreeSourcePin)
0508: getLeftTree().repaint();
0509: getCanvas().repaint();
0510:
0511: acceptReject(dtde, rejectDrag);
0512:
0513: return true;
0514: }
0515:
0516: public boolean dragOutgoing(RightTree tree, DropTargetDragEvent dtde) {
0517: Point point = dtde.getLocation();
0518: Point scrollPanePoint = Utils.toScrollPane(tree, point, null);
0519:
0520: MapperNode node = getNodeAt(point.y);
0521:
0522: Graph targetGraph = null;
0523: TreePath targetPath = this .targetPath;
0524:
0525: MapperModel model = getMapperModel();
0526:
0527: boolean rejectDrag = false;
0528:
0529: if (node != null) {
0530: Graph graph = node.getGraph();
0531: TreePath treePath = node.getTreePath();
0532:
0533: if (graph != null && treePath != null) {
0534: if (sourcePin instanceof Vertex) {
0535: if (Utils.equal(targetPath, treePath)
0536: && canConnect(model, treePath, sourcePin,
0537: graph)) {
0538: targetGraph = graph;
0539: targetPath = treePath;
0540: }
0541: } else if (canConnect(model, treePath, sourcePin, graph)) {
0542: // TreeSourcePin
0543: targetGraph = graph;
0544: targetPath = treePath;
0545: }
0546: } else {
0547: graph = null;
0548: }
0549: }
0550:
0551: this .x2 = scrollPanePoint.x;
0552: this .y2 = scrollPanePoint.y;
0553: this .targetComponent = tree;
0554:
0555: if (targetGraph != null) {
0556: this .targetPin = targetGraph;
0557: this .targetPath = targetPath;
0558: acceptReject(dtde, false);
0559: } else {
0560: this .targetPin = null;
0561: acceptReject(dtde, true);
0562: }
0563:
0564: getCanvas().repaint();
0565:
0566: return true;
0567: }
0568:
0569: private void acceptReject(DropTargetDragEvent dtde,
0570: boolean rejectDrag) {
0571: if (rejectDrag) {
0572: dtde.rejectDrag();
0573: } else {
0574: dtde.acceptDrag(DnDConstants.COPY + DnDConstants.LINK
0575: + DnDConstants.MOVE);
0576: }
0577: }
0578:
0579: private Vertex findVertex(TreePath treePath, Graph graph,
0580: int graphX, int graphY, int step) {
0581: for (int i = graph.getVertexCount() - 1; i >= 0; i--) {
0582: Vertex vertex = graph.getVertex(i);
0583: if (vertex.dontContains(graphX, graphY, step))
0584: continue;
0585:
0586: if (vertex.contains(graphX, graphY, step)) {
0587: if (activePins.contains(treePath, vertex)) {
0588: return vertex;
0589: }
0590:
0591: return null;
0592: }
0593:
0594: if (activePins.contains(treePath, vertex)) {
0595: if (vertex.sourcePinContains(graphX, graphY, step)) {
0596: return vertex;
0597: }
0598: }
0599: }
0600:
0601: return null;
0602: }
0603:
0604: private VertexItem findVertexItem(TreePath treePath, Graph graph,
0605: int graphX, int graphY, int step) {
0606: for (int i = graph.getVertexCount() - 1; i >= 0; i--) {
0607: Vertex vertex = graph.getVertex(i);
0608: if (vertex.dontContains(graphX, graphY, step))
0609: continue;
0610:
0611: if (vertex.contains(graphX, graphY, step)) {
0612: for (int j = vertex.getItemCount() - 1; j >= 0; j--) {
0613: VertexItem item = vertex.getItem(j);
0614: if (item.contains(graphX, graphY, step)) {
0615: if (activePins.contains(treePath, item)) {
0616: return item;
0617: }
0618: return null;
0619: }
0620: }
0621: return null;
0622: }
0623:
0624: if (!(vertex instanceof Constant)) {
0625: for (int j = vertex.getItemCount() - 1; j >= 0; j--) {
0626: VertexItem item = vertex.getItem(j);
0627: if (activePins.contains(treePath, item)
0628: && item.targetPinContains(graphX, graphY,
0629: step)) {
0630: return item;
0631: }
0632: }
0633: }
0634: }
0635:
0636: return null;
0637: }
0638:
0639: public boolean drop(JComponent component, DropTargetDropEvent dtde) {
0640: if (!isActive())
0641: return false;
0642: if (!isValidTransferable(dtde.getTransferable()))
0643: return false;
0644:
0645: MapperModel model = getMapperModel();
0646:
0647: if (sourcePin != null && targetPin != null
0648: && targetPath != null) {
0649: model.connect(targetPath, sourcePin, targetPin,
0650: oldTreePath, oldLink);
0651: }
0652:
0653: getMapper().repaint();
0654: return true;
0655: }
0656:
0657: public void done() {
0658: if (!isActive())
0659: return;
0660: reset();
0661: getMapper().repaint();
0662: }
0663:
0664: public void setSource(SourcePin sourcePin, JComponent c, Point p) {
0665: this .sourcePin = sourcePin;
0666: this .sourceComponent = c;
0667: this .x1 = p.x;
0668: this .y1 = p.y;
0669: }
0670:
0671: public void setTarget(TreePath targetPath, TargetPin targetPin,
0672: JComponent c, Point p) {
0673: this .targetPath = targetPath;
0674: this .targetPin = targetPin;
0675: this .targetComponent = c;
0676: this .x2 = p.x;
0677: this .y2 = p.y;
0678: }
0679:
0680: public void paintLeftTree(LeftTree tree, Graphics g) {
0681: if (!isActive())
0682: return;
0683: if (sourcePin instanceof TreeSourcePin
0684: && targetComponent != tree) {
0685: Point sourcePoint = getSourcePoint();
0686: g.setColor(MapperStyle.LINK_COLOR_SELECTED_NODE);
0687: g.drawLine(sourcePoint.x, sourcePoint.y,
0688: tree.getWidth() - 1, sourcePoint.y);
0689: }
0690: }
0691:
0692: public void paintCanvas(Canvas canvas, Graphics g) {
0693: if (!isActive())
0694: return;
0695: if (sourceComponent != targetComponent
0696: || (sourceComponent == canvas && targetComponent == canvas)) {
0697: LeftTree leftTree = getLeftTree();
0698: RightTree rightTree = getRightTree();
0699:
0700: Point sourcePoint = getSourcePoint();
0701: Point targetPoint = getTargetPoint();
0702:
0703: if (sourcePoint == null || targetPoint == null)
0704: return;
0705:
0706: Rectangle visibleRect = canvas.getViewport().getViewRect();
0707:
0708: boolean paintSourceDecoration = true;
0709: boolean paintTargetDecoration = true;
0710:
0711: if (sourceComponent == leftTree) {
0712: paintSourceDecoration = false;
0713: sourcePoint.y = canvas.yFromMapper(leftTree
0714: .yToMapper(sourcePoint.y));
0715: sourcePoint.x = Integer.MIN_VALUE;
0716: } else if (sourceComponent == rightTree) {
0717: sourcePoint.y = canvas.yFromMapper(rightTree
0718: .yToMapper(sourcePoint.y));
0719: sourcePoint.x = visibleRect.x + visibleRect.width;
0720: }
0721:
0722: if (targetComponent == rightTree) {
0723: paintTargetDecoration = false;
0724: targetPoint.y = canvas.yFromMapper(rightTree
0725: .yToMapper(targetPoint.y));
0726: targetPoint.x = Integer.MAX_VALUE;
0727: } else if (targetComponent == leftTree) {
0728: targetPoint.y = canvas.yFromMapper(leftTree
0729: .yToMapper(targetPoint.y));
0730: targetPoint.x = visibleRect.x;
0731: }
0732:
0733: int step = getMapper().getStepSize();
0734:
0735: Graphics2D g2 = (Graphics2D) g.create();
0736: g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
0737: RenderingHints.VALUE_ANTIALIAS_ON);
0738:
0739: if (!Utils.equal(sourcePoint, targetPoint)) {
0740: Link.paintLine(g2,
0741: MapperStyle.LINK_COLOR_SELECTED_NODE, null,
0742: sourcePoint, targetPoint, step, visibleRect.x,
0743: visibleRect.x + visibleRect.width);
0744: } else {
0745: if (targetPin == null) {
0746: paintTargetDecoration = false;
0747: }
0748: if (sourcePin == null) {
0749: paintSourceDecoration = false;
0750: }
0751: }
0752:
0753: if (paintSourceDecoration) {
0754: Link.paintSourceDecoration(g2, sourcePoint, null, step);
0755: }
0756:
0757: if (paintTargetDecoration) {
0758: Link.paintTargetDecoration(g2, targetPoint, null, step);
0759: }
0760:
0761: g2.dispose();
0762: }
0763: }
0764:
0765: public void paintRightTree(RightTree tree, Graphics g) {
0766: if (!isActive())
0767: return;
0768: if (targetPin instanceof Graph && sourceComponent != tree) {
0769: Point targetPoint = getTargetPoint();
0770: g.setColor(MapperStyle.LINK_COLOR_SELECTED_NODE);
0771:
0772: int step = getMapper().getStepSize();
0773:
0774: Graphics2D g2 = (Graphics2D) g.create();
0775: g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
0776: RenderingHints.VALUE_ANTIALIAS_ON);
0777:
0778: g2.drawLine(0, targetPoint.y, targetPoint.x - step / 2,
0779: targetPoint.y);
0780:
0781: Link.paintTargetDecoration(g2, targetPoint, null, step);
0782:
0783: g2.dispose();
0784: }
0785: }
0786:
0787: private MapperCollection findActivePins() {
0788: return (isOutgoing()) ? findActiveTargetPins()
0789: : findActiveSourcePins();
0790: }
0791:
0792: private MapperCollection findActiveSourcePins() {
0793: MapperModel model = getMapperModel();
0794: if (model != null) {
0795: if (model.getRoot() != null && targetPath != null
0796: && targetPin != null) {
0797: Set<Vertex> verteces = new HashSet<Vertex>();
0798: findSourceVerteces(targetPin, model, targetPath,
0799: verteces);
0800: return MapperCollection.createVerteces(targetPath,
0801: verteces);
0802: }
0803: }
0804: return MapperCollection.create();
0805: }
0806:
0807: private MapperCollection findActiveTargetPins() {
0808: MapperModel model = getMapperModel();
0809: if (model != null) {
0810: Object root = model.getRoot();
0811: if (root != null) {
0812: if (sourcePin instanceof TreeSourcePin) {
0813: Map<TreePath, Set<VertexItem>> vertexItems = new HashMap<TreePath, Set<VertexItem>>();
0814: findTargetVertexItems((TreeSourcePin) sourcePin,
0815: model, new TreePath(root), vertexItems);
0816: return MapperCollection.create(vertexItems);
0817: } else if (sourcePin instanceof Vertex
0818: && targetPath != null) {
0819: Set<VertexItem> vertexItems = new HashSet<VertexItem>();
0820: findTargetVertexItems((Vertex) sourcePin, model,
0821: targetPath, vertexItems);
0822: return MapperCollection.createVertexItems(
0823: targetPath, vertexItems);
0824: }
0825: }
0826: }
0827:
0828: return MapperCollection.create();
0829: }
0830:
0831: private void findSourceVerteces(TargetPin targetPin,
0832: MapperModel model, TreePath treePath, Set<Vertex> result) {
0833: Graph graph = model.getGraph(treePath);
0834:
0835: if (graph != null) {
0836: for (int i = graph.getVertexCount() - 1; i >= 0; i--) {
0837: Vertex vertex = graph.getVertex(i);
0838: if (canConnect(model, treePath, vertex, targetPin)) {
0839: result.add(vertex);
0840: }
0841: }
0842: }
0843: }
0844:
0845: private void findTargetVertexItems(TreeSourcePin treeSourcePin,
0846: MapperModel model, TreePath treePath,
0847: Map<TreePath, Set<VertexItem>> result) {
0848: Object parent = treePath.getLastPathComponent();
0849: Graph graph = model.getGraph(treePath);
0850:
0851: if (graph != null) {
0852: Set<VertexItem> items = new HashSet<VertexItem>();
0853:
0854: for (int i = graph.getVertexCount() - 1; i >= 0; i--) {
0855: Vertex vertex = graph.getVertex(i);
0856: if (!(vertex instanceof Constant)) {
0857: for (int j = vertex.getItemCount() - 1; j >= 0; j--) {
0858: VertexItem item = vertex.getItem(j);
0859: if (canConnect(model, treePath, treeSourcePin,
0860: item)) {
0861: items.add(item);
0862: }
0863: }
0864: }
0865: }
0866:
0867: if (!items.isEmpty()) {
0868: result.put(treePath, items);
0869: }
0870:
0871: items = null;
0872: }
0873:
0874: if (!model.isLeaf(parent) && model.searchGraphsInside(treePath)) {
0875: for (int i = model.getChildCount(parent) - 1; i >= 0; i--) {
0876: Object child = model.getChild(parent, i);
0877: findTargetVertexItems(treeSourcePin, model,
0878: new MapperTreePath(treePath, child), result);
0879: }
0880: }
0881: }
0882:
0883: private void findTargetVertexItems(Vertex sourceVertex,
0884: MapperModel model, TreePath treePath,
0885: Set<VertexItem> vertexItems) {
0886: Graph graph = model.getGraph(treePath);
0887:
0888: if (graph != null) {
0889: for (int i = graph.getVertexCount() - 1; i >= 0; i--) {
0890: Vertex vertex = graph.getVertex(i);
0891: if (!(vertex instanceof Constant)) {
0892: for (int j = vertex.getItemCount() - 1; j >= 0; j--) {
0893: VertexItem item = vertex.getItem(j);
0894: if (canConnect(model, treePath, sourceVertex,
0895: item)) {
0896: vertexItems.add(item);
0897: }
0898: }
0899: }
0900: }
0901: }
0902: }
0903:
0904: private boolean canConnect(MapperModel model, TreePath treePath,
0905: SourcePin sourcePin, TargetPin targetPin) {
0906: boolean canConnect = (isOutgoing()) ? canConnectOutgoing(
0907: treePath, targetPin) : canConnectIngoing(treePath,
0908: sourcePin);
0909:
0910: if (canConnect && checkCyrcle(sourcePin, targetPin)) {
0911: canConnect = false;
0912: }
0913:
0914: return (canConnect) ? model.canConnect(treePath, sourcePin,
0915: targetPin, oldTreePath, oldLink) : false;
0916: }
0917:
0918: private boolean canConnectOutgoing(TreePath treePath,
0919: TargetPin targetPin) {
0920: if (targetPin instanceof VertexItem) {
0921: VertexItem item = (VertexItem) targetPin;
0922:
0923: Link link = item.getIngoingLink();
0924:
0925: if (link == null)
0926: return true;
0927:
0928: return (link == oldLink)
0929: && Utils.equal(treePath, oldTreePath);
0930: }
0931:
0932: Graph graph = (Graph) targetPin;
0933:
0934: if (oldLink != null) {
0935: return oldLink.getTarget() == graph
0936: && Utils.equal(oldTreePath, treePath);
0937: }
0938:
0939: return !graph.hasOutgoingLinks();
0940: }
0941:
0942: private boolean canConnectIngoing(TreePath treePath,
0943: SourcePin sourcePin) {
0944: if (sourcePin instanceof Vertex) {
0945: Vertex vertex = (Vertex) sourcePin;
0946:
0947: Link link = vertex.getOutgoingLink();
0948:
0949: if (link == null)
0950: return true;
0951:
0952: return (link == oldLink)
0953: && Utils.equal(treePath, oldTreePath);
0954: }
0955:
0956: return true;
0957: }
0958:
0959: private static class LinkTransferable implements Transferable {
0960: private Long uid;
0961:
0962: public LinkTransferable(long uid) {
0963: this .uid = new Long(uid);
0964: }
0965:
0966: public DataFlavor[] getTransferDataFlavors() {
0967: return new DataFlavor[] { LINK_DATA_FLAVOR };
0968: }
0969:
0970: public boolean isDataFlavorSupported(DataFlavor flavor) {
0971: return flavor == LINK_DATA_FLAVOR;
0972: }
0973:
0974: public Object getTransferData(DataFlavor flavor)
0975: throws UnsupportedFlavorException, IOException {
0976: if (flavor == LINK_DATA_FLAVOR)
0977: return uid;
0978: throw new UnsupportedFlavorException(flavor);
0979: }
0980: }
0981:
0982: private boolean checkCyrcle(SourcePin sourcePin, TargetPin targetPin) {
0983: if (sourcePin instanceof Vertex
0984: && targetPin instanceof VertexItem) {
0985: Set<Vertex> visited = new HashSet<Vertex>();
0986: visited.add(((VertexItem) targetPin).getVertex());
0987: return checkCyrcle((Vertex) sourcePin, visited);
0988: }
0989:
0990: return false;
0991: }
0992:
0993: private boolean checkCyrcle(Vertex current, Set<Vertex> visited) {
0994: if (visited.contains(current))
0995: return true;
0996:
0997: visited.add(current);
0998:
0999: for (int i = current.getItemCount() - 1; i >= 0; i--) {
1000: VertexItem item = current.getItem(i);
1001: Link link = item.getIngoingLink();
1002:
1003: if (link != null && link != oldLink) {
1004: SourcePin sourcePin = link.getSource();
1005: if (sourcePin instanceof Vertex) {
1006: if (checkCyrcle((Vertex) sourcePin, visited)) {
1007: return true;
1008: }
1009: }
1010: }
1011: }
1012:
1013: visited.remove(current);
1014:
1015: return false;
1016: }
1017:
1018: private static final DataFlavor LINK_DATA_FLAVOR = new DataFlavor(
1019: LinkTransferable.class, "MapperLinkToolUID");
1020:
1021: private static synchronized long createUID() {
1022: return UID++;
1023: }
1024:
1025: private static long UID = 0;
1026: }
|