8265441: IGV: select block nodes by clicking on it

Reviewed-by: rcastanedalo, thartmann
This commit is contained in:
Tobias Holenstein 2022-10-26 14:04:38 +00:00
parent 78454b69da
commit 3135914362
16 changed files with 156 additions and 188 deletions

View File

@ -41,7 +41,8 @@ public final class SelectBytecodesAction extends CookieAction {
SelectBytecodesCookie c = activatedNodes[0].getCookie(SelectBytecodesCookie.class); SelectBytecodesCookie c = activatedNodes[0].getCookie(SelectBytecodesCookie.class);
InputGraphProvider p = LookupHistory.getLast(InputGraphProvider.class); InputGraphProvider p = LookupHistory.getLast(InputGraphProvider.class);
if (p != null) { if (p != null) {
p.setSelectedNodes(c.getNodes()); p.clearSelectedNodes();
p.addSelectedNodes(c.getNodes());
} }
} }

View File

@ -133,7 +133,8 @@ public class ControlFlowScene extends GraphScene<InputBlock, InputBlockEdge> imp
for (BlockWidget w : selection) { for (BlockWidget w : selection) {
inputNodes.addAll(w.getBlock().getNodes()); inputNodes.addAll(w.getBlock().getNodes());
} }
p.setSelectedNodes(inputNodes); p.clearSelectedNodes();
p.addSelectedNodes(inputNodes);
} }
} }

View File

