8283930: IGV: add toggle button to show/hide empty blocks in CFG view
Reviewed-by: kvn, chagedorn
This commit is contained in:
parent
a445ecd1e9
commit
6028181071
@ -100,11 +100,6 @@ public class BlockConnection implements Connection {
|
||||
controlPoints = list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAlwaysVisible() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSlots() {
|
||||
return false;
|
||||
|
@ -41,8 +41,6 @@ public interface Connection extends Link {
|
||||
|
||||
public String getToolTipText();
|
||||
|
||||
public boolean isAlwaysVisible();
|
||||
|
||||
public boolean hasSlots();
|
||||
|
||||
}
|
||||
|
@ -148,11 +148,6 @@ public class FigureConnection implements Connection {
|
||||
controlPoints = list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAlwaysVisible() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSlots() {
|
||||
return true;
|
||||
|
@ -605,17 +605,22 @@ public class DiagramScene extends ObjectScene implements DiagramViewer {
|
||||
}
|
||||
|
||||
private boolean isVisible(Connection c) {
|
||||
if (getModel().getShowCFG()) {
|
||||
return c.isAlwaysVisible();
|
||||
// Generally, a connection is visible if its source and destination
|
||||
// widgets are visible. An exception is Figure connections in the CFG
|
||||
// view, which are never shown.
|
||||
if (getModel().getShowCFG() && c instanceof FigureConnection) {
|
||||
return false;
|
||||
}
|
||||
FigureWidget w1 = getWidget(c.getFrom().getVertex());
|
||||
FigureWidget w2 = getWidget(c.getTo().getVertex());
|
||||
|
||||
if (w1.isVisible() && w2.isVisible()) {
|
||||
return true;
|
||||
Widget w1, w2;
|
||||
if (c instanceof BlockConnection) {
|
||||
w1 = getWidget(((Block)c.getFromCluster()).getInputBlock());
|
||||
w2 = getWidget(((Block)c.getToCluster()).getInputBlock());
|
||||
} else {
|
||||
assert (c instanceof FigureConnection);
|
||||
w1 = getWidget(c.getFrom().getVertex());
|
||||
w2 = getWidget(c.getTo().getVertex());
|
||||
}
|
||||
|
||||
return false;
|
||||
return w1.isVisible() && w2.isVisible();
|
||||
}
|
||||
|
||||
private void relayout(Set<Widget> oldVisibleWidgets) {
|
||||
@ -697,10 +702,21 @@ public class DiagramScene extends ObjectScene implements DiagramViewer {
|
||||
}
|
||||
}
|
||||
}
|
||||
// Add connections for CFG edges.
|
||||
edges.addAll(diagram.getBlockConnections());
|
||||
// Add visible connections for CFG edges.
|
||||
for (BlockConnection c : diagram.getBlockConnections()) {
|
||||
if (isVisible(c)) {
|
||||
edges.add(c);
|
||||
}
|
||||
}
|
||||
m.setSubManager(new LinearLayoutManager(figureRank));
|
||||
m.setClusters(new HashSet<>(diagram.getBlocks()));
|
||||
Set<Block> visibleBlocks = new HashSet<>();
|
||||
for (Block b : diagram.getBlocks()) {
|
||||
BlockWidget w = getWidget(b.getInputBlock());
|
||||
if (w.isVisible()) {
|
||||
visibleBlocks.add(b);
|
||||
}
|
||||
}
|
||||
m.setClusters(new HashSet<>(visibleBlocks));
|
||||
m.doLayout(new LayoutGraph(edges, figures));
|
||||
}
|
||||
|
||||
@ -795,8 +811,9 @@ public class DiagramScene extends ObjectScene implements DiagramViewer {
|
||||
|
||||
if (getModel().getShowCFG()) {
|
||||
for (BlockConnection c : diagram.getBlockConnections()) {
|
||||
SceneAnimator anim = animator;
|
||||
processOutputSlot(lastLineCache, null, Collections.singletonList(c), 0, null, null, offx2, offy2, anim);
|
||||
if (isVisible(c)) {
|
||||
processOutputSlot(lastLineCache, null, Collections.singletonList(c), 0, null, null, offx2, offy2, animator);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1211,18 +1228,19 @@ public class DiagramScene extends ObjectScene implements DiagramViewer {
|
||||
w.setVisible(false);
|
||||
}
|
||||
}
|
||||
visibleBlocks.clear();
|
||||
for (InputBlock b : diagram.getGraph().getBlocks()) {
|
||||
if (!b.isArtificial()) {
|
||||
visibleBlocks.add(b);
|
||||
}
|
||||
if (getModel().getShowEmptyBlocks()) {
|
||||
// Add remaining blocks.
|
||||
visibleBlocks.addAll(diagram.getGraph().getBlocks());
|
||||
}
|
||||
}
|
||||
|
||||
if (getModel().getShowBlocks() || getModel().getShowCFG()) {
|
||||
for (InputBlock b : diagram.getGraph().getBlocks()) {
|
||||
|
||||
boolean visibleAfter = visibleBlocks.contains(b);
|
||||
// A block is visible if it is marked as such, except for
|
||||
// artificial or null blocks in the CFG view.
|
||||
boolean visibleAfter = visibleBlocks.contains(b) &&
|
||||
!(getModel().getShowCFG() && (b.isArtificial() || b.getNodes().isEmpty()));
|
||||
|
||||
BlockWidget w = getWidget(b);
|
||||
if (visibleAfter) {
|
||||
|
@ -62,6 +62,7 @@ public class DiagramViewModel extends RangeSliderModel implements ChangedListene
|
||||
private boolean showBlocks;
|
||||
private boolean showCFG;
|
||||
private boolean showNodeHull;
|
||||
private boolean showEmptyBlocks;
|
||||
private boolean hideDuplicates;
|
||||
private ChangedListener<FilterChain> filterChainChangedListener = new ChangedListener<FilterChain>() {
|
||||
|
||||
@ -166,6 +167,15 @@ public class DiagramViewModel extends RangeSliderModel implements ChangedListene
|
||||
viewPropertiesChangedEvent.fire();
|
||||
}
|
||||
|
||||
public boolean getShowEmptyBlocks() {
|
||||
return showEmptyBlocks;
|
||||
}
|
||||
|
||||
public void setShowEmptyBlocks(boolean b) {
|
||||
showEmptyBlocks = b;
|
||||
viewPropertiesChangedEvent.fire();
|
||||
}
|
||||
|
||||
public boolean getHideDuplicates() {
|
||||
return hideDuplicates;
|
||||
}
|
||||
@ -194,6 +204,7 @@ public class DiagramViewModel extends RangeSliderModel implements ChangedListene
|
||||
this.showBlocks = Settings.get().getInt(Settings.DEFAULT_VIEW, Settings.DEFAULT_VIEW_DEFAULT) == Settings.DefaultView.CLUSTERED_SEA_OF_NODES;
|
||||
this.showCFG = Settings.get().getInt(Settings.DEFAULT_VIEW, Settings.DEFAULT_VIEW_DEFAULT) == Settings.DefaultView.CONTROL_FLOW_GRAPH;
|
||||
this.showNodeHull = true;
|
||||
this.showEmptyBlocks = true;
|
||||
this.group = g;
|
||||
filterGraphs();
|
||||
assert filterChain != null;
|
||||
|
@ -99,6 +99,7 @@ public final class EditorTopComponent extends TopComponent implements PropertyCh
|
||||
private OverviewAction overviewAction;
|
||||
private HideDuplicatesAction hideDuplicatesAction;
|
||||
private PredSuccAction predSuccAction;
|
||||
private ShowEmptyBlocksAction showEmptyBlocksAction;
|
||||
private SelectionModeAction selectionModeAction;
|
||||
private PanModeAction panModeAction;
|
||||
private boolean notFirstTime;
|
||||
@ -279,6 +280,13 @@ public final class EditorTopComponent extends TopComponent implements PropertyCh
|
||||
toolBar.add(button);
|
||||
predSuccAction.addPropertyChangeListener(this);
|
||||
|
||||
showEmptyBlocksAction = new ShowEmptyBlocksAction();
|
||||
button = new JToggleButton(showEmptyBlocksAction);
|
||||
button.setSelected(true);
|
||||
button.setEnabled(Settings.get().getInt(Settings.DEFAULT_VIEW, Settings.DEFAULT_VIEW_DEFAULT) == Settings.DefaultView.CONTROL_FLOW_GRAPH);
|
||||
toolBar.add(button);
|
||||
showEmptyBlocksAction.addPropertyChangeListener(this);
|
||||
|
||||
hideDuplicatesAction = new HideDuplicatesAction();
|
||||
hideDuplicatesButton = new JToggleButton(hideDuplicatesAction);
|
||||
hideDuplicatesButton.setSelected(false);
|
||||
@ -546,6 +554,9 @@ public final class EditorTopComponent extends TopComponent implements PropertyCh
|
||||
if (evt.getSource() == this.predSuccAction) {
|
||||
boolean b = (Boolean) predSuccAction.getValue(PredSuccAction.STATE);
|
||||
this.getModel().setShowNodeHull(b);
|
||||
} else if (evt.getSource() == this.showEmptyBlocksAction) {
|
||||
boolean b = (Boolean) showEmptyBlocksAction.getValue(ShowEmptyBlocksAction.STATE);
|
||||
this.getModel().setShowEmptyBlocks(b);
|
||||
} else if (evt.getSource() == this.overviewAction) {
|
||||
boolean b = (Boolean) overviewAction.getValue(OverviewAction.STATE);
|
||||
if (b) {
|
||||
@ -556,12 +567,15 @@ public final class EditorTopComponent extends TopComponent implements PropertyCh
|
||||
} else if (evt.getSource() == this.seaLayoutAction) {
|
||||
boolean b = seaLayoutAction.isSelected();
|
||||
this.getModel().setShowSea(b);
|
||||
this.showEmptyBlocksAction.setEnabled(false);
|
||||
} else if (evt.getSource() == this.blockLayoutAction) {
|
||||
boolean b = blockLayoutAction.isSelected();
|
||||
this.getModel().setShowBlocks(b);
|
||||
this.showEmptyBlocksAction.setEnabled(false);
|
||||
} else if (evt.getSource() == this.cfgLayoutAction) {
|
||||
boolean b = cfgLayoutAction.isSelected();
|
||||
this.getModel().setShowCFG(b);
|
||||
this.showEmptyBlocksAction.setEnabled(true);
|
||||
} else if (evt.getSource() == this.hideDuplicatesAction) {
|
||||
boolean b = (Boolean) hideDuplicatesAction.getValue(HideDuplicatesAction.STATE);
|
||||
this.getModel().setHideDuplicates(b);
|
||||
|
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (c) 2022, 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.view.actions;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.Action;
|
||||
import javax.swing.ImageIcon;
|
||||
import org.openide.util.ImageUtilities;
|
||||
|
||||
public class ShowEmptyBlocksAction extends AbstractAction {
|
||||
|
||||
private boolean state;
|
||||
public static final String STATE = "state";
|
||||
|
||||
public ShowEmptyBlocksAction() {
|
||||
state = true;
|
||||
putValue(AbstractAction.SMALL_ICON, new ImageIcon(ImageUtilities.loadImage(iconResource())));
|
||||
putValue(STATE, true);
|
||||
putValue(Action.SHORT_DESCRIPTION, "Show empty blocks in control-flow graph view");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent ev) {
|
||||
this.state = !state;
|
||||
this.putValue(STATE, state);
|
||||
}
|
||||
|
||||
protected String iconResource() {
|
||||
return "com/sun/hotspot/igv/view/images/showEmptyBlocks.png";
|
||||
}
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 1.7 KiB |
@ -17,6 +17,7 @@
|
||||
<file name="com-sun-hotspot-igv-view-actions-ZoomOutAction.instance"><attr name="position" intvalue="2001"/></file>
|
||||
<file name="com-sun-hotspot-igv-view-actions-OverviewAction.instance"><attr name="position" intvalue="2001"/></file>
|
||||
<file name="com-sun-hotspot-igv-view-actions-PredSuccAction.instance"><attr name="position" intvalue="2001"/></file>
|
||||
<file name="com-sun-hotspot-igv-view-actions-ShowEmptyBlocksAction.instance"><attr name="position" intvalue="2001"/></file>
|
||||
<file name="com-sun-hotspot-igv-view-actions-EnableSeaLayoutAction.instance"><attr name="position" intvalue="2001"/></file>
|
||||
<file name="com-sun-hotspot-igv-view-actions-EnableBlockLayoutAction.instance"><attr name="position" intvalue="2001"/></file>
|
||||
<file name="com-sun-hotspot-igv-view-actions-EnableCFGLayoutAction.instance"><attr name="position" intvalue="2001"/></file>
|
||||
|
Loading…
Reference in New Issue
Block a user