comparison src/share/tools/IdealGraphVisualizer/ControlFlow/src/com/sun/hotspot/igv/controlflow/ControlFlowScene.java @ 21146:33ff6b03fad1

add support for control flow window and basic block view on graphs Contributed-by: Michael Haupt <michael.haupt@oracle.com> Contributed-by: Peter Hofer <peter.hofer@jku.at> Contributed-by: Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
author Michael Haupt <michael.haupt@oracle.com>
date Wed, 29 Apr 2015 08:31:28 +0200
parents
children
comparison
equal deleted inserted replaced
21142:0b221b4ad707 21146:33ff6b03fad1
1 /*
2 * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24 package com.sun.hotspot.igv.controlflow;
25
26 import com.sun.hotspot.igv.data.InputBlockEdge;
27 import com.sun.hotspot.igv.data.InputBlock;
28 import com.sun.hotspot.igv.data.InputGraph;
29 import com.sun.hotspot.igv.data.services.InputGraphProvider;
30 import com.sun.hotspot.igv.data.InputNode;
31 import com.sun.hotspot.igv.util.LookupHistory;
32 import java.awt.Color;
33 import java.awt.Point;
34 import java.awt.Rectangle;
35 import java.util.ArrayList;
36 import java.util.HashSet;
37 import java.util.Set;
38 import javax.swing.BorderFactory;
39 import org.netbeans.api.visual.action.ActionFactory;
40 import org.netbeans.api.visual.action.MoveProvider;
41 import org.netbeans.api.visual.action.RectangularSelectDecorator;
42 import org.netbeans.api.visual.action.RectangularSelectProvider;
43 import org.netbeans.api.visual.action.SelectProvider;
44 import org.netbeans.api.visual.action.WidgetAction;
45 import org.netbeans.api.visual.anchor.AnchorFactory;
46 import org.netbeans.api.visual.anchor.AnchorShape;
47 import org.netbeans.api.visual.router.RouterFactory;
48 import org.netbeans.api.visual.widget.LayerWidget;
49 import org.netbeans.api.visual.widget.Widget;
50 import org.netbeans.api.visual.graph.GraphScene;
51 import org.netbeans.api.visual.graph.layout.GraphLayout;
52 import org.netbeans.api.visual.layout.LayoutFactory;
53 import org.netbeans.api.visual.layout.SceneLayout;
54 import org.netbeans.api.visual.widget.ConnectionWidget;
55
56 /**
57 *
58 * @author Thomas Wuerthinger
59 */
60 public class ControlFlowScene extends GraphScene<InputBlock, InputBlockEdge> implements SelectProvider, MoveProvider, RectangularSelectDecorator, RectangularSelectProvider {
61
62 private HashSet<BlockWidget> selection;
63 private InputGraph oldGraph;
64 private LayerWidget edgeLayer;
65 private LayerWidget mainLayer;
66 private LayerWidget selectLayer;
67 private WidgetAction hoverAction = this.createWidgetHoverAction();
68 private WidgetAction selectAction = new DoubleClickSelectAction(this);
69 private WidgetAction moveAction = ActionFactory.createMoveAction(null, this);
70
71 public ControlFlowScene() {
72 selection = new HashSet<BlockWidget>();
73
74 this.getInputBindings().setZoomActionModifiers(0);
75 this.setLayout(LayoutFactory.createAbsoluteLayout());
76
77 mainLayer = new LayerWidget(this);
78 this.addChild(mainLayer);
79
80 edgeLayer = new LayerWidget(this);
81 this.addChild(edgeLayer);
82
83 selectLayer = new LayerWidget(this);
84 this.addChild(selectLayer);
85
86 this.getActions().addAction(hoverAction);
87 this.getActions().addAction(selectAction);
88 this.getActions().addAction(ActionFactory.createRectangularSelectAction(this, selectLayer, this));
89 this.getActions().addAction(ActionFactory.createMouseCenteredZoomAction(1.1));
90 }
91
92 public void setGraph(InputGraph g) {
93 if (g == oldGraph) {
94 return;
95 }
96 oldGraph = g;
97
98 ArrayList<InputBlock> blocks = new ArrayList<InputBlock>(this.getNodes());
99 for (InputBlock b : blocks) {
100 removeNode(b);
101 }
102
103 ArrayList<InputBlockEdge> edges = new ArrayList<InputBlockEdge>(this.getEdges());
104 for (InputBlockEdge e : edges) {
105 removeEdge(e);
106 }
107
108 for (InputBlock b : g.getBlocks()) {
109 addNode(b);
110 }
111
112 for (InputBlockEdge e : g.getBlockEdges()) {
113 addEdge(e);
114 assert g.getBlocks().contains(e.getFrom());
115 assert g.getBlocks().contains(e.getTo());
116 this.setEdgeSource(e, e.getFrom());
117 this.setEdgeTarget(e, e.getTo());
118 }
119
120 GraphLayout<InputBlock, InputBlockEdge> layout = new HierarchicalGraphLayout<InputBlock, InputBlockEdge>();//GridGraphLayout();
121 SceneLayout sceneLayout = LayoutFactory.createSceneGraphLayout(this, layout);
122 sceneLayout.invokeLayout();
123
124 this.validate();
125 }
126
127 public void clearSelection() {
128 for (BlockWidget w : selection) {
129 w.setState(w.getState().deriveSelected(false));
130 }
131 selection.clear();
132 selectionChanged();
133 }
134
135 public void selectionChanged() {
136 InputGraphProvider p = LookupHistory.getLast(InputGraphProvider.class);//)Utilities.actionsGlobalContext().lookup(InputGraphProvider.class);
137 if (p != null) {
138 Set<InputNode> inputNodes = new HashSet<InputNode>();
139 for (BlockWidget w : selection) {
140 inputNodes.addAll(w.getBlock().getNodes());
141 }
142 p.setSelectedNodes(inputNodes);
143 }
144 }
145
146 public void addToSelection(BlockWidget widget) {
147 widget.setState(widget.getState().deriveSelected(true));
148 selection.add(widget);
149 selectionChanged();
150 }
151
152 public void removeFromSelection(BlockWidget widget) {
153 widget.setState(widget.getState().deriveSelected(false));
154 selection.remove(widget);
155 selectionChanged();
156 }
157
158 public boolean isAimingAllowed(Widget widget, Point point, boolean b) {
159 return false;
160 }
161
162 public boolean isSelectionAllowed(Widget widget, Point point, boolean b) {
163 return true;
164 }
165
166 public void select(Widget widget, Point point, boolean change) {
167 if (widget == this) {
168 clearSelection();
169 } else {
170
171 assert widget instanceof BlockWidget;
172 BlockWidget bw = (BlockWidget) widget;
173 if (change) {
174 if (selection.contains(bw)) {
175 removeFromSelection(bw);
176 } else {
177 addToSelection(bw);
178 }
179 } else {
180 if (!selection.contains(bw)) {
181 clearSelection();
182 addToSelection(bw);
183 }
184 }
185 }
186 }
187
188 public void movementStarted(Widget widget) {
189 }
190
191 public void movementFinished(Widget widget) {
192 }
193
194 public Point getOriginalLocation(Widget widget) {
195 return widget.getPreferredLocation();
196 }
197
198 public void setNewLocation(Widget widget, Point location) {
199 if (selection.contains(widget)) {
200 // move entire selection
201 Point originalLocation = getOriginalLocation(widget);
202 int xOffset = location.x - originalLocation.x;
203 int yOffset = location.y - originalLocation.y;
204 for (Widget w : selection) {
205 Point p = new Point(w.getPreferredLocation());
206 p.translate(xOffset, yOffset);
207 w.setPreferredLocation(p);
208 }
209 } else {
210 widget.setPreferredLocation(location);
211 }
212 }
213
214 public Widget createSelectionWidget() {
215 Widget widget = new Widget(this);
216 widget.setOpaque(false);
217 widget.setBorder(BorderFactory.createLineBorder(Color.black, 2));
218 widget.setForeground(Color.red);
219 return widget;
220 }
221
222 public void performSelection(Rectangle rectangle) {
223
224 if (rectangle.width < 0) {
225 rectangle.x += rectangle.width;
226 rectangle.width *= -1;
227 }
228
229 if (rectangle.height < 0) {
230 rectangle.y += rectangle.height;
231 rectangle.height *= -1;
232 }
233
234 boolean changed = false;
235 for (InputBlock b : this.getNodes()) {
236 BlockWidget w = (BlockWidget) findWidget(b);
237 Rectangle r = new Rectangle(w.getBounds());
238 r.setLocation(w.getLocation());
239 if (r.intersects(rectangle)) {
240 if (!selection.contains(w)) {
241 changed = true;
242 selection.add(w);
243 w.setState(w.getState().deriveSelected(true));
244 }
245 } else {
246 if (selection.contains(w)) {
247 changed = true;
248 selection.remove(w);
249 w.setState(w.getState().deriveSelected(false));
250 }
251 }
252 }
253
254 if (changed) {
255 selectionChanged();
256 }
257
258 }
259
260 protected Widget attachNodeWidget(InputBlock node) {
261 BlockWidget w = new BlockWidget(this, node);
262 mainLayer.addChild(w);
263 w.getActions().addAction(hoverAction);
264 w.getActions().addAction(selectAction);
265 w.getActions().addAction(moveAction);
266 return w;
267 }
268
269 protected Widget attachEdgeWidget(InputBlockEdge edge) {
270 BlockConnectionWidget w = new BlockConnectionWidget(this, edge);
271 switch (edge.getState()) {
272 case NEW:
273 w.setBold(true);
274 break;
275 case DELETED:
276 w.setDashed(true);
277 break;
278 }
279 w.setRouter(RouterFactory.createDirectRouter());
280 w.setTargetAnchorShape(AnchorShape.TRIANGLE_FILLED);
281 edgeLayer.addChild(w);
282 return w;
283 }
284
285 protected void attachEdgeSourceAnchor(InputBlockEdge edge, InputBlock oldSourceNode, InputBlock sourceNode) {
286 Widget w = this.findWidget(edge);
287 assert w instanceof ConnectionWidget;
288 ConnectionWidget cw = (ConnectionWidget) w;
289 cw.setSourceAnchor(AnchorFactory.createRectangularAnchor(findWidget(sourceNode)));
290
291 }
292
293 protected void attachEdgeTargetAnchor(InputBlockEdge edge, InputBlock oldTargetNode, InputBlock targetNode) {
294 Widget w = this.findWidget(edge);
295 assert w instanceof ConnectionWidget;
296 ConnectionWidget cw = (ConnectionWidget) w;
297 cw.setTargetAnchor(AnchorFactory.createRectangularAnchor(findWidget(targetNode)));
298 }
299 }