@ -26,7 +26,7 @@ package com.sun.hotspot.igv.data.services;
import com.sun.hotspot.igv.data.InputGraph; import com.sun.hotspot.igv.data.InputGraph;
import com.sun.hotspot.igv.data.InputNode; import com.sun.hotspot.igv.data.InputNode;
import java.util.Set; import java.util.Collection;
/** /**
* *
@ -36,7 +36,10 @@ public interface InputGraphProvider {
InputGraph getGraph(); InputGraph getGraph();
void setSelectedNodes(Set<InputNode> nodes); void addSelectedNodes(Collection<InputNode> nodes);
void clearSelectedNodes();
/** /**
* @return an iterator walking forward through the {@link InputGraph}s following the {@link #getGraph()} * @return an iterator walking forward through the {@link InputGraph}s following the {@link #getGraph()}

View File

@ -58,7 +58,6 @@ public class SplitFilter extends AbstractFilter {
OutputSlot os = c.getOutputSlot(); OutputSlot os = c.getOutputSlot();
if (f.getInputNode() != null) { if (f.getInputNode() != null) {
os.getSource().addSourceNode(f.getInputNode()); os.getSource().addSourceNode(f.getInputNode());
os.setAssociatedNode(f.getInputNode());
os.setColor(f.getColor()); os.setColor(f.getColor());
} }
@ -75,7 +74,6 @@ public class SplitFilter extends AbstractFilter {
InputSlot is = c.getInputSlot(); InputSlot is = c.getInputSlot();
if (f.getInputNode() != null) { if (f.getInputNode() != null) {
is.getSource().addSourceNode(f.getInputNode()); is.getSource().addSourceNode(f.getInputNode());
is.setAssociatedNode(f.getInputNode());
is.setColor(f.getColor()); is.setColor(f.getColor());
} }

View File

@ -87,13 +87,14 @@ public class BlockQuickSearch implements SearchProvider {
final InputGraph theGraph = p.getGraph() != matchGraph ? matchGraph : null; final InputGraph theGraph = p.getGraph() != matchGraph ? matchGraph : null;
for (final InputBlock b : matches) { for (final InputBlock b : matches) {
if (!response.addResult(() -> { if (!response.addResult(() -> {
final EditorTopComponent comp = EditorTopComponent.getActive(); final EditorTopComponent editor = EditorTopComponent.getActive();
assert(comp != null); assert(editor != null);
if (theGraph != null) { if (theGraph != null) {
comp.getModel().selectGraph(theGraph); editor.getModel().selectGraph(theGraph);
} }
comp.setSelectedNodes(b); editor.clearSelectedNodes();
comp.requestActive(); editor.addSelectedNodes(b.getNodes(), true);
editor.requestActive();
}, },
"B" + b.getName() + (theGraph != null ? " in " + theGraph.getName() : ""))) { "B" + b.getName() + (theGraph != null ? " in " + theGraph.getName() : ""))) {
return; return;

View File

@ -32,9 +32,7 @@ import com.sun.hotspot.igv.hierarchicallayout.HierarchicalLayoutManager;
import com.sun.hotspot.igv.hierarchicallayout.LinearLayoutManager; import com.sun.hotspot.igv.hierarchicallayout.LinearLayoutManager;
import com.sun.hotspot.igv.layout.LayoutGraph; import com.sun.hotspot.igv.layout.LayoutGraph;
import com.sun.hotspot.igv.selectioncoordinator.SelectionCoordinator; import com.sun.hotspot.igv.selectioncoordinator.SelectionCoordinator;
import com.sun.hotspot.igv.util.ColorIcon; import com.sun.hotspot.igv.util.*;
import com.sun.hotspot.igv.util.DoubleClickAction;
import com.sun.hotspot.igv.util.PropertiesSheet;
import com.sun.hotspot.igv.view.actions.CustomSelectAction; import com.sun.hotspot.igv.view.actions.CustomSelectAction;
import com.sun.hotspot.igv.view.actions.CustomizablePanAction; import com.sun.hotspot.igv.view.actions.CustomizablePanAction;
import com.sun.hotspot.igv.view.actions.MouseZoomAction; import com.sun.hotspot.igv.view.actions.MouseZoomAction;
@ -70,7 +68,7 @@ import org.openide.util.lookup.InstanceContent;
* *
* @author Thomas Wuerthinger * @author Thomas Wuerthinger
*/ */
public class DiagramScene extends ObjectScene implements DiagramViewer { public class DiagramScene extends ObjectScene implements DiagramViewer, DoubleClickHandler {
private final CustomizablePanAction panAction; private final CustomizablePanAction panAction;
private final WidgetAction hoverAction; private final WidgetAction hoverAction;
@ -186,26 +184,26 @@ public class DiagramScene extends ObjectScene implements DiagramViewer {
} }
@Override @Override
public void centerFigures(List<Figure> figures) { public void centerFigures(Collection<Figure> figures) {
Rectangle overall = null;
getModel().showFigures(figures); getModel().showFigures(figures);
for (Figure f : figures) { Rectangle overallRect = null;
FigureWidget fw = getWidget(f); for (Figure figure : figures) {
if (fw != null) { FigureWidget figureWidget = getWidget(figure);
Rectangle r = fw.getBounds(); if (figureWidget != null) {
Point p = fw.getLocation(); Rectangle bounds = figureWidget.getBounds();
assert r != null; if (bounds != null) {
Rectangle r2 = new Rectangle(p.x, p.y, r.width, r.height); Point location = figureWidget.getLocation();
Rectangle figureRect = new Rectangle(location.x, location.y, bounds.width, bounds.height);
if (overall == null) { if (overallRect == null) {
overall = r2; overallRect = figureRect;
} else { } else {
overall = overall.union(r2); overallRect = overallRect.union(figureRect);
} }
} }
} }
if (overall != null) { }
centerRectangle(overall); if (overallRect != null) {
centerRectangle(overallRect);
} }
} }
@ -221,7 +219,15 @@ public class DiagramScene extends ObjectScene implements DiagramViewer {
@Override @Override
public void filteredChanged(SelectionCoordinator source) { public void filteredChanged(SelectionCoordinator source) {
gotoSelection(source.getSelectedObjects()); Set<Integer> ids = source.getSelectedObjects();
Set<Figure> figures = new HashSet<>();
for (Figure f : getModel().getDiagram().getFigures()) {
if (ids.contains(f.getInputNode().getId())) {
figures.add(f);
}
}
centerFigures(figures);
setSelectedObjects(idSetToObjectSet(ids));
validate(); validate();
} }
}; };
@ -286,6 +292,9 @@ public class DiagramScene extends ObjectScene implements DiagramViewer {
panAction = new CustomizablePanAction(MouseEvent.BUTTON1_DOWN_MASK); panAction = new CustomizablePanAction(MouseEvent.BUTTON1_DOWN_MASK);
getActions().addAction(panAction); getActions().addAction(panAction);
// handle default double-click, when not handled by other DoubleClickHandler
getActions().addAction(new DoubleClickAction(this));
selectAction = new CustomSelectAction(new SelectProvider() { selectAction = new CustomSelectAction(new SelectProvider() {
public boolean isAimingAllowed(Widget widget, Point localLocation, boolean invertSelection) { public boolean isAimingAllowed(Widget widget, Point localLocation, boolean invertSelection) {
return false; return false;
@ -375,7 +384,12 @@ public class DiagramScene extends ObjectScene implements DiagramViewer {
} }
} }
setSelectedObjects(selectedObjects); Set<Object> symmetricDiff = new HashSet<>(getSelectedObjects());
symmetricDiff.addAll(selectedObjects);
Set<Object> tmp = new HashSet<>(getSelectedObjects());
tmp.retainAll(selectedObjects);
symmetricDiff.removeAll(tmp);
setSelectedObjects(symmetricDiff);
}; };
getActions().addAction(ActionFactory.createRectangularSelectAction(rectangularSelectDecorator, selectLayer, rectangularSelectProvider)); getActions().addAction(ActionFactory.createRectangularSelectAction(rectangularSelectDecorator, selectLayer, rectangularSelectProvider));
@ -487,46 +501,42 @@ public class DiagramScene extends ObjectScene implements DiagramViewer {
return getModel().getHiddenNodes().isEmpty(); return getModel().getHiddenNodes().isEmpty();
} }
public Action createGotoAction(final Figure f) { public Action createGotoAction(final Figure figure) {
final DiagramScene diagramScene = this; String name = figure.getLines()[0];
String name = f.getLines()[0];
name += " ("; name += " (";
if (figure.getCluster() != null) {
if (f.getCluster() != null) { name += "B" + figure.getCluster().toString();
name += "B" + f.getCluster().toString();
} }
final boolean hidden = !getWidget(f, FigureWidget.class).isVisible(); boolean isHidden = !getWidget(figure, FigureWidget.class).isVisible();
if (hidden) { if (isHidden) {
if (f.getCluster() != null) { if (figure.getCluster() != null) {
name += ", "; name += ", ";
} }
name += "hidden"; name += "hidden";
} }
name += ")"; name += ")";
Action a = new AbstractAction(name, new ColorIcon(f.getColor())) { Action action = new AbstractAction(name, new ColorIcon(figure.getColor())) {
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
diagramScene.gotoFigure(f); setFigureSelection(Collections.singleton(figure));
centerFigures(Collections.singleton(figure));
} }
}; };
a.setEnabled(true); action.setEnabled(true);
return a; return action;
} }
public Action createGotoAction(final Block b) { public Action createGotoAction(final Block block) {
final DiagramScene diagramScene = this; String name = "B" + block.getInputBlock().getName();
String name = "B" + b.getInputBlock().getName(); Action action = new AbstractAction(name) {
Action a = new AbstractAction(name) {
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
diagramScene.gotoBlock(b); gotoBlock(block);
} }
}; };
a.setEnabled(true); action.setEnabled(true);
return a; return action;
} }
private void update() { private void update() {
@ -561,7 +571,7 @@ public class DiagramScene extends ObjectScene implements DiagramViewer {
f.setWidth(maxWidth.get(f.getBlock().getInputBlock())); f.setWidth(maxWidth.get(f.getBlock().getInputBlock()));
} }
FigureWidget w = new FigureWidget(f, hoverAction, selectAction, this, mainLayer); FigureWidget w = new FigureWidget(f, this, mainLayer);
w.getActions().addAction(ActionFactory.createPopupMenuAction(w)); w.getActions().addAction(ActionFactory.createPopupMenuAction(w));
w.getActions().addAction(selectAction); w.getActions().addAction(selectAction);
w.getActions().addAction(hoverAction); w.getActions().addAction(hoverAction);
@ -588,7 +598,8 @@ public class DiagramScene extends ObjectScene implements DiagramViewer {
if (getModel().getShowBlocks() || getModel().getShowCFG()) { if (getModel().getShowBlocks() || getModel().getShowCFG()) {
for (InputBlock bn : d.getInputBlocks()) { for (InputBlock bn : d.getInputBlocks()) {
BlockWidget w = new BlockWidget(this, d, bn); BlockWidget w = new BlockWidget(this, bn);
w.getActions().addAction(new DoubleClickAction(w));
w.setVisible(false); w.setVisible(false);
addObject(bn, w); addObject(bn, w);
blockLayer.addChild(w); blockLayer.addChild(w);
@ -891,6 +902,11 @@ public class DiagramScene extends ObjectScene implements DiagramViewer {
// and the selection action handles it instead // and the selection action handles it instead
} }
@Override
public void handleDoubleClick(Widget w, WidgetAction.WidgetMouseEvent e) {
setSelectedObjects(Collections.emptySet());
}
private class ConnectionSet { private class ConnectionSet {
private Set<Connection> connections; private Set<Connection> connections;
@ -932,38 +948,6 @@ public class DiagramScene extends ObjectScene implements DiagramViewer {
return result; return result;
} }
private void gotoSelection(Set<Integer> ids) {
Rectangle overall = null;
Set<Integer> hiddenNodes = new HashSet<>(getModel().getHiddenNodes());
hiddenNodes.removeAll(ids);
getModel().setHiddenNodes(hiddenNodes);
Set<Object> objects = idSetToObjectSet(ids);
for (Object o : objects) {
Widget w = getWidget(o);
if (w != null) {
Rectangle r = w.getBounds();
Point p = w.convertLocalToScene(new Point(0, 0));
assert r != null;
Rectangle r2 = new Rectangle(p.x, p.y, r.width, r.height);
if (overall == null) {
overall = r2;
} else {
overall = overall.union(r2);
}
}
}
if (overall != null) {
centerRectangle(overall);
}
setSelectedObjects(objects);
}
private void centerRectangle(Rectangle r) { private void centerRectangle(Rectangle r) {
Rectangle rect = convertSceneToView(r); Rectangle rect = convertSceneToView(r);
Rectangle viewRect = scrollPane.getViewport().getViewRect(); Rectangle viewRect = scrollPane.getViewport().getViewRect();
@ -986,7 +970,7 @@ public class DiagramScene extends ObjectScene implements DiagramViewer {
} }
@Override @Override
public void setSelection(Collection<Figure> list) { public void setFigureSelection(Set<Figure> list) {
super.setSelectedObjects(new HashSet<>(list)); super.setSelectedObjects(new HashSet<>(list));
} }
@ -1004,10 +988,6 @@ public class DiagramScene extends ObjectScene implements DiagramViewer {
return getUndoRedoManager(); return getUndoRedoManager();
} }
private boolean isVisible(Figure f) {
return !getModel().getHiddenNodes().contains(f.getInputNode().getId());
}
@Override @Override
public void componentHidden() { public void componentHidden() {
SelectionCoordinator.getInstance().getHighlightedChangedEvent().removeListener(highlightedCoordinatorListener); SelectionCoordinator.getInstance().getHighlightedChangedEvent().removeListener(highlightedCoordinatorListener);
@ -1122,31 +1102,6 @@ public class DiagramScene extends ObjectScene implements DiagramViewer {
validate(); validate();
} }
private void showFigure(Figure f) {
HashSet<Integer> newHiddenNodes = new HashSet<>(getModel().getHiddenNodes());
newHiddenNodes.remove(f.getInputNode().getId());
getModel().setHiddenNodes(newHiddenNodes);
}
private void centerWidget(Widget w) {
Rectangle r = w.getBounds();
Point p = w.getLocation();
assert r != null;
centerRectangle(new Rectangle(p.x, p.y, r.width, r.height));
}
public void gotoFigure(final Figure f) {
if (!isVisible(f)) {
showFigure(f);
}
FigureWidget fw = getWidget(f);
if (fw != null) {
centerWidget(fw);
setSelection(Collections.singletonList(f));
}
}
public JPopupMenu createPopupMenu() { public JPopupMenu createPopupMenu() {
JPopupMenu menu = new JPopupMenu(); JPopupMenu menu = new JPopupMenu();

View File

@ -242,14 +242,13 @@ public class DiagramViewModel extends RangeSliderModel implements ChangedListene
} }
public void showFigures(Collection<Figure> figures) { public void showFigures(Collection<Figure> figures) {
HashSet<Integer> newHiddenNodes = new HashSet<>(getHiddenNodes()); HashSet<Integer> newHiddenNodes = new HashSet<>(hiddenNodes);
for (Figure f : figures) { for (Figure f : figures) {
newHiddenNodes.remove(f.getInputNode().getId()); newHiddenNodes.remove(f.getInputNode().getId());
} }
setHiddenNodes(newHiddenNodes); setHiddenNodes(newHiddenNodes);
} }
public Set<Figure> getSelectedFigures() { public Set<Figure> getSelectedFigures() {
Set<Figure> result = new HashSet<>(); Set<Figure> result = new HashSet<>();
for (Figure f : diagram.getFigures()) { for (Figure f : diagram.getFigures()) {

View File

@ -31,7 +31,7 @@ import java.awt.Graphics2D;
import java.awt.Point; import java.awt.Point;
import java.awt.Rectangle; import java.awt.Rectangle;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.Set;
import javax.swing.JComponent; import javax.swing.JComponent;
import org.openide.awt.UndoRedo; import org.openide.awt.UndoRedo;
import org.openide.util.Lookup; import org.openide.util.Lookup;
@ -77,9 +77,9 @@ public interface DiagramViewer {
void componentShowing(); void componentShowing();
void setSelection(Collection<Figure> list); void setFigureSelection(Set<Figure> list);
void centerFigures(List<Figure> list); void centerFigures(Collection<Figure> list);
void setInteractionMode(InteractionMode mode); void setInteractionMode(InteractionMode mode);

View File

@ -27,7 +27,7 @@ package com.sun.hotspot.igv.view;
import com.sun.hotspot.igv.data.InputGraph; import com.sun.hotspot.igv.data.InputGraph;
import com.sun.hotspot.igv.data.InputNode; import com.sun.hotspot.igv.data.InputNode;
import com.sun.hotspot.igv.data.services.InputGraphProvider; import com.sun.hotspot.igv.data.services.InputGraphProvider;
import java.util.Set; import java.util.Collection;
import org.openide.util.lookup.ServiceProvider; import org.openide.util.lookup.ServiceProvider;
/** /**
@ -57,9 +57,16 @@ public class EditorInputGraphProvider implements InputGraphProvider {
} }
@Override @Override
public void setSelectedNodes(Set<InputNode> nodes) { public void addSelectedNodes(Collection<InputNode> nodes) {
if (editor != null && EditorTopComponent.isOpen(editor)) { if (editor != null && EditorTopComponent.isOpen(editor)) {
editor.setSelectedNodes(nodes); editor.addSelectedNodes(nodes, false);
}
}
@Override
public void clearSelectedNodes() {
if (editor != null && EditorTopComponent.isOpen(editor)) {
editor.clearSelectedNodes();
} }
} }

View File

@ -321,33 +321,25 @@ public final class EditorTopComponent extends TopComponent {
} }
} }
public void setSelectedFigures(List<Figure> list) { public void addSelectedNodes(Collection<InputNode> nodes, boolean centerSelection) {
scene.setSelection(list); Set<Integer> ids = new HashSet<>(getModel().getSelectedNodes());
scene.centerFigures(list);
}
public void setSelectedNodes(Set<InputNode> nodes) {
List<Figure> list = new ArrayList<>();
Set<Integer> ids = new HashSet<>();
for (InputNode n : nodes) { for (InputNode n : nodes) {
ids.add(n.getId()); ids.add(n.getId());
} }
Set<Figure> selectedFigures = new HashSet<>();
for (Figure f : getDiagram().getFigures()) { for (Figure f : getDiagram().getFigures()) {
if (ids.contains(f.getInputNode().getId())) { if (ids.contains(f.getInputNode().getId())) {
list.add(f); selectedFigures.add(f);
} }
} }
setSelectedFigures(list); scene.setFigureSelection(selectedFigures);
if (centerSelection) {
scene.centerFigures(selectedFigures);
}
} }
public void setSelectedNodes(InputBlock b) { public void clearSelectedNodes() {
List<Figure> list = new ArrayList<>(); scene.setFigureSelection(Collections.emptySet());
for (Figure f : getDiagram().getFigures()) {
if (f.getBlock().getInputBlock() == b) {
list.add(f);
}
}
setSelectedFigures(list);
} }
public Rectangle getSceneBounds() { public Rectangle getSceneBounds() {

View File

@ -108,24 +108,22 @@ public class NodeQuickSearch implements SearchProvider {
} }
if (matches != null) { if (matches != null) {
final Set<InputNode> set = new HashSet<>(matches); final Set<InputNode> nodeSet = new HashSet<>(matches);
final InputGraph theGraph = p.getGraph() != matchGraph ? matchGraph : null; final InputGraph theGraph = p.getGraph() != matchGraph ? matchGraph : null;
// Show "All N matching nodes" entry only if 1) there are // Show "All N matching nodes" entry only if 1) there are
// multiple matches and 2) the query does not only contain // multiple matches and 2) the query does not only contain
// digits (it is rare to select all nodes whose id contains a // digits (it is rare to select all nodes whose id contains a
// certain subsequence of digits). // certain subsequence of digits).
if (matches.size() > 1 && !rawValue.matches("\\d+")) { if (matches.size() > 1 && !rawValue.matches("\\d+")) {
if (!response.addResult(new Runnable() { if (!response.addResult(() -> {
@Override final EditorTopComponent editor = EditorTopComponent.getActive();
public void run() { if (editor != null) {
final EditorTopComponent comp = EditorTopComponent.getActive();
if (comp != null) {
if (theGraph != null) { if (theGraph != null) {
comp.getModel().selectGraph(theGraph); editor.getModel().selectGraph(theGraph);
}
comp.setSelectedNodes(set);
comp.requestActive();
} }
editor.clearSelectedNodes();
editor.addSelectedNodes(nodeSet, true);
editor.requestActive();
} }
}, },
"All " + matches.size() + " matching nodes (" + name + "=" + value + ")" + (theGraph != null ? " in " + theGraph.getName() : "") "All " + matches.size() + " matching nodes (" + name + "=" + value + ")" + (theGraph != null ? " in " + theGraph.getName() : "")
@ -145,15 +143,16 @@ public class NodeQuickSearch implements SearchProvider {
if (!response.addResult(new Runnable() { if (!response.addResult(new Runnable() {
@Override @Override
public void run() { public void run() {
final EditorTopComponent comp = EditorTopComponent.getActive(); final EditorTopComponent editor = EditorTopComponent.getActive();
if (comp != null) { if (editor != null) {
final Set<InputNode> tmpSet = new HashSet<>(); final Set<InputNode> tmpSet = new HashSet<>();
tmpSet.add(n); tmpSet.add(n);
if (theGraph != null) { if (theGraph != null) {
comp.getModel().selectGraph(theGraph); editor.getModel().selectGraph(theGraph);
} }
comp.setSelectedNodes(tmpSet); editor.clearSelectedNodes();
comp.requestActive(); editor.addSelectedNodes(tmpSet, true);
editor.requestActive();
} }
} }
}, },

View File

@ -38,27 +38,12 @@ abstract public class ExpandAdjacentAction extends CallableSystemAction {
protected void expandFigures(Function<Figure, List<Figure>> getAdjacentFigures) { protected void expandFigures(Function<Figure, List<Figure>> getAdjacentFigures) {
EditorTopComponent editor = EditorTopComponent.getActive(); EditorTopComponent editor = EditorTopComponent.getActive();
if (editor != null) { if (editor != null) {
Set<Figure> oldSelection = editor.getModel().getSelectedFigures(); Set<Figure> selectedFigured = editor.getModel().getSelectedFigures();
Set<Figure> figures = new HashSet<>(oldSelection); Set<Figure> expandedFigures = new HashSet<>(selectedFigured);
for (Figure f : editor.getModel().getDiagram().getFigures()) { for (Figure selectedFigure : selectedFigured) {
if (oldSelection.contains(f)) { expandedFigures.addAll(getAdjacentFigures.apply(selectedFigure));
continue;
} }
editor.getModel().showFigures(expandedFigures);
boolean ok = false;
for (Figure adjFig : getAdjacentFigures.apply(f)) {
if (oldSelection.contains(adjFig)) {
ok = true;
break;
}
}
if (ok) {
figures.add(f);
}
}
editor.getModel().showFigures(figures);
} }
} }

View File

@ -33,7 +33,7 @@ public final class ExpandPredecessorsAction extends ExpandAdjacentAction {
@Override @Override
public void performAction() { public void performAction() {
expandFigures(Figure::getSuccessors); expandFigures(Figure::getPredecessors);
} }
@Override @Override

View File

@ -33,7 +33,7 @@ public final class ExpandSuccessorsAction extends ExpandAdjacentAction {
@Override @Override
public void performAction() { public void performAction() {
expandFigures(Figure::getPredecessors); expandFigures(Figure::getSuccessors);
} }
@Override @Override

View File

@ -24,24 +24,29 @@
package com.sun.hotspot.igv.view.widgets; package com.sun.hotspot.igv.view.widgets;
import com.sun.hotspot.igv.data.InputBlock; import com.sun.hotspot.igv.data.InputBlock;
import com.sun.hotspot.igv.graph.Diagram; import com.sun.hotspot.igv.data.services.InputGraphProvider;
import com.sun.hotspot.igv.util.DoubleClickHandler;
import com.sun.hotspot.igv.util.LookupHistory;
import java.awt.*; import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.geom.Rectangle2D; import java.awt.geom.Rectangle2D;
import org.netbeans.api.visual.action.WidgetAction;
import org.netbeans.api.visual.widget.Scene; import org.netbeans.api.visual.widget.Scene;
import org.netbeans.api.visual.widget.Widget; import org.netbeans.api.visual.widget.Widget;
import org.openide.util.Utilities;
/** /**
* *
* @author Thomas Wuerthinger * @author Thomas Wuerthinger
*/ */
public class BlockWidget extends Widget { public class BlockWidget extends Widget implements DoubleClickHandler {
public static final Color BACKGROUND_COLOR = new Color(235, 235, 255); public static final Color BACKGROUND_COLOR = new Color(235, 235, 255);
private static final Font TITLE_FONT = new Font("Arial", Font.BOLD, 14); private static final Font TITLE_FONT = new Font("Arial", Font.BOLD, 14);
public static final Color TITLE_COLOR = new Color(42, 42, 171); public static final Color TITLE_COLOR = new Color(42, 42, 171);
private InputBlock blockNode; private final InputBlock blockNode;
public BlockWidget(Scene scene, Diagram d, InputBlock blockNode) { public BlockWidget(Scene scene, InputBlock blockNode) {
super(scene); super(scene);
this.blockNode = blockNode; this.blockNode = blockNode;
this.setBackground(BACKGROUND_COLOR); this.setBackground(BACKGROUND_COLOR);
@ -71,4 +76,26 @@ public class BlockWidget extends Widget {
g.drawString(s, r.x + 5, r.y + (int) r1.getHeight()); g.drawString(s, r.x + 5, r.y + (int) r1.getHeight());
g.setStroke(old); g.setStroke(old);
} }
private void addToSelection(BlockWidget blockWidget, boolean additiveSelection) {
InputGraphProvider graphProvider = LookupHistory.getLast(InputGraphProvider.class);
if (graphProvider != null) {
if (!additiveSelection) {
graphProvider.clearSelectedNodes();
}
graphProvider.addSelectedNodes(blockWidget.blockNode.getNodes());
}
}
private int getModifierMask () {
return Utilities.isMac() ? MouseEvent.META_DOWN_MASK : MouseEvent.CTRL_DOWN_MASK;
}
@Override
public void handleDoubleClick(Widget widget, WidgetAction.WidgetMouseEvent event) {
assert widget instanceof BlockWidget;
BlockWidget blockWidget = (BlockWidget) widget;
boolean additiveSelection = (event.getModifiersEx() & getModifierMask()) != 0;
addToSelection(blockWidget, additiveSelection);
}
} }

View File

@ -84,7 +84,7 @@ public class FigureWidget extends Widget implements Properties.Provider, PopupMe
return middleWidget.isHitAt(localLocation); return middleWidget.isHitAt(localLocation);
} }
public FigureWidget(final Figure f, WidgetAction hoverAction, WidgetAction selectAction, DiagramScene scene, Widget parent) { public FigureWidget(final Figure f, DiagramScene scene, Widget parent) {
super(scene); super(scene);
assert this.getScene() != null; assert this.getScene() != null;