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: package org.netbeans.modules.soa.mappercore;
0020:
0021: import java.awt.BasicStroke;
0022: import java.awt.Color;
0023: import java.awt.Cursor;
0024: import java.awt.Dimension;
0025: import java.awt.Point;
0026: import java.awt.Stroke;
0027: import java.awt.event.ActionEvent;
0028: import java.awt.event.KeyEvent;
0029: import java.util.ArrayList;
0030: import java.util.Comparator;
0031: import java.util.HashSet;
0032: import java.util.List;
0033: import java.util.Set;
0034: import javax.swing.AbstractAction;
0035: import javax.swing.ActionMap;
0036: import javax.swing.Icon;
0037: import javax.swing.InputMap;
0038: import javax.swing.JComponent;
0039: import javax.swing.JPanel;
0040: import javax.swing.JScrollPane;
0041: import javax.swing.JViewport;
0042: import javax.swing.KeyStroke;
0043: import javax.swing.UIManager;
0044: import javax.swing.event.ChangeEvent;
0045: import javax.swing.event.ChangeListener;
0046: import javax.swing.event.EventListenerList;
0047: import javax.swing.event.TreeExpansionEvent;
0048: import javax.swing.event.TreeExpansionListener;
0049: import javax.swing.event.TreeModelEvent;
0050: import javax.swing.event.TreeModelListener;
0051: import javax.swing.tree.DefaultTreeCellRenderer;
0052: import javax.swing.tree.TreeCellRenderer;
0053: import javax.swing.tree.TreeModel;
0054: import javax.swing.tree.TreePath;
0055: import org.netbeans.modules.soa.mappercore.event.MapperSelectionEvent;
0056: import org.netbeans.modules.soa.mappercore.event.MapperSelectionListener;
0057: import org.netbeans.modules.soa.mappercore.model.MapperModel;
0058: import org.netbeans.modules.soa.mappercore.utils.Utils;
0059: import org.netbeans.modules.soa.mappercore.graphics.VerticalGradient;
0060: import org.netbeans.modules.soa.mappercore.graphics.XRange;
0061: import org.netbeans.modules.soa.mappercore.model.Graph;
0062: import org.netbeans.modules.soa.mappercore.model.Link;
0063: import org.netbeans.modules.soa.mappercore.model.TreeSourcePin;
0064: import org.netbeans.modules.soa.mappercore.model.VertexItem;
0065: import org.openide.util.NbBundle;
0066:
0067: /**
0068: *
0069: * @author anjeleevich
0070: */
0071: public class Mapper extends JPanel {
0072:
0073: private MapperModel model;
0074: private MapperNode root;
0075: private TreeModelListener treeModelListener = new TreeModelListenerImpl();
0076: private MapperSelectionListener selectionListener;
0077: private int leftDividerPosition = -1;
0078: private int rightDividerPosition = -1;
0079: private JPanel leftDivider;
0080: private JPanel rightDivider;
0081: private LeftTree leftTree;
0082: private RightTree rightTree;
0083: private Canvas canvas;
0084: // L&F
0085: private int leftChildIndent;
0086: private int rightChildIndent;
0087: private Icon openIcon;
0088: private Icon closedIcon;
0089: private Icon leafIcon;
0090: private Icon expandedIcon;
0091: private Icon collapsedIcon;
0092: private Color treeLineColor;
0093: private Dimension preferredTreeSize = null;
0094: private XRange graphXRange = null;
0095: private boolean validNodes = false;
0096: private boolean repaintSceduled = false;
0097: private MapperContext context = new DefaultMapperContext();
0098: private LinkTool linkTool;
0099: private MoveTool moveTool;
0100: private EventListenerList listenersList = new EventListenerList();
0101: private SelectionModel selectionModel;
0102: private TreePath pathDndselect = null;
0103:
0104: /** Creates a new instance of RightTree */
0105: public Mapper(MapperModel model) {
0106: setLayout(new MapperLayout());
0107:
0108: selectionModel = new SelectionModel(this );
0109:
0110: leftTree = new LeftTree(this );
0111: rightTree = new RightTree(this );
0112: canvas = new Canvas(this );
0113:
0114: leftDivider = new MapperDivider();
0115: leftDivider.setCursor(Cursor
0116: .getPredefinedCursor(Cursor.W_RESIZE_CURSOR));
0117:
0118: rightDivider = new MapperDivider();
0119: rightDivider.setCursor(Cursor
0120: .getPredefinedCursor(Cursor.E_RESIZE_CURSOR));
0121:
0122: new MapperDividersController(this , leftDivider, rightDivider);
0123:
0124: add(leftTree.getView(), MapperLayout.LEFT_SCROLL);
0125: add(leftDivider, MapperLayout.LEFT_DIVIDER);
0126: add(canvas.getView(), MapperLayout.CENTER_SCROLL);
0127: add(rightDivider, MapperLayout.RIGHT_DIVIDER);
0128: add(rightTree.getView(), MapperLayout.RIGHT_SCROLL);
0129:
0130: new ScrollPaneYSyncronizer(canvas.getScrollPane(), rightTree
0131: .getScrollPane());
0132:
0133: linkTool = new LinkTool(this );
0134: moveTool = new MoveTool(this );
0135:
0136: setModel(model);
0137:
0138: selectionModel
0139: .addSelectionListener(new MapperSelectionListener() {
0140:
0141: public void mapperSelectionChanged(
0142: MapperSelectionEvent event) {
0143: repaint();
0144: }
0145: });
0146:
0147: InputMap iMap = getInputMap(WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
0148: ActionMap aMap = getActionMap();
0149:
0150: iMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_A,
0151: KeyEvent.CTRL_DOWN_MASK), "mapper-select-all-action");
0152: aMap.put("mapper-select-all-action", new AbstractAction() {
0153: public void actionPerformed(ActionEvent event) {
0154: SelectionModel selectionModel = getSelectionModel();
0155: TreePath selectedPath = selectionModel
0156: .getSelectedPath();
0157: if (selectedPath != null) {
0158: selectionModel.selectAll(selectedPath);
0159: }
0160: }
0161: });
0162:
0163: getAccessibleContext().setAccessibleName(
0164: NbBundle.getMessage(Mapper.class, "ACSN_Mapper")); // NOI18N
0165: getAccessibleContext().setAccessibleDescription(
0166: NbBundle.getMessage(Mapper.class, "ACSD_Mapper")); // NOI18N
0167: }
0168:
0169: public void addRightTreeExpansionListener(
0170: TreeExpansionListener listener) {
0171: listenersList.add(TreeExpansionListener.class, listener);
0172: }
0173:
0174: public void removeRightTreeExpansionListener(
0175: TreeExpansionListener listener) {
0176: listenersList.remove(TreeExpansionListener.class, listener);
0177: }
0178:
0179: public void addSelectionListener(MapperSelectionListener listener) {
0180: getSelectionModel().addSelectionListener(listener);
0181: }
0182:
0183: public void removeSelectionListener(MapperSelectionListener listener) {
0184: getSelectionModel().removeSelectionListener(listener);
0185: }
0186:
0187: public TreePath getSelectedDndPath() {
0188: return pathDndselect;
0189: }
0190:
0191: public SelectionModel getSelectionModel() {
0192: return selectionModel;
0193: }
0194:
0195: LinkTool getLinkTool() {
0196: return linkTool;
0197: }
0198:
0199: MoveTool getMoveTool() {
0200: return moveTool;
0201: }
0202:
0203: public MapperContext getContext() {
0204: return context;
0205: }
0206:
0207: public void setSelectedDndPath(TreePath path) {
0208: pathDndselect = path;
0209: }
0210:
0211: public void setContext(MapperContext context) {
0212: if (context == null) {
0213: context = new DefaultMapperContext();
0214: }
0215:
0216: if (this .context != context) {
0217: this .context = context;
0218:
0219: TreeCellRenderer oldCellRenderer = leftTree
0220: .getCellRenderer();
0221: leftTree.setCellRenderer(new DefaultTreeCellRenderer());
0222: leftTree.setCellRenderer(oldCellRenderer);
0223: leftTree.revalidate();
0224: leftTree.repaint();
0225:
0226: MapperNode root = getRoot();
0227:
0228: if (root != null) {
0229: root.invalidateTree();
0230: root.repaint();
0231: }
0232: }
0233: }
0234:
0235: public TreePath getSelected() {
0236: return getSelectionModel().getSelectedPath();
0237: }
0238:
0239: public TreePath getSelectedPath() {
0240: return getSelectionModel().getSelectedPath();
0241: }
0242:
0243: public void setSelected(TreePath treePath) {
0244: getSelectionModel().setSelected(treePath);
0245: }
0246:
0247: void resetRepaintSceduled() {
0248: repaintSceduled = false;
0249: }
0250:
0251: void setSelectedNode(MapperNode selectedNode) {
0252: setSelected(selectedNode.getTreePath());
0253: }
0254:
0255: public void setExpandedState(TreePath treePath, boolean state) {
0256: if (state) {
0257: MapperNode node = getNode(treePath, true);
0258: TreePath expandedTreePath = null;
0259: while (node != null) {
0260: if (!node.isLeaf() && node.isCollapsed()) {
0261: node.setExpanded(true);
0262: if (expandedTreePath == null) {
0263: expandedTreePath = node.getTreePath();
0264: }
0265: }
0266: node = node.getParent();
0267: }
0268:
0269: if (expandedTreePath != null) {
0270: fireNodeExpanded(expandedTreePath);
0271: }
0272: } else {
0273: MapperNode node = getNode(treePath, false);
0274: if (node != null && !node.isLeaf() && node.isExpanded()) {
0275: node.setCollapsed(true);
0276: fireNodeCollapsed(treePath);
0277: }
0278: }
0279: }
0280:
0281: public void setExpandedGraphState(TreePath treePath, boolean state) {
0282: if (model == null) {
0283: return;
0284: }
0285:
0286: Graph graph = model.getGraph(treePath);
0287:
0288: if (graph == null || graph.isEmpty()) {
0289: return;
0290: }
0291:
0292: if (state) {
0293: MapperNode node = getNode(treePath, true);
0294: node.setGraphExpanded(true);
0295: } else {
0296: MapperNode node = getNode(treePath, false);
0297: if (node != null) {
0298: node.setGraphExpanded(false);
0299: }
0300: }
0301: }
0302:
0303: private void fireNodeCollapsed(TreePath treePath) {
0304: if (treePath == null) {
0305: return;
0306: }
0307: TreeExpansionListener[] listeners = listenersList
0308: .getListeners(TreeExpansionListener.class);
0309: if (listeners != null && listeners.length > 0) {
0310: TreeExpansionEvent event = new TreeExpansionEvent(this ,
0311: treePath);
0312: for (TreeExpansionListener l : listeners) {
0313: l.treeCollapsed(event);
0314: }
0315: }
0316: }
0317:
0318: private void fireNodeExpanded(TreePath treePath) {
0319: if (treePath == null) {
0320: return;
0321: }
0322: TreeExpansionListener[] listeners = listenersList
0323: .getListeners(TreeExpansionListener.class);
0324: if (listeners != null && listeners.length > 0) {
0325: TreeExpansionEvent event = new TreeExpansionEvent(this ,
0326: treePath);
0327: for (TreeExpansionListener l : listeners) {
0328: l.treeExpanded(event);
0329: }
0330: }
0331: }
0332:
0333: void collapseNode(MapperNode node) {
0334: setExpandedState(node.getTreePath(), false);
0335: }
0336:
0337: void expandNode(MapperNode node) {
0338: setExpandedState(node.getTreePath(), true);
0339: }
0340:
0341: void switchCollapsedExpandedState(MapperNode node) {
0342: if (node.isLeaf()) {
0343: return;
0344: }
0345: if (node.isExpanded()) {
0346: collapseNode(node);
0347: } else {
0348: expandNode(node);
0349: }
0350: }
0351:
0352: public int getLeftDividerPosition() {
0353: return leftDividerPosition;
0354: }
0355:
0356: public int getRightDividerPosition() {
0357: return rightDividerPosition;
0358: }
0359:
0360: void setDividerPositions(int leftDividerPosition,
0361: int rightDividerPosition) {
0362: this .leftDividerPosition = leftDividerPosition;
0363: this .rightDividerPosition = rightDividerPosition;
0364: }
0365:
0366: public void setModel(MapperModel model) {
0367: MapperModel oldModel = this .model;
0368:
0369: TreeModel oldLeftTreeModel = (oldModel != null) ? leftTree
0370: .getModel() : null;
0371: TreeModel newLeftTreeModel = (model != null) ? model
0372: .getLeftTreeModel() : null;
0373:
0374: if (oldModel != model) {
0375: this .model = model;
0376:
0377: if (oldLeftTreeModel != newLeftTreeModel) {
0378: leftTree.setModel(newLeftTreeModel);
0379: }
0380:
0381: if (oldModel != null) {
0382: oldModel.removeTreeModelListener(treeModelListener);
0383: }
0384:
0385: if (model != null) {
0386: model.addTreeModelListener(treeModelListener);
0387: root = new MapperNode(this , null, model.getRoot());
0388: // root.getChildCount();
0389: } else {
0390: root = null;
0391: }
0392:
0393: invalidateNodes();
0394: repaintNodes();
0395:
0396: revalidate();
0397: repaint();
0398:
0399: firePropertyChange(MODEL_PROPERTY, oldModel, model);
0400: }
0401: }
0402:
0403: public MapperModel getModel() {
0404: return model;
0405: }
0406:
0407: MapperNode getRoot() {
0408: return root;
0409: }
0410:
0411: public LeftTree getLeftTree() {
0412: return leftTree;
0413: }
0414:
0415: public Canvas getCanvas() {
0416: return canvas;
0417: }
0418:
0419: public RightTree getRightTree() {
0420: return rightTree;
0421: }
0422:
0423: public void expandNonEmptyGraphs() {
0424: expandGraphs(Utils.getNonEmptyGraphs(getModel()));
0425: }
0426:
0427: public void expandGraphs(List<TreePath> treePathes) {
0428: if (treePathes == null) {
0429: return;
0430: }
0431:
0432: Set<TreePath> parentTreePathes = new HashSet<TreePath>();
0433: for (TreePath treePath : treePathes) {
0434: TreePath parentTreePath = treePath.getParentPath();
0435: if (parentTreePath != null) {
0436: parentTreePathes.add(parentTreePath);
0437: }
0438: }
0439:
0440: for (TreePath parentTreePath : parentTreePathes) {
0441: setExpandedState(parentTreePath, true);
0442: }
0443:
0444: for (TreePath treePath : treePathes) {
0445: setExpandedGraphState(treePath, true);
0446: }
0447: }
0448:
0449: public List<TreePath> getExpandedPathes() {
0450: List<TreePath> result = new ArrayList<TreePath>();
0451: MapperNode rootNode = getRoot();
0452:
0453: if (root != null) {
0454: collectExpandedPathes(rootNode, result);
0455: }
0456:
0457: return result;
0458: }
0459:
0460: private void collectExpandedPathes(MapperNode node,
0461: List<TreePath> result) {
0462: if (node.isLeaf())
0463: return;
0464:
0465: if (node.isExpanded()) {
0466: result.add(node.getTreePath());
0467: }
0468:
0469: if (node.isLoaded()) {
0470: for (int i = node.getChildCount() - 1; i >= 0; i--) {
0471: collectExpandedPathes(node.getChild(i), result);
0472: }
0473: }
0474: }
0475:
0476: public List<TreePath> getExpandedGraphsPathes() {
0477: List<TreePath> result = new ArrayList<TreePath>();
0478:
0479: MapperModel model = getModel();
0480: MapperNode rootNode = getRoot();
0481:
0482: if (model != null && root != null) {
0483: collectExpandedGraphsPathes(model, rootNode, result);
0484: }
0485:
0486: return result;
0487: }
0488:
0489: private void collectExpandedGraphsPathes(MapperModel model,
0490: MapperNode node, List<TreePath> result) {
0491: Graph graph = node.getGraph();
0492: if (graph != null && !graph.isEmpty() && node.isGraphExpanded()) {
0493: result.add(node.getTreePath());
0494: }
0495:
0496: if (node.isLeaf())
0497: return;
0498: if (!model.searchGraphsInside(node.getTreePath()))
0499: return;
0500:
0501: if (node.isLoaded()) {
0502: for (int i = node.getChildCount() - 1; i >= 0; i--) {
0503: collectExpandedGraphsPathes(model, node.getChild(i),
0504: result);
0505: }
0506: }
0507: }
0508:
0509: public void applyExpandedPathes(List<TreePath> rightTreePathes) {
0510: if (rightTreePathes == null || rightTreePathes.isEmpty())
0511: return;
0512:
0513: for (TreePath treePath : rightTreePathes) {
0514: MapperNode node = getNode(treePath, true);
0515: if (node != null && !node.isLeaf() && node.isCollapsed()) {
0516: node.setExpanded(true);
0517: fireNodeExpanded(treePath);
0518: }
0519: }
0520: }
0521:
0522: public void applyExpandedGraphsPathes(List<TreePath> rightTreePathes) {
0523: if (rightTreePathes == null || rightTreePathes.isEmpty())
0524: return;
0525:
0526: MapperModel model = getModel();
0527:
0528: if (model == null)
0529: return;
0530:
0531: for (TreePath treePath : rightTreePathes) {
0532: Graph graph = model.getGraph(treePath);
0533: if (graph != null && !graph.isEmpty()) {
0534: MapperNode node = getNode(treePath, true);
0535: if (node != null && node.isGraphCollapsed()) {
0536: node.setGraphExpanded(true);
0537: }
0538: }
0539: }
0540: }
0541:
0542: public void hideOtherPathes(int expandedLevel) {
0543: if (model == null)
0544: return;
0545: if (root == null)
0546: return;
0547:
0548: TreePath selectedPath = getSelectedPath();
0549: if (selectedPath == null)
0550: return;
0551:
0552: collapseAll(root, 0, expandedLevel, selectedPath);
0553: }
0554:
0555: public void collapseAll(int expandedLevel) {
0556: if (root == null)
0557: return;
0558: collapseAll(root, 0, expandedLevel, null);
0559: }
0560:
0561: private void collapseAll(MapperNode node, int level,
0562: int expandedLevel, TreePath skipPath) {
0563: TreePath treePath = node.getTreePath();
0564:
0565: boolean skipCollapse = false;
0566: boolean skipCollapseGraph = false;
0567:
0568: if (skipPath != null) {
0569: skipCollapseGraph = treePath.equals(skipPath);
0570: skipCollapse = treePath.isDescendant(skipPath)
0571: && !skipCollapseGraph;
0572: }
0573:
0574: if (!node.isLeaf()) {
0575: if (level >= expandedLevel && node.isExpanded()
0576: && !skipCollapse) {
0577: setExpandedState(treePath, false);
0578: }
0579:
0580: if (node.isLoaded()) {
0581: for (int i = node.getChildCount() - 1; i >= 0; i--) {
0582: collapseAll(node.getChild(i), level + 1,
0583: expandedLevel, skipPath);
0584: }
0585: }
0586: }
0587:
0588: Graph graph = node.getGraph();
0589: if (graph != null && !skipCollapseGraph
0590: && node.isGraphExpanded()) {
0591: setExpandedGraphState(treePath, false);
0592: }
0593: }
0594:
0595: public RightTreeCellRenderer getRightTreeCellRenderer() {
0596: return rightTree.getTreeCellRenderer();
0597: }
0598:
0599: public TreePath getRightTreePathForLink(Link link) {
0600: return getRightTreePathForLink(link, getRoot().getTreePath());
0601: }
0602:
0603: private TreePath getRightTreePathForLink(Link link,
0604: TreePath initialTreePath) {
0605: if (link == null || initialTreePath == null)
0606: return null;
0607:
0608: MapperNode node = getNode(initialTreePath, true);
0609:
0610: if (link.getGraph() == node.getGraph()) {
0611: return initialTreePath;
0612: }
0613:
0614: for (int i = 0; i < node.getChildCount(); i++) {
0615: MapperNode childNode = node.getChild(i);
0616: if (childNode.isLeaf()) {
0617: if (link.getGraph() == childNode.getGraph()) {
0618: return childNode.getTreePath();
0619: }
0620: } else {
0621: if (getRightTreePathForLink(link, childNode
0622: .getTreePath()) != null) {
0623: return getRightTreePathForLink(link, childNode
0624: .getTreePath());
0625: }
0626: }
0627: }
0628: return null;
0629: }
0630:
0631: public Link getPrevIngoingLink(Link link) {
0632: Set<Graph> graphs = canvas.getMapper().getRoot()
0633: .getChildGraphs();
0634:
0635: List<Link> ingoingLinks = new ArrayList<Link>();
0636: for (Graph g : graphs) {
0637: ingoingLinks.addAll(g.getIngoingLinks());
0638: }
0639: if (!ingoingLinks.contains(link))
0640: return null;
0641:
0642: TreePath leftPath;
0643: leftPath = ((TreeSourcePin) link.getSource()).getTreePath();
0644: int currentRow = getLeftTree().getParentsRowForPath(leftPath);
0645: Graph currentGraph = null;
0646: if (link.getTarget() instanceof Graph)
0647: currentGraph = (Graph) link.getTarget();
0648: if (link.getTarget() instanceof VertexItem)
0649: currentGraph = ((VertexItem) link.getTarget()).getVertex()
0650: .getGraph();
0651:
0652: List<Link> linksCandidateRow = new ArrayList<Link>();
0653: List<Link> linksCandidateGraph = new ArrayList<Link>();
0654: // find links with rows == currentRow
0655: for (Link l : ingoingLinks) {
0656: //if (l != link) {
0657: leftPath = ((TreeSourcePin) l.getSource()).getTreePath();
0658: int row = getLeftTree().getParentsRowForPath(leftPath);
0659: if (row == currentRow) {
0660: linksCandidateRow.add(l);
0661: }
0662: // }
0663: }
0664: // if (linksCandidateRow.size() == 1) {
0665: // return linksCandidateRow.get(0);
0666: // }
0667: if (linksCandidateRow.size() > 1) {
0668: // find prevLinks in own Row with nearest Graph
0669: linksCandidateGraph.clear();
0670: Graph maxGraph = null;
0671: Graph graph = null;
0672: for (Link l : linksCandidateRow) {
0673: if (l.getTarget() instanceof Graph)
0674: graph = (Graph) l.getTarget();
0675: if (l.getTarget() instanceof VertexItem)
0676: graph = ((VertexItem) l.getTarget()).getVertex()
0677: .getGraph();
0678: // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
0679: // poisk naibolshego grapha menshe tecuahego v!!!!!!!!!!!! perepisat
0680: if (compare(currentGraph, graph, getRoot()
0681: .getTreePath()) >= 0) {
0682: if (maxGraph == null) {
0683: maxGraph = graph;
0684: linksCandidateGraph.add(l);
0685: } else {
0686: if (compare(maxGraph, graph, getRoot()
0687: .getTreePath()) < 0) {
0688: linksCandidateGraph.clear();
0689: maxGraph = graph;
0690: linksCandidateGraph.add(l);
0691: }
0692: if (compare(maxGraph, graph, getRoot()
0693: .getTreePath()) == 0) {
0694: linksCandidateGraph.add(l);
0695: }
0696: }
0697: }
0698: }
0699: // find links in own Graph
0700: if (linksCandidateGraph.size() == 1) {
0701: return linksCandidateGraph.get(0);
0702: }
0703: if (linksCandidateGraph.size() > 1) {
0704: // find prevLink in one graph
0705: if (linksCandidateGraph.contains(link)) {
0706: Link prevLink = maxGraph.getPrevLink(link,
0707: linksCandidateGraph);
0708: if (prevLink != null)
0709: return prevLink;
0710: if (maxGraph.getPrevLink(link) == null) {
0711: // find prevLinks in own Row with nearest Graph
0712: linksCandidateGraph.clear();
0713: maxGraph = null;
0714: graph = null;
0715: for (Link l : linksCandidateRow) {
0716: if (l.getTarget() instanceof Graph)
0717: graph = (Graph) l.getTarget();
0718: if (l.getTarget() instanceof VertexItem)
0719: graph = ((VertexItem) l.getTarget())
0720: .getVertex().getGraph();
0721: // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
0722: // poisk naibolshego grapha menshe tecuahego v!!!!!!!!!!!! perepisat
0723: if (compare(currentGraph, graph, getRoot()
0724: .getTreePath()) > 0) {
0725: if (maxGraph == null) {
0726: maxGraph = graph;
0727: linksCandidateGraph.add(l);
0728: } else {
0729: if (compare(maxGraph, graph,
0730: getRoot().getTreePath()) < 0) {
0731: linksCandidateGraph.clear();
0732: maxGraph = graph;
0733: linksCandidateGraph.add(l);
0734: }
0735: if (compare(maxGraph, graph,
0736: getRoot().getTreePath()) == 0) {
0737: linksCandidateGraph.add(l);
0738: }
0739: }
0740: }
0741: }
0742: if (maxGraph == null)
0743: return null;
0744: prevLink = maxGraph.getPrevLink(null,
0745: linksCandidateGraph);
0746: return prevLink;
0747: }
0748: } else {
0749: Link prevLink = maxGraph.getPrevLink(null,
0750: linksCandidateGraph);
0751: if (prevLink != null)
0752: return prevLink;
0753: }
0754: }
0755: }
0756: //find links with nearest Row < currentRow
0757: linksCandidateRow.clear();
0758: int maxRow = 0;
0759: for (Link l : ingoingLinks) {
0760: leftPath = ((TreeSourcePin) l.getSource()).getTreePath();
0761: int row = getLeftTree().getParentsRowForPath(leftPath);
0762: if (row < currentRow && row > maxRow) {
0763: linksCandidateRow.clear();
0764: maxRow = row;
0765: linksCandidateRow.add(l);
0766: }
0767: if (row < currentRow && row == maxRow) {
0768: linksCandidateRow.add(l);
0769: }
0770: }
0771: if (maxRow == 0) {
0772: return null;
0773: }
0774: if (linksCandidateRow.size() == 1) {
0775: return linksCandidateRow.get(0);
0776: }
0777: // find prevLinks in own Row with nearest Graph
0778: linksCandidateGraph.clear();
0779: Graph maxGraph = null;
0780: Graph graph = null;
0781: for (Link l : linksCandidateRow) {
0782: if (l.getTarget() instanceof Graph)
0783: graph = (Graph) l.getTarget();
0784: if (l.getTarget() instanceof VertexItem)
0785: graph = ((VertexItem) l.getTarget()).getVertex()
0786: .getGraph();
0787: // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
0788: // poisk naibolshego grapha menshe tecuahego v!!!!!!!!!!!! perepisat
0789: if (compare(currentGraph, graph, getRoot().getTreePath()) >= 0) {
0790: if (maxGraph == null) {
0791: maxGraph = graph;
0792: linksCandidateGraph.add(l);
0793: } else {
0794: if (compare(maxGraph, graph, getRoot()
0795: .getTreePath()) < 0) {
0796: linksCandidateGraph.clear();
0797: maxGraph = graph;
0798: linksCandidateGraph.add(l);
0799: }
0800: if (compare(maxGraph, graph, getRoot()
0801: .getTreePath()) == 0) {
0802: linksCandidateGraph.add(l);
0803: }
0804: }
0805: }
0806: }
0807: if (linksCandidateGraph.size() == 1) {
0808: return linksCandidateGraph.get(0);
0809: }
0810: if (linksCandidateGraph.size() > 1) {
0811: // find prevLink in one graph
0812: if (linksCandidateGraph.contains(link)) {
0813: Link prevLink = maxGraph.getPrevLink(link,
0814: linksCandidateGraph);
0815: if (prevLink != null)
0816: return prevLink;
0817:
0818: prevLink = maxGraph.getPrevLink(link);
0819: return prevLink;
0820: } else {
0821: return maxGraph.getPrevLink(null, linksCandidateGraph);
0822: }
0823: }
0824: return null;
0825: }
0826:
0827: public Link getNextOutgoingLink(Link link) {
0828: return null;
0829: }
0830:
0831: int getTextHeight() {
0832: return getFontMetrics(getFont()).getHeight();
0833: }
0834:
0835: int getTextWidth(String string) {
0836: return getFontMetrics(getFont()).stringWidth(string);
0837: }
0838:
0839: int getStepSize() {
0840: return Math.max((getTextHeight() + 2) / 2 + 1, 9);
0841: }
0842:
0843: MapperNode getNode(TreePath treePath, boolean load) {
0844: return getNode(treePath.getPath(), load);
0845: }
0846:
0847: MapperNode getNode(Object[] path, boolean load) {
0848: if (path == null) {
0849: return null;
0850: }
0851: if (path.length == 0) {
0852: return null;
0853: }
0854: if (root == null) {
0855: return null;
0856: }
0857: if (root.getValue() != path[0]) {
0858: throw new IllegalStateException();
0859: }
0860:
0861: MapperNode node = root;
0862: for (int i = 1; i < path.length; i++) {
0863: if (!load && !node.isLoaded()) {
0864: return null;
0865: }
0866: if (model.getIndexOfChild(node.getValue(), path[i]) == -1) {
0867: }
0868: node = node.getChild(model.getIndexOfChild(node.getValue(),
0869: path[i]));
0870: }
0871:
0872: return node;
0873: }
0874:
0875: MapperNode getClosestLoadedNode(Object[] path) {
0876: if (path == null) {
0877: return null;
0878: }
0879: if (path.length == 0) {
0880: return null;
0881: }
0882: if (root == null) {
0883: return null;
0884: }
0885: if (root.getValue() != path[0]) {
0886: throw new IllegalStateException();
0887: }
0888:
0889: MapperNode node = root;
0890:
0891: for (int i = 1; i < path.length; i++) {
0892: if (!node.isLoaded()) {
0893: break;
0894: }
0895: node = node.getChild(model.getIndexOfChild(node.getValue(),
0896: path[i]));
0897: }
0898:
0899: return node;
0900: }
0901:
0902: MapperNode getNodeAt(int y) {
0903: return (root == null) ? null : root.getNode(y);
0904: }
0905:
0906: void invalidateNodes() {
0907: if (validNodes) {
0908: rightTree.revalidate();
0909:
0910: canvas.revalidate();
0911:
0912: JComponent component = (JComponent) rightTree
0913: .getScrollPane().getRowHeader().getView();
0914: component.revalidate();
0915:
0916: preferredTreeSize = null;
0917: graphXRange = null;
0918:
0919: validNodes = false;
0920: }
0921: }
0922:
0923: void repaintNodes() {
0924: if (!repaintSceduled) {
0925: rightTree.repaint();
0926: canvas.repaint();
0927:
0928: JComponent component = (JComponent) rightTree
0929: .getScrollPane().getRowHeader().getView();
0930: component.repaint();
0931:
0932: repaintSceduled = true;
0933: }
0934: }
0935:
0936: void validateNodes() {
0937: if (!validNodes && root != null) {
0938: preferredTreeSize = root.getPreferredSize();
0939: graphXRange = root.getGraphXRange();
0940:
0941: root.setBounds(0, preferredTreeSize.height, 0);
0942: root.validate();
0943:
0944: validNodes = true;
0945: }
0946: }
0947:
0948: @Override
0949: public void doLayout() {
0950: validateNodes();
0951: super .doLayout();
0952: }
0953:
0954: @Override
0955: public Dimension getPreferredSize() {
0956: validateNodes();
0957: return super .getPreferredSize();
0958: }
0959:
0960: Dimension getPreferredTreeSize() {
0961: validateNodes();
0962: return (preferredTreeSize == null) ? null : new Dimension(
0963: preferredTreeSize.width, preferredTreeSize.height - 1);
0964: }
0965:
0966: XRange getGraphXRange() {
0967: validateNodes();
0968: return (graphXRange == null) ? null : new XRange(graphXRange);
0969: }
0970:
0971: int getLeftIndent() {
0972: return leftChildIndent;
0973: }
0974:
0975: int getRightIndent() {
0976: return rightChildIndent;
0977: }
0978:
0979: int getTotalIndent() {
0980: return leftChildIndent + rightChildIndent;
0981: }
0982:
0983: Icon getOpenIcon() {
0984: return openIcon;
0985: }
0986:
0987: Icon getClosedIcon() {
0988: return closedIcon;
0989: }
0990:
0991: Icon getLeafIcon() {
0992: return leafIcon;
0993: }
0994:
0995: Icon getExpandedIcon() {
0996: return expandedIcon;
0997: }
0998:
0999: Icon getCollapsedIcon() {
1000: return collapsedIcon;
1001: }
1002:
1003: Color getTreeLineColor() {
1004: return treeLineColor;
1005: }
1006:
1007: void updateChildGraphs(TreePath treePath) {
1008: MapperNode node = getClosestLoadedNode(treePath.getPath());
1009:
1010: while (node != null) {
1011: node.updateChildGraphs();
1012: node.invalidate();
1013: node.repaint();
1014: node = node.getParent();
1015: }
1016: }
1017:
1018: @Override
1019: public void updateUI() {
1020: super .updateUI();
1021: treeLineColor = UIManager.getColor("Tree.hash");
1022:
1023: leftChildIndent = UIManager.getInt("Tree.rightChildIndent");
1024: rightChildIndent = UIManager.getInt("Tree.leftChildIndent");
1025:
1026: openIcon = UIManager.getIcon("Tree.openIcon");
1027: closedIcon = UIManager.getIcon("Tree.closedIcon");
1028: leafIcon = UIManager.getIcon("Tree.leafIcon");
1029:
1030: expandedIcon = UIManager.getIcon("Tree.expandedIcon");
1031: collapsedIcon = UIManager.getIcon("Tree.collapsedIcon");
1032: }
1033:
1034: private int compare(Graph graph1, Graph graph2, TreePath treePath) {
1035: if (graph1 == graph2)
1036: return 0;
1037:
1038: MapperNode node = getNode(treePath, true);
1039: if (node.getGraph() == graph1)
1040: return -1;
1041: if (node.getGraph() == graph2)
1042: return 1;
1043:
1044: for (int i = 0; i < node.getChildCount(); i++) {
1045: MapperNode nodeChild = node.getChild(i);
1046: if (nodeChild.isLeaf()) {
1047: if (nodeChild.getGraph() == graph1)
1048: return -1;
1049: if (nodeChild.getGraph() == graph2)
1050: return 1;
1051: } else {
1052: int r = compare(graph1, graph2, nodeChild.getTreePath());
1053: if (r != 0)
1054: return r;
1055: }
1056: }
1057: return 0;
1058: }
1059:
1060: private class TreeModelListenerImpl implements TreeModelListener {
1061:
1062: public void treeNodesChanged(TreeModelEvent e) {
1063: TreePath treePath = e.getTreePath();
1064: int[] indeces = e.getChildIndices();
1065:
1066: if (indeces == null || treePath == null) {
1067: root.updateChildGraphs();
1068: root.updateNode();
1069: root.invalidate();
1070: root.repaint();
1071: } else {
1072: updateChildGraphs(treePath);
1073:
1074: MapperNode node = getNode(treePath, false);
1075: if (node != null) {
1076: for (int i : indeces) {
1077: MapperNode child = node.getChild(i);
1078: child.updateNode();
1079: child.invalidate();
1080: child.repaint();
1081: }
1082: }
1083: }
1084: }
1085:
1086: public void treeNodesInserted(TreeModelEvent e) {
1087: updateChildGraphs(e.getTreePath());
1088: MapperNode node = getNode(e.getPath(), false);
1089: if (node != null) {
1090: // node.insertChildren(e);
1091: node.updateNode();
1092: node.updateChildren();
1093: node.invalidate();
1094: node.repaint();
1095: }
1096: }
1097:
1098: public void treeNodesRemoved(TreeModelEvent e) {
1099: updateChildGraphs(e.getTreePath());
1100: MapperNode node = getNode(e.getPath(), false);
1101: if (node != null) {
1102: node.updateNode();
1103: node.updateChildren();
1104: node.invalidate();
1105: node.repaint();
1106: // node.removeChildren(e);
1107: }
1108: }
1109:
1110: public void treeStructureChanged(TreeModelEvent e) {
1111: MapperModel mapperModel = model;
1112: setModel(null);
1113: setModel(mapperModel);
1114: }
1115: }
1116:
1117: private class ScrollPaneYSyncronizer implements ChangeListener {
1118:
1119: private JViewport viewport1;
1120: private JViewport viewport2;
1121:
1122: public ScrollPaneYSyncronizer(JScrollPane scrollPane1,
1123: JScrollPane scrollPane2) {
1124: viewport1 = scrollPane1.getViewport();
1125: viewport2 = scrollPane2.getViewport();
1126:
1127: viewport1.addChangeListener(this );
1128: viewport2.addChangeListener(this );
1129: }
1130:
1131: public void stateChanged(ChangeEvent e) {
1132: if (e.getSource() == viewport1) {
1133: Point position = viewport2.getViewPosition();
1134: position.y = viewport1.getViewPosition().y;
1135: viewport2.setViewPosition(position);
1136: } else {
1137: Point position = viewport1.getViewPosition();
1138: position.y = viewport2.getViewPosition().y;
1139: viewport1.setViewPosition(position);
1140: }
1141: }
1142: }
1143:
1144: public static final String MODEL_PROPERTY = "mapper-model-property";
1145: public static final Stroke DASHED_ROW_SEPARATOR_STROKE = new BasicStroke(
1146: 1, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 1,
1147: new float[] { 4, 2 }, 0);
1148: public static final Stroke DASHED_STROKE = new BasicStroke(1,
1149: BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 1,
1150: new float[] { 4, 4 }, 0);
1151: public static final Color CANVAS_BACKGROUND_COLOR = new Color(
1152: 0xFCFAF5);
1153: public static final Color CANVAS_GRID_COLOR = new Color(0xC0C0C0);
1154: public static final Color ROW_SEPARATOR_COLOR = new Color(0xBBD3E9); //new Color(0x99B7D3);
1155: public static final Color SELECTED_BACKGROUND_COLOR_TOP = new Color(
1156: 0xF0F9FF);
1157: public static final Color SELECTED_BACKGROUND_COLOR_BOTTOM = new Color(
1158: 0xD0E0F0);
1159: public static final Color RIGHT_TREE_HEADER_COLOR = new Color(
1160: 0x999999);
1161: public static final VerticalGradient SELECTED_BACKGROUND_IN_FOCUS = new VerticalGradient(
1162: Mapper.SELECTED_BACKGROUND_COLOR_TOP,
1163: Mapper.SELECTED_BACKGROUND_COLOR_BOTTOM);
1164: public static final VerticalGradient SELECTED_BACKGROUND_NOT_IN_FOCUS = new VerticalGradient(
1165: Utils.gray(Mapper.SELECTED_BACKGROUND_COLOR_TOP, 75), Utils
1166: .gray(Mapper.SELECTED_BACKGROUND_COLOR_BOTTOM, 75));
1167:
1168: private static final Comparator<Graph> GRAPH_COMPARATOR = new Comparator<Graph>() {
1169: public int compare(Graph graph1, Graph graph2) {
1170: return 0;
1171: }
1172: };
1173: }
|