Added
Link Here
|
1 |
/* |
2 |
* The contents of this file are subject to the terms of the Common Development |
3 |
* and Distribution License (the License). You may not use this file except in |
4 |
* compliance with the License. |
5 |
* |
6 |
* You can obtain a copy of the License at http://www.netbeans.org/cddl.html |
7 |
* or http://www.netbeans.org/cddl.txt. |
8 |
* |
9 |
* When distributing Covered Code, include this CDDL Header Notice in each file |
10 |
* and include the License file at http://www.netbeans.org/cddl.txt. |
11 |
* If applicable, add the following below the CDDL Header, with the fields |
12 |
* enclosed by brackets [] replaced by your own identifying information: |
13 |
* "Portions Copyrighted [year] [name of copyright owner]" |
14 |
* |
15 |
* The Original Software is NetBeans. The Initial Developer of the Original |
16 |
* Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun |
17 |
* Microsystems, Inc. All Rights Reserved. |
18 |
*/ |
19 |
package org.netbeans.modules.visual.graph.layout; |
20 |
|
21 |
import org.netbeans.api.visual.graph.layout.GraphLayout; |
22 |
import org.netbeans.api.visual.graph.layout.UniversalGraph; |
23 |
import org.netbeans.api.visual.widget.Widget; |
24 |
|
25 |
import java.awt.*; |
26 |
import java.util.*; |
27 |
|
28 |
/** |
29 |
* @author David Kaspar |
30 |
*/ |
31 |
public final class TreeGraphLayout<N,E> extends GraphLayout<N,E> { |
32 |
|
33 |
private int originX; |
34 |
private int originY; |
35 |
private int verticalGap; |
36 |
private int horizontalGap; |
37 |
private boolean vertical; |
38 |
|
39 |
private N rootNode; |
40 |
|
41 |
public TreeGraphLayout (int originX, int originY, int verticalGap, int horizontalGap, boolean vertical) { |
42 |
this.originX = originX; |
43 |
this.originY = originY; |
44 |
this.verticalGap = verticalGap; |
45 |
this.horizontalGap = horizontalGap; |
46 |
this.vertical = vertical; |
47 |
} |
48 |
|
49 |
public void setRootNode (N rootNode) { |
50 |
this.rootNode = rootNode; |
51 |
} |
52 |
|
53 |
protected void performGraphLayout (UniversalGraph<N, E> graph) { |
54 |
if (rootNode == null) |
55 |
return; |
56 |
Collection<N> allNodes = graph.getNodes (); |
57 |
ArrayList<N> nodesToResolve = new ArrayList<N> (allNodes); |
58 |
|
59 |
HashSet<N> loadedSet = new HashSet<N> (); |
60 |
Node root = new Node (graph, rootNode, loadedSet); |
61 |
nodesToResolve.removeAll (loadedSet); |
62 |
if (vertical) { |
63 |
root.allocateHorizontally (graph); |
64 |
root.resolveVertically (originX, originY); |
65 |
} else { |
66 |
root.allocateVertically (graph); |
67 |
root.resolveHorizontally (originX, originY); |
68 |
} |
69 |
|
70 |
final HashMap<N, Point> resultPosition = new HashMap<N, Point> (); |
71 |
root.upload (resultPosition); |
72 |
|
73 |
for (N node : nodesToResolve) { |
74 |
Point position = new Point (); |
75 |
// TODO - resolve others |
76 |
resultPosition.put (node, position); |
77 |
} |
78 |
|
79 |
for (Map.Entry<N, Point> entry : resultPosition.entrySet ()) |
80 |
setResolvedNodeLocation (graph, entry.getKey (), entry.getValue ()); |
81 |
} |
82 |
|
83 |
protected void performNodesLayout (UniversalGraph<N, E> universalGraph, Collection<N> nodes) { |
84 |
throw new UnsupportedOperationException (); // TODO |
85 |
} |
86 |
|
87 |
private class Node { |
88 |
|
89 |
private N node; |
90 |
private ArrayList<Node> children; |
91 |
|
92 |
private Rectangle relativeBounds; |
93 |
private int space; |
94 |
private int totalSpace; |
95 |
private Point point; |
96 |
|
97 |
private Node (UniversalGraph<N, E> graph, N node, HashSet<N> loadedSet) { |
98 |
this.node = node; |
99 |
loadedSet.add (node); |
100 |
|
101 |
children = new ArrayList<Node> (); |
102 |
for (E edge: graph.findNodeEdges (node, true, false)) { |
103 |
N child = graph.getEdgeTarget (edge); |
104 |
if (child != null && ! loadedSet.contains (child)) |
105 |
children.add (new Node (graph, child, loadedSet)); |
106 |
} |
107 |
} |
108 |
|
109 |
private int allocateHorizontally (UniversalGraph<N, E> graph) { |
110 |
Widget widget = graph.getScene ().findWidget (node); |
111 |
widget.getLayout ().layout (widget); |
112 |
relativeBounds = widget.getPreferredBounds (); |
113 |
space = 0; |
114 |
for (int i = 0; i < children.size (); i++) { |
115 |
if (i > 0) |
116 |
space += horizontalGap; |
117 |
space += children.get (i).allocateHorizontally (graph); |
118 |
} |
119 |
totalSpace = Math.max (space, relativeBounds.width); |
120 |
return totalSpace; |
121 |
} |
122 |
|
123 |
private void resolveVertically (int x, int y) { |
124 |
point = new Point (x + totalSpace / 2, y - relativeBounds.y); |
125 |
x += (totalSpace - space) / 2; |
126 |
y += relativeBounds.height + verticalGap; |
127 |
for (Node child : children) { |
128 |
child.resolveVertically (x, y); |
129 |
x += child.totalSpace + horizontalGap; |
130 |
} |
131 |
} |
132 |
|
133 |
private int allocateVertically (UniversalGraph<N, E> graph) { |
134 |
Widget widget = graph.getScene ().findWidget (node); |
135 |
widget.getLayout ().layout (widget); |
136 |
relativeBounds = widget.getPreferredBounds (); |
137 |
space = 0; |
138 |
for (int i = 0; i < children.size (); i++) { |
139 |
if (i > 0) |
140 |
space += verticalGap; |
141 |
space += children.get (i).allocateVertically (graph); |
142 |
} |
143 |
totalSpace = Math.max (space, relativeBounds.height); |
144 |
return totalSpace; |
145 |
} |
146 |
|
147 |
private void resolveHorizontally (int x, int y) { |
148 |
point = new Point (x - relativeBounds.x, y + totalSpace / 2); |
149 |
x += relativeBounds.width + horizontalGap; |
150 |
y += (totalSpace - space) / 2; |
151 |
for (Node child : children) { |
152 |
child.resolveHorizontally (x, y); |
153 |
y += child.totalSpace + verticalGap; |
154 |
} |
155 |
} |
156 |
|
157 |
private void upload (HashMap<N, Point> result) { |
158 |
result.put (node, point); |
159 |
for (Node child : children) |
160 |
child.upload (result); |
161 |
} |
162 |
} |
163 |
|
164 |
} |