blob: 1d2c9a2cb8824eb920bb3356e265d8e664891aeb [file] [log] [blame]
/*
* Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
package com.sun.hotspot.igv.controlflow;
import com.sun.hotspot.igv.data.InputBlock;
import com.sun.hotspot.igv.data.InputBlockEdge;
import com.sun.hotspot.igv.data.InputGraph;
import com.sun.hotspot.igv.data.services.InputGraphProvider;
import com.sun.hotspot.igv.data.InputNode;
import java.awt.Color;
import java.awt.Point;
import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.HashMap;
import java.util.Set;
import javax.swing.BorderFactory;
import org.netbeans.api.visual.action.ActionFactory;
import org.netbeans.api.visual.action.MoveProvider;
import org.netbeans.api.visual.action.RectangularSelectDecorator;
import org.netbeans.api.visual.action.RectangularSelectProvider;
import org.netbeans.api.visual.action.SelectProvider;
import org.netbeans.api.visual.action.WidgetAction;
import org.netbeans.api.visual.anchor.AnchorFactory;
import org.netbeans.api.visual.anchor.AnchorShape;
import org.netbeans.api.visual.layout.LayoutFactory;
import org.netbeans.api.visual.router.RouterFactory;
import org.netbeans.api.visual.widget.LayerWidget;
import org.netbeans.api.visual.widget.Widget;
import org.netbeans.api.visual.graph.GraphScene;
import org.netbeans.api.visual.graph.layout.GraphLayout;
import org.netbeans.api.visual.layout.SceneLayout;
import org.netbeans.api.visual.widget.ConnectionWidget;
import org.openide.util.Lookup;
/**
*
* @author Thomas Wuerthinger
*/
public class ControlFlowScene extends GraphScene<InputBlock, InputBlockEdge> implements SelectProvider, MoveProvider, RectangularSelectDecorator, RectangularSelectProvider {
private HashSet<BlockWidget> selection;
private HashMap<InputBlock, BlockWidget> blockMap;
private InputGraph oldGraph;
private LayerWidget edgeLayer;
private LayerWidget mainLayer;
private LayerWidget selectLayer;
private WidgetAction hoverAction = this.createWidgetHoverAction();
private WidgetAction selectAction = ActionFactory.createSelectAction(this);
private WidgetAction moveAction = ActionFactory.createMoveAction(null, this);
public ControlFlowScene() {
selection = new HashSet<BlockWidget>();
this.getInputBindings().setZoomActionModifiers(0);
this.setLayout(LayoutFactory.createAbsoluteLayout());
mainLayer = new LayerWidget(this);
this.addChild(mainLayer);
edgeLayer = new LayerWidget(this);
this.addChild(edgeLayer);
selectLayer = new LayerWidget(this);
this.addChild(selectLayer);
this.getActions().addAction(hoverAction);
this.getActions().addAction(selectAction);
this.getActions().addAction(ActionFactory.createRectangularSelectAction(this, selectLayer, this));
this.getActions().addAction(ActionFactory.createMouseCenteredZoomAction(1.1));
}
public void setGraph(InputGraph g) {
if (g == oldGraph) {
return;
}
oldGraph = g;
ArrayList<InputBlock> blocks = new ArrayList<InputBlock>(this.getNodes());
for (InputBlock b : blocks) {
removeNode(b);
}
ArrayList<InputBlockEdge> edges = new ArrayList<InputBlockEdge>(this.getEdges());
for (InputBlockEdge e : edges) {
removeEdge(e);
}
for (InputBlock b : g.getBlocks()) {
addNode(b);
}
for (InputBlock b : g.getBlocks()) {
for (InputBlockEdge e : b.getOutputs()) {
addEdge(e);
assert g.getBlocks().contains(e.getFrom());
assert g.getBlocks().contains(e.getTo());
this.setEdgeSource(e, e.getFrom());
this.setEdgeTarget(e, e.getTo());
}
}
GraphLayout layout = new HierarchicalGraphLayout();//GridGraphLayout();
SceneLayout sceneLayout = LayoutFactory.createSceneGraphLayout(this, layout);
sceneLayout.invokeLayout();
this.validate();
}
public BlockWidget getBlockWidget(InputBlock b) {
return blockMap.get(b);
}
public void clearSelection() {
for (BlockWidget w : selection) {
w.setState(w.getState().deriveSelected(false));
}
selection.clear();
selectionChanged();
}
public void selectionChanged() {
InputGraphProvider p = Lookup.getDefault().lookup(InputGraphProvider.class);
if (p != null) {
Set<InputNode> inputNodes = new HashSet<InputNode>();
for (BlockWidget w : selection) {
inputNodes.addAll(w.getBlock().getNodes());
}
p.setSelectedNodes(inputNodes);
}
}
public void addToSelection(BlockWidget widget) {
widget.setState(widget.getState().deriveSelected(true));
selection.add(widget);
selectionChanged();
}
public void removeFromSelection(BlockWidget widget) {
widget.setState(widget.getState().deriveSelected(false));
selection.remove(widget);
selectionChanged();
}
public boolean isAimingAllowed(Widget widget, Point point, boolean b) {
return false;
}
public boolean isSelectionAllowed(Widget widget, Point point, boolean b) {
return true;
}
public void select(Widget widget, Point point, boolean change) {
if (widget == this) {
clearSelection();
} else {
assert widget instanceof BlockWidget;
BlockWidget bw = (BlockWidget) widget;
if (change) {
if (selection.contains(bw)) {
removeFromSelection(bw);
} else {
addToSelection(bw);
}
} else {
if (!selection.contains(bw)) {
clearSelection();
addToSelection(bw);
}
}
}
}
public void movementStarted(Widget widget) {
}
public void movementFinished(Widget widget) {
}
public Point getOriginalLocation(Widget widget) {
return widget.getPreferredLocation();
}
public void setNewLocation(Widget widget, Point location) {
Point originalLocation = getOriginalLocation(widget);
int xOffset = location.x - originalLocation.x;
int yOffset = location.y - originalLocation.y;
for (Widget w : this.selection) {
Point p = new Point(w.getPreferredLocation());
p.translate(xOffset, yOffset);
w.setPreferredLocation(p);
}
}
public Widget createSelectionWidget() {
Widget widget = new Widget(this);
widget.setOpaque(false);
widget.setBorder(BorderFactory.createLineBorder(Color.black, 2));
widget.setForeground(Color.red);
return widget;
}
public void performSelection(Rectangle rectangle) {
if (rectangle.width < 0) {
rectangle.x += rectangle.width;
rectangle.width *= -1;
}
if (rectangle.height < 0) {
rectangle.y += rectangle.height;
rectangle.height *= -1;
}
boolean changed = false;
for (InputBlock b : this.getNodes()) {
BlockWidget w = (BlockWidget) findWidget(b);
Rectangle r = new Rectangle(w.getBounds());
r.setLocation(w.getLocation());
if (r.intersects(rectangle)) {
if (!selection.contains(w)) {
changed = true;
selection.add(w);
w.setState(w.getState().deriveSelected(true));
}
} else {
if (selection.contains(w)) {
changed = true;
selection.remove(w);
w.setState(w.getState().deriveSelected(false));
}
}
}
if (changed) {
selectionChanged();
}
}
protected Widget attachNodeWidget(InputBlock node) {
BlockWidget w = new BlockWidget(this, node);
mainLayer.addChild(w);
w.getActions().addAction(hoverAction);
w.getActions().addAction(selectAction);
w.getActions().addAction(moveAction);
return w;
}
protected Widget attachEdgeWidget(InputBlockEdge edge) {
ConnectionWidget w = new BlockConnectionWidget(this, edge);
w.setRouter(RouterFactory.createDirectRouter());
w.setTargetAnchorShape(AnchorShape.TRIANGLE_FILLED);
edgeLayer.addChild(w);
return w;
}
protected void attachEdgeSourceAnchor(InputBlockEdge edge, InputBlock oldSourceNode, InputBlock sourceNode) {
Widget w = this.findWidget(edge);
assert w instanceof ConnectionWidget;
ConnectionWidget cw = (ConnectionWidget) w;
cw.setSourceAnchor(AnchorFactory.createRectangularAnchor(findWidget(sourceNode)));
}
protected void attachEdgeTargetAnchor(InputBlockEdge edge, InputBlock oldTargetNode, InputBlock targetNode) {
Widget w = this.findWidget(edge);
assert w instanceof ConnectionWidget;
ConnectionWidget cw = (ConnectionWidget) w;
cw.setTargetAnchor(AnchorFactory.createRectangularAnchor(findWidget(targetNode)));
}
}