0001: /*
0002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
0003: *
0004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
0005: *
0006: * The contents of this file are subject to the terms of either the GNU
0007: * General Public License Version 2 only ("GPL") or the Common
0008: * Development and Distribution License("CDDL") (collectively, the
0009: * "License"). You may not use this file except in compliance with the
0010: * License. You can obtain a copy of the License at
0011: * http://www.netbeans.org/cddl-gplv2.html
0012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
0013: * specific language governing permissions and limitations under the
0014: * License. When distributing the software, include this License Header
0015: * Notice in each file and include the License file at
0016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
0017: * particular file as subject to the "Classpath" exception as provided
0018: * by Sun in the GPL Version 2 section of the License file that
0019: * accompanied this code. If applicable, add the following below the
0020: * License Header, with the fields enclosed by brackets [] replaced by
0021: * your own identifying information:
0022: * "Portions Copyrighted [year] [name of copyright owner]"
0023: *
0024: * Contributor(s):
0025: *
0026: * The Original Software is NetBeans. The Initial Developer of the Original
0027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
0028: * Microsystems, Inc. All Rights Reserved.
0029: *
0030: * If you wish your version of this file to be governed by only the CDDL
0031: * or only the GPL Version 2, indicate your decision by adding
0032: * "[Contributor] elects to include this software in this distribution
0033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
0034: * single choice of license, a recipient has the option to distribute
0035: * your version of this file under either the CDDL, the GPL Version 2 or
0036: * to extend the choice of license to its licensees as provided above.
0037: * However, if you add GPL Version 2 code and therefore, elected the GPL
0038: * Version 2 license, then the option applies only if the new code is
0039: * made subject to such option by the copyright holder.
0040: */
0041: package org.netbeans.modules.sql.framework.ui.graph.impl;
0042:
0043: import java.awt.Color;
0044: import java.awt.Graphics2D;
0045: import java.awt.Point;
0046: import java.awt.datatransfer.DataFlavor;
0047: import java.awt.datatransfer.Transferable;
0048: import java.awt.dnd.DnDConstants;
0049: import java.awt.dnd.DropTargetDragEvent;
0050: import java.awt.event.KeyEvent;
0051: import java.awt.geom.Rectangle2D;
0052: import java.awt.print.PageFormat;
0053: import java.util.ArrayList;
0054: import java.util.Collection;
0055: import java.util.Iterator;
0056: import java.util.List;
0057:
0058: import javax.swing.Action;
0059: import javax.swing.JMenuItem;
0060: import javax.swing.JOptionPane;
0061: import javax.swing.JPopupMenu;
0062: import javax.swing.KeyStroke;
0063:
0064: import org.netbeans.modules.sql.framework.model.SQLObject;
0065: import org.netbeans.modules.sql.framework.ui.graph.IGraphController;
0066: import org.netbeans.modules.sql.framework.ui.graph.IGraphLink;
0067: import org.netbeans.modules.sql.framework.ui.graph.IGraphNode;
0068: import org.netbeans.modules.sql.framework.ui.graph.IGraphPort;
0069: import org.netbeans.modules.sql.framework.ui.graph.IGraphView;
0070: import org.netbeans.modules.sql.framework.ui.graph.IHighlightable;
0071: import org.netbeans.modules.sql.framework.ui.graph.IOperatorXmlInfo;
0072: import org.netbeans.modules.sql.framework.ui.graph.IToolBar;
0073: import org.netbeans.modules.sql.framework.ui.graph.actions.GraphActionDelegator;
0074: import org.netbeans.modules.sql.framework.ui.utils.UIUtil;
0075: import org.openide.DialogDisplayer;
0076: import org.openide.NotifyDescriptor;
0077:
0078: import com.nwoods.jgo.JGoDocument;
0079: import com.nwoods.jgo.JGoLink;
0080: import com.nwoods.jgo.JGoListPosition;
0081: import com.nwoods.jgo.JGoObject;
0082: import com.nwoods.jgo.JGoPort;
0083: import com.nwoods.jgo.JGoSelection;
0084: import com.nwoods.jgo.JGoView;
0085: import com.nwoods.jgo.layout.JGoLayeredDigraphAutoLayout;
0086:
0087: import net.java.hulp.i18n.Logger;
0088: import org.netbeans.modules.etl.logger.Localizer;
0089: import org.netbeans.modules.etl.logger.LogUtil;
0090: import org.netbeans.modules.etl.ui.ETLDataObject;
0091:
0092: import org.netbeans.modules.sql.framework.ui.view.BasicTopView;
0093:
0094: /**
0095: * Extension of JGoView to implement IGraphView interface.
0096: *
0097: * @author Ritesh Adval
0098: * @author Jonathan Giron
0099: * @version $Revision$
0100: */
0101: public abstract class GraphView extends JGoView implements IGraphView {
0102:
0103: private static final int STANDARD_SCALE = 1;
0104: private static final int VIEW_SCALE = 2;
0105: private static final int PAGE_SCALE = 3;
0106: private static transient final Logger mLogger = LogUtil
0107: .getLogger(GraphView.class.getName());
0108: private static transient final Localizer mLoc = Localizer.get();
0109: private static final String NETBEANS_DBTABLE_MIMETYPE = "application/x-java-netbeans-dbexplorer-table;class=org.netbeans.api.db.explorer.DatabaseMetaDataTransfer$Table";
0110: protected static DataFlavor[] mDataFlavorArray = new DataFlavor[2];
0111: private IGraphController graphController;
0112: private JGoLayeredDigraphAutoLayout layout;
0113: private Object graphViewContainer;
0114: private Object graphModel;
0115: private ETLDataObject mObj;
0116: private Object graphFactory;
0117: private IToolBar toolBar;
0118: private List graphActions;
0119: protected JPopupMenu popUpMenu;
0120: private int printScale = STANDARD_SCALE;
0121: protected Point mousePoint = null;
0122: private IOperatorXmlInfo opXmlInfo = null;
0123:
0124: // current object under mouse
0125: private static JGoObject currentObj = null;
0126: public static JGoObject selectedObject = null;
0127: private BirdsEyeView satelliteView;
0128:
0129: static {
0130: try {
0131: mDataFlavorArray[0] = new DataFlavor(
0132: DataFlavor.javaJVMLocalObjectMimeType);
0133:
0134: mDataFlavorArray[1] = new DataFlavor(
0135: NETBEANS_DBTABLE_MIMETYPE);
0136: } catch (ClassNotFoundException ex) {
0137: ex.printStackTrace();
0138: }
0139: }
0140:
0141: /** Creates a new instance of BasicGraphView */
0142: public GraphView() {
0143: setDropEnabled(true);
0144: //set default primary and secondary selection colors
0145: resetSelectionColors();
0146: satelliteView = new BirdsEyeView();
0147: //set GraphDocument
0148: this .setDocument(new GraphDocument());
0149: setObserved(this );
0150: }
0151:
0152: /**
0153: * computeAcceptableDrop
0154: *
0155: * @param e - DropTargetDragEvent
0156: * @return - true/false
0157: */
0158: @Override
0159: public int computeAcceptableDrop(DropTargetDragEvent e) {
0160: return DnDConstants.ACTION_COPY_OR_MOVE;
0161: }
0162:
0163: /**
0164: * isDropFlavorAcceptable
0165: *
0166: * @param e - DropTargetDragEvent
0167: * @return - true/false
0168: */
0169: @Override
0170: public boolean isDropFlavorAcceptable(DropTargetDragEvent e) {
0171: for (int i = 0; i < mDataFlavorArray.length; i++) {
0172: if (e.isDataFlavorSupported(mDataFlavorArray[i])) {
0173: return true;
0174: }
0175: }
0176:
0177: return false;
0178: }
0179:
0180: /**
0181: * Drop
0182: *
0183: * @param e - DropTargetDropEvent
0184: */
0185: @Override
0186: // TODO: We can't handle application by exception...
0187: public void drop(java.awt.dnd.DropTargetDropEvent e) {
0188: try {
0189: Point viewCoord = e.getLocation();
0190: Point docCoord = viewToDocCoords(viewCoord);
0191: //sets location as doc coordinates
0192: e.getLocation().setLocation(docCoord);
0193:
0194: if (e.isDataFlavorSupported(mDataFlavorArray[0])) {
0195: Transferable tr = e.getTransferable();
0196:
0197: /*if (!(tr.getTransferData(mDataFlavorArray[0]) instanceof IOperatorXmlInfo)) {
0198: if (graphController != null) {
0199: graphController.handleDrop(e);
0200: }
0201:
0202: return;
0203: }*/
0204:
0205: IOperatorXmlInfo xmlInfo = null;
0206: try {
0207: xmlInfo = (IOperatorXmlInfo) tr
0208: .getTransferData(mDataFlavorArray[0]);
0209: } catch (Exception ex) {
0210: // FIXME: There should be a better way to do this.
0211: // Also Fix PaletteSupport
0212: xmlInfo = getXMLInfo();
0213: }
0214:
0215: if (!(xmlInfo instanceof IOperatorXmlInfo)) {
0216: if (graphController != null) {
0217: graphController.handleDrop(e);
0218: }
0219: return;
0220: }
0221:
0222: // IOperatorXmlInfo xmlInfo = (IOperatorXmlInfo) tr.getTransferData(mDataFlavorArray[0]);
0223:
0224: if (graphController != null) {
0225: graphController.handleNodeAdded(xmlInfo, docCoord);
0226: } else {
0227: addXmlInfoNode(xmlInfo, docCoord);
0228: }
0229:
0230: // Must wait to accept drop until all other execution paths that might
0231: // throw an exception have been executed.
0232: e.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
0233: } else if (graphController != null) {
0234: graphController.handleDrop(e);
0235: } else {
0236: e.rejectDrop();
0237: }
0238:
0239: // //also call graph controller' handle drop
0240: // if (graphController != null) {
0241: // graphController.handleDrop(e);
0242: // }
0243: } catch (Exception ex) {
0244: e.rejectDrop();
0245: ex.printStackTrace();
0246: StringBuilder msgBuf = new StringBuilder(
0247: "Cannot create node in the canvas");
0248: if (ex.getMessage() != null) {
0249: msgBuf.append(": ").append(ex.getMessage());
0250: } else {
0251: msgBuf.append(".");
0252: }
0253:
0254: DialogDisplayer.getDefault().notify(
0255: new NotifyDescriptor.Message(msgBuf.toString(),
0256: NotifyDescriptor.ERROR_MESSAGE));
0257: }
0258: }
0259:
0260: /**
0261: * @see com.nwoods.jgo.JGoView#doMouseDown
0262: */
0263: @Override
0264: public boolean doMouseDown(int modifiers, Point dc, Point vc) {
0265: mousePoint = dc;
0266: return super .doMouseDown(modifiers, dc, vc);
0267: }
0268:
0269: /**
0270: * Handles key event
0271: *
0272: * @param evt Description of the Parameter
0273: */
0274: @Override
0275: public void onKeyEvent(KeyEvent evt) {
0276: int t = evt.getKeyCode();
0277:
0278: if (t == KeyEvent.VK_DELETE) {
0279: if (getDocument().isModifiable()) {
0280: deleteNodesAndLinks();
0281: }
0282: } else if (t == KeyEvent.VK_A && evt.isControlDown()) {
0283: this .selectAll();
0284: }
0285: }
0286:
0287: /**
0288: * Delete an object
0289: *
0290: * @param node node to be deleted
0291: */
0292: public void deleteNode(IGraphNode node) {
0293: //delete object
0294: deleteLinks(node);
0295: if (graphController != null) {
0296: graphController.handleNodeRemoved(node);
0297: }
0298: }
0299:
0300: private void deleteLinks(IGraphNode node) {
0301: List list = node.getAllLinks();
0302: deleteLinks(list);
0303: }
0304:
0305: /**
0306: * Delete a collection of links
0307: *
0308: * @param links - links
0309: */
0310: public void deleteLinks(Collection links) {
0311: Iterator it = links.iterator();
0312: while (it.hasNext()) {
0313: IGraphLink link = (IGraphLink) it.next();
0314: if (graphController != null && link != null) {
0315: graphController.handleLinkDeleted(link);
0316: }
0317: }
0318: }
0319:
0320: private void deleteNodesAndLinks() {
0321: //get all selected nodes
0322: Collection nodes = this .getSelectedNodes();
0323: //get all selected links
0324: Collection links = this .getSelectedLinks();
0325: //no nodes are selected but one or more link is selected by user
0326: if (nodes.size() == 0 && links.size() > 0) {
0327: String nbBundle = mLoc.t("PRSR001: Confirm Deletion");
0328: String nbBundle1 = mLoc
0329: .t("PRSR001: Do you want to delete 000?");
0330: String title = Localizer.parse(nbBundle);
0331: String msg = Localizer.parse(nbBundle1);
0332: msg = msg.replaceFirst("000", "All selected links");
0333:
0334: int option = UIUtil.showYesAllDialog(this , msg, title);
0335: if (option == JOptionPane.YES_OPTION) {
0336: this .deleteLinks(links);
0337: }
0338:
0339: return;
0340: }
0341: //some node and zero or more links area selected by user
0342: deleteNodesAndLinks(nodes, links);
0343: }
0344:
0345: private void deleteNodesAndLinks(Collection nodes, Collection links) {
0346: //keep a list of links which are getting deleted as a result of deleting a node
0347: ArrayList nodeDeletedLinks = new ArrayList();
0348: boolean delete = false;
0349: //now delete them
0350: Iterator it = nodes.iterator();
0351: while (it.hasNext()) {
0352: IGraphNode node = (IGraphNode) it.next();
0353: if (!node.isDeleteAllowed()) {
0354: continue;
0355: }
0356:
0357: //links.removeAll(node.getAllLinks());
0358: if (!delete) {
0359: String nbBundle = mLoc.t("PRSR001: Confirm Deletion");
0360: String nbBundle1 = mLoc
0361: .t("PRSR001: Do you want to delete 000?");
0362: String title = Localizer.parse(nbBundle);
0363: String msg = Localizer.parse(nbBundle1);
0364: SQLObject sqlObject = (SQLObject) node.getDataObject();
0365: if (nodes.size() > 1) {
0366: msg = msg.replaceFirst("000",
0367: "All selected components");
0368: } else {
0369: msg = msg.replaceFirst("000", sqlObject
0370: .getDisplayName());
0371: }
0372: int option = UIUtil.showYesAllDialog(this , msg, title);
0373: if (option == JOptionPane.YES_OPTION) {
0374: delete = true;
0375: } else if (option == JOptionPane.NO_OPTION) {
0376: break;
0377: }
0378: }
0379: if (delete) {
0380: //delete links associated with a given graph node, links associated with
0381: //a node may not have been selected by user but since we are deleting a
0382: //node we should delete the links associated with it
0383: deleteNodeLinks(node.getAllLinks(), nodeDeletedLinks);
0384: // deleteLinks(node);
0385: graphController.handleNodeRemoved(node);
0386: }
0387: }
0388:
0389: if (delete) {
0390: //now delete all selected links
0391: //remove the links which are already deleted as a result of deleting a node
0392: links.removeAll(nodeDeletedLinks);
0393: //now remove the links if any which are selected but their source and
0394: // destination nodes are not selected
0395: this .deleteLinks(links);
0396: }
0397:
0398: // Iterator it = links.iterator();
0399: // while (it.hasNext()) {
0400: // IGraphLink link = (IGraphLink) it.next();
0401: // graphController.handleLinkDeleted(link);
0402: // }
0403: }
0404:
0405: private void deleteNodeLinks(Collection nodeLinks,
0406: Collection deletedLinks) {
0407: Iterator it = nodeLinks.iterator();
0408: while (it.hasNext()) {
0409: IGraphLink link = (IGraphLink) it.next();
0410: //if link is not already deleted then delete it
0411: if (!deletedLinks.contains(link)) {
0412: //add link to node deleted link
0413: deletedLinks.add(link);
0414: graphController.handleLinkDeleted(link);
0415: }
0416: }
0417: }
0418:
0419: @Override
0420: public boolean doMouseMove(int modifiers, Point dc, Point vc) {
0421: super .doMouseMove(modifiers, dc, vc);
0422: //handle mouse event and delegate to child object under mouse point
0423: if (getState() != MouseStateCreateLinkFrom
0424: && getState() != MouseStateCreateLink
0425: && getState() != MouseStateDragBoxSelection) {
0426: doMouseHandling(modifiers, dc, vc);
0427: }
0428: return true;
0429: }
0430:
0431: private boolean doMouseHandling(int modifiers, Point dc, Point vc) {
0432: boolean returnStatus = false;
0433:
0434: // if we're over a port, start drawing a new link
0435: JGoObject obj = pickPort(dc);
0436:
0437: if (obj == null) {
0438: obj = pickDocObject(dc, false);
0439: }
0440:
0441: while (obj != null) {
0442: if (obj instanceof GraphPort
0443: && ((GraphPort) obj).doMouseEntered(modifiers, dc,
0444: vc, this )) {
0445: returnStatus = true;
0446: break;
0447: } else if (obj instanceof IHighlightable) {
0448: ((IHighlightable) obj).setHighlighted(true);
0449: returnStatus = true;
0450: break;
0451: } else {
0452: obj = obj.getParent();
0453: }
0454: }
0455:
0456: //fire mouseExisted event
0457: if (currentObj instanceof GraphPort && currentObj != null
0458: && currentObj != obj) {
0459: ((GraphPort) currentObj).doMouseExited(modifiers, dc, vc,
0460: this );
0461: } else if (currentObj instanceof IHighlightable
0462: && null != currentObj && obj != currentObj) {
0463: ((IHighlightable) currentObj).setHighlighted(false);
0464: }
0465:
0466: // this is the current obj where mouse has entered
0467: currentObj = obj;
0468:
0469: return returnStatus;
0470: }
0471:
0472: /**
0473: * Called to create a new link from the from port to the to port.
0474: *
0475: * @param from source JGoPort
0476: * @param to destination JGoPort
0477: */
0478: @Override
0479: public void newLink(JGoPort from, JGoPort to) {
0480: if (graphController != null) {
0481: graphController.handleLinkAdded((IGraphPort) from,
0482: (IGraphPort) to);
0483: } else {
0484: super .newLink(from, to);
0485: }
0486: }
0487:
0488: /**
0489: * Called when link creation fails.
0490: *
0491: * @param from source JGoPort
0492: * @param to destination JGoPort
0493: */
0494: @Override
0495: public void noNewLink(JGoPort from, JGoPort to) {
0496: }
0497:
0498: /**
0499: * Called when link reconnection fails.
0500: *
0501: * @param oldlink JGoLink to be reconnected
0502: * @param from source JGoPort
0503: * @param to destination JGoPort
0504: */
0505: @Override
0506: public void noReLink(JGoLink oldlink, JGoPort from, JGoPort to) {
0507: }
0508:
0509: /**
0510: * Adds a link from the given source port to the given destination port.
0511: *
0512: * @param from source IGraphPort
0513: * @param to destination IGraphPort
0514: */
0515: public void addLink(IGraphPort from, IGraphPort to) {
0516: GraphLink link = new GraphLink(from, to);
0517: this .getDocument().addObjectAtTail(link);
0518: }
0519:
0520: public void addLink(IGraphLink link) {
0521: this .getDocument().addObjectAtTail((JGoObject) link);
0522: }
0523:
0524: /**
0525: * Adds the given IGraphNode to the view.
0526: *
0527: * @param node new IGraphNode to add
0528: */
0529: public void addNode(IGraphNode node) {
0530: node.setGraphView(this );
0531:
0532: JGoObject obj = (JGoObject) node;
0533:
0534: if (obj.getLeft() == -1) {
0535: obj.setLeft(50);
0536: }
0537:
0538: if (obj.getTop() == -1) {
0539: obj.setTop(50);
0540: }
0541:
0542: //check for overlapping
0543: avoidOverlap(obj);
0544:
0545: JGoObject jgoObj = (JGoObject) node;
0546:
0547: //add this node to document
0548: this .getDocument().addObjectAtTail(jgoObj);
0549: satelliteView.getDocument().addObjectAtTail(jgoObj);
0550:
0551: //now select this node
0552: this .getSelection().selectObject(jgoObj);
0553:
0554: //and have focus in this view
0555: satelliteView.requestFocus();
0556: this .requestFocus();
0557: }
0558:
0559: /**
0560: * Creates and adds a new operator node at the given location, as specified by the
0561: * given operator descriptor.
0562: *
0563: * @param xmlInfo descriptor specifying operator configuration information
0564: * @param location Point at which to create new operator node
0565: * @return new IGraphNode representing operator in question
0566: */
0567: public IGraphNode addXmlInfoNode(IOperatorXmlInfo xmlInfo,
0568: Point location) {
0569: OperatorGraphNode graphNode = new OperatorGraphNode(xmlInfo);
0570: graphNode.setLocation(location);
0571: addNode(graphNode);
0572: return graphNode;
0573: }
0574:
0575: /**
0576: * Ensures given JGoObject does not overlap other JGoObjects in the view.
0577: *
0578: * @param guiInfo JGoObject whose positioning should not overlap other objects.
0579: */
0580: public void avoidOverlap(JGoObject guiInfo) {
0581: Point p = new Point(guiInfo.getLeft(), guiInfo.getTop());
0582: int width = guiInfo.getWidth();
0583: int height = guiInfo.getHeight();
0584: JGoSelection selection = this .getSelection();
0585: selection.clearSelection();
0586:
0587: JGoObject obj = null;
0588:
0589: Point tmpPoint = new Point(guiInfo.getLeft(), guiInfo.getTop());
0590: int selY = -1;
0591:
0592: int i = p.x;
0593:
0594: //scanning from topleft to topright
0595: while (i <= (p.x + width)) {
0596: i = i + 10;
0597: tmpPoint.setLocation(i, p.y);
0598: obj = getObjectInModel(tmpPoint, false);
0599: if (obj != null) {
0600: selection.extendSelection(obj);
0601: if (selY == -1 || selY > obj.getTop()) {
0602: selY = obj.getTop();
0603: }
0604: }
0605: }
0606:
0607: i = p.y;
0608: //scanning from topright to bottomright
0609: while (i <= (p.y + height)) {
0610: i = i + 10;
0611: tmpPoint.setLocation(p.x + width, p.y);
0612: obj = getObjectInModel(tmpPoint, true);
0613: if (obj != null) {
0614: selection.extendSelection(obj);
0615:
0616: if (selY == -1 || selY > obj.getTop()) {
0617: selY = obj.getTop();
0618: }
0619: }
0620: }
0621:
0622: i = p.x + width;
0623: //scanning from bottomright to bottomleft
0624: while (i >= p.x) {
0625: i = i - 10;
0626: tmpPoint.setLocation(i, p.y + height);
0627: obj = getObjectInModel(tmpPoint, true);
0628: if (obj != null) {
0629: selection.extendSelection(obj);
0630:
0631: if (selY == -1 || selY > obj.getTop()) {
0632: selY = obj.getTop();
0633: }
0634: }
0635: }
0636:
0637: i = p.y + height;
0638: //scanning from bottomleft to topleft
0639: while (i >= p.y) {
0640: i = i - 10;
0641: tmpPoint.setLocation(p.x, i);
0642: obj = getObjectInModel(tmpPoint, true);
0643: if (obj != null) {
0644: selection.extendSelection(obj);
0645:
0646: if (selY == -1 || selY > obj.getTop()) {
0647: selY = obj.getTop();
0648: }
0649: }
0650: }
0651:
0652: int ydiff = p.y - selY;
0653:
0654: int yOffset = 0;
0655: if (p.y > selY) {
0656: yOffset = height + ydiff;
0657: } else {
0658: yOffset = height - ydiff;
0659: }
0660:
0661: //now move the selection down
0662: if (!selection.isEmpty()) {
0663: JGoDocument jgoModel = this .getDocument();
0664: JGoListPosition pos = null;
0665: JGoObject jgoObj = null;
0666:
0667: for (pos = jgoModel.getFirstObjectPos(); pos != null; pos = jgoModel
0668: .getNextObjectPosAtTop(pos)) {
0669:
0670: jgoObj = jgoModel.getObjectAtPos(pos);
0671: int top = jgoObj.getTop();
0672: if (top > p.y) {
0673: selection.extendSelection(jgoObj);
0674: }
0675: }
0676:
0677: this .moveSelection(selection, -1, 0, yOffset + 10,
0678: JGoView.MouseStateSelection);
0679: selection.clearSelection();
0680: }
0681:
0682: }
0683:
0684: /**
0685: * Gets the canvas node, if any, at the given position
0686: *
0687: * @param loc point in canvas document
0688: * @param flag if true check only the objects which are selectable
0689: * @return the object, if any, found at given location
0690: */
0691: public JGoObject getObjectInModel(Point loc, boolean flag) {
0692: return this .pickDocObject(loc, flag);
0693: }
0694:
0695: /**
0696: * Removes the link, if any, between the given ports.
0697: *
0698: * @param from source IGraphPort of link to be removed
0699: * @param to destination IGraphPort of link to be removed
0700: */
0701: public void removeLink(IGraphPort from, IGraphPort to) {
0702: JGoDocument jgoModel = this .getDocument();
0703: JGoListPosition pos = null;
0704: JGoObject jgoObj = null;
0705:
0706: for (pos = jgoModel.getFirstObjectPos(); pos != null; pos = jgoModel
0707: .getNextObjectPos(pos)) {
0708:
0709: jgoObj = jgoModel.getObjectAtPos(pos);
0710: if (jgoObj instanceof GraphLink) {
0711: GraphLink link = (GraphLink) jgoObj;
0712: if (link.getFromGraphPort().equals(from)
0713: && link.getToGraphPort().equals(to)) {
0714: this .removeObject(link);
0715: }
0716: }
0717: }
0718: }
0719:
0720: /**
0721: * Removes the given IGraphNode from the view.
0722: *
0723: * @param node new IGraphNode to remove
0724: */
0725: public void removeNode(IGraphNode node) {
0726: this .getDocument().removeObject((JGoObject) node);
0727: }
0728:
0729: /**
0730: * Sets the graph controller of this view.
0731: *
0732: * @param controller new graph controller
0733: */
0734: public void setGraphController(IGraphController controller) {
0735: this .graphController = controller;
0736: }
0737:
0738: /**
0739: * Gets the graph controller of this view.
0740: *
0741: * @return current graph controller
0742: */
0743: public IGraphController getGraphController() {
0744: return this .graphController;
0745: }
0746:
0747: /**
0748: * Expands all graph objects in this view.
0749: */
0750: public void expandAll() {
0751: expandORCollapseAll(true);
0752: }
0753:
0754: /**
0755: * Collapses all graph objects in this view.
0756: */
0757: public void collapseAll() {
0758: expandORCollapseAll(false);
0759: }
0760:
0761: /**
0762: * autolayout all the graph objects
0763: */
0764: public void autoLayout() {
0765: layout = new JGoLayeredDigraphAutoLayout(this .getDocument());
0766: layout
0767: .setDirectionOption(JGoLayeredDigraphAutoLayout.LD_DIRECTION_RIGHT);
0768: layout.setColumnSpacing(20);
0769: layout.setLayerSpacing(20);
0770: layout.performLayout();
0771: }
0772:
0773: private void expandORCollapseAll(boolean expand) {
0774: JGoDocument jgoModel = this .getDocument();
0775: JGoListPosition pos = null;
0776: JGoObject jgoObj = null;
0777:
0778: for (pos = jgoModel.getFirstObjectPos(); pos != null; pos = jgoModel
0779: .getNextObjectPos(pos)) {
0780:
0781: jgoObj = jgoModel.getObjectAtPos(pos);
0782: if (!(jgoObj instanceof JGoLink)
0783: && jgoObj instanceof IGraphNode) {
0784: IGraphNode graphNode = (IGraphNode) jgoObj;
0785: graphNode.expand(expand);
0786: }
0787: }
0788: }
0789:
0790: /**
0791: * Retrieves a collection of currently selected links
0792: *
0793: * @return Collection of selected links in this view.
0794: */
0795: public Collection getSelectedLinks() {
0796: List list = new ArrayList();
0797: JGoSelection selection = this .getSelection();
0798: if (selection == null) {
0799: return list;
0800: }
0801:
0802: JGoObject obj = null;
0803: JGoListPosition pos = selection.getFirstObjectPos();
0804: while (pos != null) {
0805: obj = selection.getObjectAtPos(pos);
0806: if (obj instanceof IGraphLink) {
0807: list.add(obj);
0808: }
0809: pos = selection.getNextObjectPos(pos);
0810: }
0811:
0812: return list;
0813: }
0814:
0815: /**
0816: * Retrieves a collection of currently selected nodes
0817: *
0818: * @return Collection of selected nodes in this view.
0819: */
0820: protected Collection getSelectedNodes() {
0821: List list = new ArrayList();
0822: JGoSelection selection = this .getSelection();
0823: if (selection == null) {
0824: return list;
0825: }
0826:
0827: JGoObject obj = null;
0828: JGoListPosition pos = selection.getFirstObjectPos();
0829: while (pos != null) {
0830: obj = selection.getObjectAtPos(pos);
0831: if (obj instanceof IGraphNode) {
0832: list.add(obj);
0833: }
0834: pos = selection.getNextObjectPos(pos);
0835: }
0836:
0837: return list;
0838: }
0839:
0840: /**
0841: * Retrieves a collection of all links
0842: *
0843: * @return -
0844: */
0845: public Collection getAllGraphLinks() {
0846: List list = new ArrayList();
0847: JGoDocument document = this .getDocument();
0848: JGoObject obj = null;
0849: JGoListPosition pos = document.getFirstObjectPos();
0850: while (pos != null) {
0851: obj = document.getObjectAtPos(pos);
0852: if (obj instanceof IGraphLink) {
0853: list.add(obj);
0854: }
0855: pos = document.getNextObjectPos(pos);
0856: }
0857: return list;
0858:
0859: }
0860:
0861: /**
0862: * Reset selection colors
0863: */
0864: public void resetSelectionColors() {
0865: setDefaultPrimarySelectionColor(new Color(73, 117, 183));
0866: setDefaultSecondarySelectionColor(new Color(73, 117, 183));
0867:
0868: }
0869:
0870: /**
0871: * get graph view container which can manage this view
0872: *
0873: * @return graph view manager
0874: */
0875: public Object getGraphViewContainer() {
0876: return this .graphViewContainer;
0877: }
0878:
0879: /**
0880: * set the graph view container which this view can refer to
0881: *
0882: * @param mgr graph view manager
0883: */
0884: public void setGraphViewContainer(Object mgr) {
0885: this .graphViewContainer = mgr;
0886: }
0887:
0888: /**
0889: * Describe <code>getPrintScale</code> method here.
0890: *
0891: * @param g2 a <code>Graphics2D</code> value
0892: * @param pf a <code>PageFormat</code> value
0893: * @return a <code>double</code> value
0894: */
0895: @Override
0896: public double getPrintScale(Graphics2D g2, PageFormat pf) {
0897: switch (printScale) {
0898: case VIEW_SCALE:
0899: return getScale();
0900: case PAGE_SCALE:
0901: Rectangle2D.Double pageRect = getPrintPageRect(g2, pf);
0902: java.awt.Dimension docSize = getPrintDocumentSize();
0903: // make sure it doesn't get scaled too much! (especially if no objects in
0904: // document)
0905: docSize.width = Math.max(docSize.width, 50);
0906: docSize.height = Math.max(docSize.height, 50);
0907: double hratio = pageRect.width / docSize.width;
0908: double vratio = pageRect.height / docSize.height;
0909: return Math.min(hratio, vratio);
0910: default:
0911: return 1.0d;
0912: }
0913: }
0914:
0915: /**
0916: * Print the view
0917: */
0918: public void printView() {
0919: String option1 = "Print at standard scale";
0920: String option2 = "Print using view's currently selected scale";
0921: String option3 = "Scale to fit page";
0922: Object[] options = { option1, option2, option3 };
0923: Object selectedValue = JOptionPane.showInputDialog(this ,
0924: "Choose a print option", "Print Options",
0925: JOptionPane.INFORMATION_MESSAGE, null, options,
0926: options[0]);
0927: if (selectedValue != null) {
0928: if (selectedValue.equals(option2)) {
0929: this .printScale = VIEW_SCALE;
0930: } else if (selectedValue.equals(option3)) {
0931: this .printScale = PAGE_SCALE;
0932: } else {
0933: this .printScale = STANDARD_SCALE;
0934: }
0935: print();
0936: }
0937: }
0938:
0939: @Override
0940: public boolean doMouseUp(int modifiers, java.awt.Point dc,
0941: java.awt.Point vc) {
0942: selectedObject = getCurrentObject();
0943: if (getGraphViewContainer() instanceof BasicTopView) {
0944: BasicTopView editor = (BasicTopView) getGraphViewContainer();
0945: editor.showProperties(selectedObject);
0946: }
0947:
0948: resetSelectionColors();
0949: boolean mClick = super .doMouseUp(modifiers, dc, vc);
0950:
0951: if (this .pickDocObject(dc, false) != null) {
0952: return mClick;
0953: }
0954:
0955: //if popup menu is null the create it and populate it with actions
0956: //set on this graph view
0957: if (popUpMenu == null) {
0958: buildPopUpMenu();
0959: }
0960:
0961: int onmask = java.awt.event.InputEvent.BUTTON3_MASK;
0962:
0963: if ((modifiers & onmask) != 0 && popUpMenu != null) {
0964: //if element is not checked out then ask user to check it out before
0965: // modifiying it
0966:
0967: if (!canEdit()) {
0968: return false;
0969: }
0970:
0971: if (popUpMenu != null) {
0972: popUpMenu.show(this , vc.x, vc.y);
0973:
0974: return true;
0975: }
0976: }
0977:
0978: return false;
0979: }
0980:
0981: private void registerAccelerator(Action action) {
0982: Object actionName = action.getValue(Action.NAME);
0983: Action oldAction = getActionMap().get(actionName);
0984: if (oldAction == null) {
0985: getActionMap().put(actionName, action);
0986: }
0987:
0988: KeyStroke ks = (KeyStroke) action
0989: .getValue(Action.ACCELERATOR_KEY);
0990: getInputMap().put(ks, actionName);
0991: }
0992:
0993: private void buildPopUpMenu() {
0994: popUpMenu = new JPopupMenu();
0995:
0996: List actions = this .getGraphActions();
0997: if (actions == null) {
0998: return;
0999: }
1000:
1001: Iterator it = actions.iterator();
1002:
1003: while (it.hasNext()) {
1004: Action action = (Action) it.next();
1005: GraphActionDelegator gaDelegator = new GraphActionDelegator(
1006: this , action);
1007: if (action != null) {
1008: if (action.getValue(Action.ACCELERATOR_KEY) != null) {
1009: registerAccelerator(gaDelegator);
1010: JMenuItem mi = new JMenuItem(gaDelegator);
1011: popUpMenu.add(mi);
1012: } else {
1013: popUpMenu.add(gaDelegator);
1014: }
1015: } else {
1016: popUpMenu.addSeparator();
1017: }
1018: }
1019: }
1020:
1021: /**
1022: * set the graph model
1023: *
1024: * @param model graph model
1025: */
1026: public void setGraphModel(Object model) {
1027: this .graphModel = model;
1028: }
1029:
1030: /**
1031: * get graph model
1032: *
1033: * @return graph model
1034: */
1035: public Object getGraphModel() {
1036: return this .graphModel;
1037: }
1038:
1039: /**
1040: * get the graph actions that need to be shown in popup menu
1041: *
1042: * @return a list of GraphAction, null in list represents a seperator
1043: */
1044: public List getGraphActions() {
1045: return graphActions;
1046: }
1047:
1048: /**
1049: * set graph actions on this view
1050: *
1051: * @param actions list of GraphAction
1052: */
1053: public void setGraphActions(List actions) {
1054: this .graphActions = actions;
1055: }
1056:
1057: /**
1058: * can this graph be edited
1059: *
1060: * @return true if graph is edited
1061: */
1062: public boolean canEdit() {
1063: return true;
1064: }
1065:
1066: public Object getGraphFactory() {
1067: return this .graphFactory;
1068: }
1069:
1070: /**
1071: * set the graph factory which is used for creating nodes in this graph
1072: *
1073: * @param gFactory graph node factory
1074: */
1075: public void setGraphFactory(Object gFactory) {
1076: this .graphFactory = gFactory;
1077: }
1078:
1079: /**
1080: * get a action based on class name
1081: *
1082: * @param actionClass
1083: * @return action
1084: */
1085: public Action getAction(Class actionClass) {
1086: List actions = this .getGraphActions();
1087: if (actions == null) {
1088: return null;
1089: }
1090:
1091: Iterator it = actions.iterator();
1092:
1093: while (it.hasNext()) {
1094: Action act = (Action) it.next();
1095: if (act != null
1096: && act.getClass().getName().equals(
1097: actionClass.getName())) {
1098: return act;
1099: }
1100: }
1101:
1102: return null;
1103: }
1104:
1105: /**
1106: * set the toolbar
1107: *
1108: * @param tBar
1109: */
1110: public void setToolBar(IToolBar tBar) {
1111: this .toolBar = tBar;
1112: }
1113:
1114: /**
1115: * get the toolbar
1116: *
1117: * @return toolbar
1118: */
1119: public IToolBar getToolBar() {
1120: return this .toolBar;
1121: }
1122:
1123: /**
1124: * remove all the view and document objects
1125: */
1126: public void clearAll() {
1127: this .getDocument().deleteContents();
1128: JGoListPosition pos = null;
1129: JGoObject jgoObj = null;
1130:
1131: for (pos = getFirstObjectPos(); pos != null; pos = getNextObjectPos(pos)) {
1132:
1133: jgoObj = getObjectAtPos(pos);
1134: this .removeObject(jgoObj);
1135: }
1136: }
1137:
1138: public void setModifiable(boolean b) {
1139: this .getDocument().setModifiable(b);
1140: this .setKeyEnabled(b);
1141: this .setMouseEnabled(b);
1142: this .setDragDropEnabled(b);
1143: if (this .getToolBar() != null) {
1144: this .getToolBar().enableToolBar(b);
1145: }
1146: }
1147:
1148: /**
1149: * check if this graph view is modifiable
1150: *
1151: * @return modifiable
1152: */
1153: public boolean isModifiable() {
1154: return this .getDocument().isModifiable();
1155: }
1156:
1157: /**
1158: * get the canvas node which holds IDataObject
1159: *
1160: * @param obj IDataObject
1161: * @return -
1162: */
1163: public IGraphNode findGraphNode(Object obj) {
1164:
1165: JGoDocument jgoModel = this .getDocument();
1166: JGoListPosition pos = null;
1167: JGoObject jgoObj = null;
1168:
1169: for (pos = jgoModel.getFirstObjectPos(); pos != null; pos = jgoModel
1170: .getNextObjectPos(pos)) {
1171:
1172: jgoObj = jgoModel.getObjectAtPos(pos);
1173:
1174: if (!(jgoObj instanceof IGraphNode)) {
1175: continue;
1176: }
1177: IGraphNode canvasNode = (IGraphNode) jgoObj;
1178: if (canvasNode.getDataObject() == obj) {
1179: return canvasNode;
1180: }
1181: }
1182: return null;
1183: }
1184:
1185: public void highlightInvalidNode(Object dataObj, boolean createSel) {
1186:
1187: if (createSel) {
1188: resetSelectionColors();
1189: }
1190:
1191: JGoSelection sel = this .getSelection();
1192:
1193: JGoObject obj = (JGoObject) findGraphNode(dataObj);
1194: if (obj == null) {
1195: return;
1196: }
1197:
1198: if (createSel) {
1199: //set invalid node selection color
1200: setDefaultPrimarySelectionColor(Color.RED);
1201: setDefaultSecondarySelectionColor(Color.RED);
1202:
1203: sel.clearSelection();
1204: sel.selectObject(obj);
1205: } else {
1206: sel.extendSelection(obj);
1207: }
1208:
1209: this .scrollRectToVisible(obj.getBoundingRect());
1210: }
1211:
1212: public void clearSelection() {
1213: JGoSelection sel = this .getSelection();
1214: sel.clearSelection();
1215: }
1216:
1217: public void setXMLInfo(IOperatorXmlInfo xmlInfo) {
1218: this .opXmlInfo = xmlInfo;
1219: }
1220:
1221: public IOperatorXmlInfo getXMLInfo() {
1222: return opXmlInfo;
1223: }
1224:
1225: public void setSelectedObject(JGoObject obj) {
1226: GraphView.selectedObject = obj;
1227: }
1228:
1229: public JGoObject getSelectedObject() {
1230: return GraphView.selectedObject;
1231: }
1232:
1233: public void setObserved(JGoView observed) {
1234: satelliteView.setObserved(this );
1235: satelliteView.requestFocus();
1236: }
1237:
1238: public BirdsEyeView getSatelliteView() {
1239: return satelliteView;
1240: }
1241:
1242: public JGoView getObserved() {
1243: return satelliteView.getObserved();
1244: }
1245: }
|