001: /*
002: * The contents of this file are subject to the terms of the Common Development
003: * and Distribution License (the License). You may not use this file except in
004: * compliance with the License.
005: *
006: * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
007: * or http://www.netbeans.org/cddl.txt.
008: *
009: * When distributing Covered Code, include this CDDL Header Notice in each file
010: * and include the License file at http://www.netbeans.org/cddl.txt.
011: * If applicable, add the following below the CDDL Header, with the fields
012: * enclosed by brackets [] replaced by your own identifying information:
013: * "Portions Copyrighted [year] [name of copyright owner]"
014: *
015: * The Original Software is NetBeans. The Initial Developer of the Original
016: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
017: * Microsystems, Inc. All Rights Reserved.
018: */
019:
020: package org.netbeans.modules.soa.mapper.basicmapper.canvas.jgo.autolayout;
021:
022: import java.awt.Rectangle;
023: import java.util.ArrayList;
024: import java.util.Collection;
025: import java.util.Collections;
026: import java.util.Comparator;
027: import java.util.Enumeration;
028: import java.util.HashMap;
029: import java.util.HashSet;
030: import java.util.Iterator;
031: import java.util.LinkedList;
032: import java.util.List;
033: import java.util.Map;
034: import java.util.Set;
035: import java.util.TreeMap;
036:
037: import javax.swing.tree.DefaultMutableTreeNode;
038:
039: import com.nwoods.jgo.JGoLayer;
040: import com.nwoods.jgo.JGoLink;
041: import com.nwoods.jgo.JGoListPosition;
042: import com.nwoods.jgo.JGoPort;
043: import org.netbeans.modules.soa.mapper.basicmapper.canvas.jgo.AbstractCanvasLink;
044: import org.netbeans.modules.soa.mapper.basicmapper.canvas.jgo.BasicCanvasFieldNode;
045: import org.netbeans.modules.soa.mapper.basicmapper.canvas.jgo.BasicCanvasMethoidNode;
046: import org.netbeans.modules.soa.mapper.basicmapper.canvas.jgo.BasicCanvasNodeToTreeLink;
047: import org.netbeans.modules.soa.mapper.basicmapper.canvas.jgo.BasicCanvasTreeToNodeLink;
048: import org.netbeans.modules.soa.mapper.basicmapper.canvas.jgo.BasicCanvasTreeToTreeLink;
049: import org.netbeans.modules.soa.mapper.basicmapper.tree.BasicMapperTreeNode;
050: import org.netbeans.modules.soa.mapper.common.basicmapper.canvas.gtk.ICanvasNodeToNodeLink;
051: import org.netbeans.modules.soa.mapper.common.basicmapper.canvas.gtk.ICanvasNodeToTreeLink;
052: import org.netbeans.modules.soa.mapper.common.basicmapper.canvas.gtk.ICanvasTreeToNodeLink;
053:
054: public class TreeLayout {
055:
056: static final int YPAD = 20;
057: static final int XPAD = 40;
058: static final int XOFFSET = 10;
059:
060: Map mMap = new HashMap();
061: TreeMap mSrcTreeLinks = new TreeMap();
062: int mSrcLinks;
063: Set mRoots = new HashSet();
064:
065: void addLink(int row, Object linkObj) {
066: Integer key = new Integer(row);
067: List list = (List) mSrcTreeLinks.get(key);
068: if (list == null) {
069: list = new LinkedList();
070: mSrcTreeLinks.put(key, list);
071: }
072: list.add(linkObj);
073: mSrcLinks++;
074: }
075:
076: public void performLayout(JGoLayer layer) {
077: for (JGoListPosition pos = layer.getFirstObjectPos(); pos != null; pos = layer
078: .getNextObjectPos(pos)) {
079: Object obj = layer.getObjectAtPos(pos);
080: if (obj instanceof BasicCanvasMethoidNode) {
081: addNode((BasicCanvasMethoidNode) obj);
082: } else if (obj instanceof BasicCanvasTreeToTreeLink) {
083: BasicCanvasTreeToTreeLink ttl = (BasicCanvasTreeToTreeLink) obj;
084: BasicMapperTreeNode tn = (BasicMapperTreeNode) ttl
085: .getSourceTreeAddress();
086: //tn.expand();
087: addLink(tn.getRow(), ttl);
088: }
089: }
090: Iterator iter = mSrcTreeLinks.values().iterator();
091: int i = 1;
092: int size = mSrcLinks;
093: while (iter.hasNext()) {
094: List list = (List) iter.next();
095: Iterator ii = list.iterator();
096: while (ii.hasNext()) {
097: Object jgolink = ii.next();
098: // hack
099: ((AbstractCanvasLink) jgolink).setPosition(i, size);
100: i++;
101: }
102: }
103: List sortedRoots = new ArrayList();
104: sortedRoots.addAll(mRoots);
105: Collections.sort(sortedRoots, new Comparator() {
106: public int compare(Object l, Object r) {
107: // keep the roots in vertical order
108: DefaultMutableTreeNode ln = (DefaultMutableTreeNode) l;
109: DefaultMutableTreeNode rn = (DefaultMutableTreeNode) r;
110: BasicCanvasMethoidNode n1 = (BasicCanvasMethoidNode) ln
111: .getUserObject();
112: BasicCanvasMethoidNode n2 = (BasicCanvasMethoidNode) rn
113: .getUserObject();
114: return n1.getLocation().y - n2.getLocation().y;
115: }
116: });
117: iter = sortedRoots.iterator();
118: int y = 0;
119: while (iter.hasNext()) {
120: DefaultMutableTreeNode root = (DefaultMutableTreeNode) iter
121: .next();
122: int startX = computeWidth(root);
123: if (size > 0) {
124: //startX -= XPAD; // strip last pad
125: startX += (6 + (6 * size)); // add space for tree links
126: }
127: BasicCanvasMethoidNode n = (BasicCanvasMethoidNode) root
128: .getUserObject();
129: Rectangle rec = n.getBounding();
130: y += YPAD;
131: y = layout(root, startX, y, rec.width);
132: }
133: mMap.clear();
134: mSrcTreeLinks.clear();
135: mSrcLinks = 0;
136: mRoots.clear();
137: }
138:
139: int layout(DefaultMutableTreeNode tn, int startX, int startY,
140: int maxColWidth) {
141: Object obj = tn.getUserObject();
142: int newY = 0;
143: int y = startY;
144: int yOffset = 0;
145: if (obj instanceof BasicCanvasMethoidNode) {
146: BasicCanvasMethoidNode n = (BasicCanvasMethoidNode) obj;
147: Rectangle rec = n.getBounding();
148: int x = startX - rec.width; // right align
149: n.setLocation(x, startY);
150: startX -= (maxColWidth + XPAD);
151: newY = rec.y + rec.height + YPAD;
152: Iterator iter = n.getNodes().iterator();
153: while (iter.hasNext()) {
154: BasicCanvasFieldNode child = (BasicCanvasFieldNode) iter
155: .next();
156: JGoPort port = (JGoPort) child.getConnectPointObject();
157: JGoListPosition pos = port.getFirstLinkPos();
158: if (pos != null) {
159: JGoLink jgolink = port.getLinkAtPos(pos);
160: if (child.getFieldNode().isInput()) {
161: if (jgolink instanceof ICanvasTreeToNodeLink) {
162: Rectangle r = child.getBounding();
163: yOffset = r.y + r.height - rec.y;
164: }
165: }
166: }
167: }
168: }
169: y += yOffset;
170: Enumeration e = tn.children();
171: int colWidth = 0;
172: while (e.hasMoreElements()) {
173: DefaultMutableTreeNode c = (DefaultMutableTreeNode) e
174: .nextElement();
175: BasicCanvasMethoidNode n = (BasicCanvasMethoidNode) c
176: .getUserObject();
177: Rectangle r = n.getBounding();
178: if (r.width > colWidth) {
179: colWidth = r.width;
180: }
181: }
182: e = tn.children();
183: int i = tn.getChildCount() - 1;
184: while (e.hasMoreElements()) {
185: DefaultMutableTreeNode c = (DefaultMutableTreeNode) e
186: .nextElement();
187: y = layout(c, startX - (i * XOFFSET), y, colWidth);
188: if (y > newY) {
189: newY = y;
190: }
191: --i;
192: }
193: return newY;
194: }
195:
196: int computeWidth(DefaultMutableTreeNode tn) {
197: int colWidth = 0;
198: int totalWidth = 0;
199: Object obj = tn.getUserObject();
200: if (obj instanceof BasicCanvasMethoidNode) {
201: BasicCanvasMethoidNode n = (BasicCanvasMethoidNode) obj;
202: Rectangle rect = n.getBounding();
203: colWidth = rect.width;
204: }
205: Enumeration e = tn.children();
206: while (e.hasMoreElements()) {
207: DefaultMutableTreeNode c = (DefaultMutableTreeNode) e
208: .nextElement();
209: int colTotalWidth = computeWidth(c);
210: if (colTotalWidth > totalWidth) {
211: totalWidth = colTotalWidth;
212: }
213: colWidth += XOFFSET;
214: }
215: colWidth += XPAD;
216: return totalWidth + colWidth;
217: }
218:
219: private DefaultMutableTreeNode addNode(BasicCanvasMethoidNode node) {
220: DefaultMutableTreeNode tn = (DefaultMutableTreeNode) mMap
221: .get(node);
222: if (tn == null) {
223: tn = new DefaultMutableTreeNode(node);
224: mMap.put(node, tn);
225: Collection list = ((BasicCanvasMethoidNode) node)
226: .getNodes();
227: int count = list.size();
228: Iterator iter = list.iterator();
229: boolean noOutput = true;
230: boolean linkedToOutputTree = false;
231: boolean nullOutput = false;
232: int i = 1;
233: while (iter.hasNext()) {
234: BasicCanvasFieldNode child = (BasicCanvasFieldNode) iter
235: .next();
236: JGoPort port = (JGoPort) child.getConnectPointObject();
237: JGoListPosition pos = port.getFirstLinkPos();
238: if (pos != null) {
239: JGoLink jgolink = port.getLinkAtPos(pos);
240: if (child.getFieldNode().isInput()) {
241: if (jgolink instanceof ICanvasNodeToNodeLink) {
242: ICanvasNodeToNodeLink link = (ICanvasNodeToNodeLink) jgolink;
243: // hack
244: //((BasicCanvasNodeToNodeLink)link).setPosition(i, count);
245: i++;
246: BasicCanvasFieldNode src = (BasicCanvasFieldNode) link
247: .getSourceFieldNode();
248: BasicCanvasMethoidNode srcNode = (BasicCanvasMethoidNode) src
249: .getContainer();
250: tn.add(addNode(srcNode));
251: } else if (jgolink instanceof ICanvasTreeToNodeLink) {
252: BasicCanvasTreeToNodeLink tnl = (BasicCanvasTreeToNodeLink) jgolink;
253: BasicMapperTreeNode tnode = (BasicMapperTreeNode) tnl
254: .getSourceTreeAddress();
255: //tnode.expand();
256: addLink(tnode.getRow(), jgolink);
257: }
258: } else {
259: if (jgolink instanceof ICanvasNodeToTreeLink) {
260: BasicCanvasNodeToTreeLink ntl = (BasicCanvasNodeToTreeLink) jgolink;
261: BasicMapperTreeNode tnode = (BasicMapperTreeNode) ntl
262: .getDestTreeAddress();
263: //tnode.expand();
264: linkedToOutputTree = true;
265: }
266: }
267: } else {
268: // no link
269: if (child.getFieldNode().isOutput()) {
270: nullOutput = true;
271: }
272: }
273: if (child.getFieldNode().isOutput()) {
274: noOutput = false;
275: }
276: }
277: if (noOutput || linkedToOutputTree || nullOutput) {
278: mRoots.add(tn);
279: }
280: }
281: return tn;
282: }
283: }
|