mirror of
https://github.com/openjdk/jdk.git
synced 2026-07-28 11:53:09 +00:00
8309463: IGV: Dynamic graph layout algorithm
Reviewed-by: tholenstein, rcastanedalo, chagedorn
This commit is contained in:
parent
1d0250709a
commit
5cc64cc27a
@ -384,6 +384,19 @@ public class Figure extends Properties.Entity implements Vertex {
|
||||
return new Dimension(width, height);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (!(o instanceof Figure)) {
|
||||
return false;
|
||||
}
|
||||
return getInputNode().equals(((Figure) o).getInputNode());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return getInputNode().hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return idString;
|
||||
|
||||
@ -156,5 +156,17 @@ public class FigureConnection implements Connection {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (!(o instanceof FigureConnection)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return getInputSlot().getFigure().equals(((FigureConnection)o).getInputSlot().getFigure())
|
||||
&& getOutputSlot().getFigure().equals(((FigureConnection)o).getOutputSlot().getFigure())
|
||||
&& getInputSlot().getPosition() == ((FigureConnection)o).getInputSlot().getPosition()
|
||||
&& getOutputSlot().getPosition() == ((FigureConnection) o).getOutputSlot().getPosition();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@ -51,6 +51,11 @@
|
||||
<artifactId>Layout</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.sun.hotspot.igv</groupId>
|
||||
<artifactId>Util</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2023, 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
|
||||
@ -27,6 +27,7 @@ import com.sun.hotspot.igv.layout.LayoutGraph;
|
||||
import com.sun.hotspot.igv.layout.LayoutManager;
|
||||
import com.sun.hotspot.igv.layout.Link;
|
||||
import com.sun.hotspot.igv.layout.Vertex;
|
||||
import com.sun.hotspot.igv.util.Statistics;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Point;
|
||||
import java.util.*;
|
||||
@ -79,49 +80,6 @@ public class HierarchicalLayoutManager implements LayoutManager {
|
||||
private Set<? extends Link> importantLinks;
|
||||
private final Set<Link> linksToFollow;
|
||||
|
||||
private class LayoutNode {
|
||||
|
||||
public int x;
|
||||
public int y;
|
||||
public int width;
|
||||
public int height;
|
||||
public int layer = -1;
|
||||
public int xOffset;
|
||||
public int yOffset;
|
||||
public int bottomYOffset;
|
||||
public Vertex vertex; // Only used for non-dummy nodes, otherwise null
|
||||
|
||||
public List<LayoutEdge> preds = new ArrayList<>();
|
||||
public List<LayoutEdge> succs = new ArrayList<>();
|
||||
public HashMap<Integer, Integer> outOffsets = new HashMap<>();
|
||||
public HashMap<Integer, Integer> inOffsets = new HashMap<>();
|
||||
public int pos = -1; // Position within layer
|
||||
|
||||
public int crossingNumber;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Node " + vertex;
|
||||
}
|
||||
}
|
||||
|
||||
private class LayoutEdge {
|
||||
|
||||
public LayoutNode from;
|
||||
public LayoutNode to;
|
||||
// Horizontal distance relative to start of 'from'.
|
||||
public int relativeFrom;
|
||||
// Horizontal distance relative to start of 'to'.
|
||||
public int relativeTo;
|
||||
public Link link;
|
||||
public boolean vip;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Edge " + from + ", " + to;
|
||||
}
|
||||
}
|
||||
|
||||
private abstract static class AlgorithmPart {
|
||||
|
||||
public void start() {
|
||||
@ -190,6 +148,10 @@ public class HierarchicalLayoutManager implements LayoutManager {
|
||||
this.layoutSelfEdges = layoutSelfEdges;
|
||||
}
|
||||
|
||||
public List<LayoutNode> getNodes() {
|
||||
return nodes;
|
||||
}
|
||||
|
||||
// Remove self-edges, possibly saving them into the selfEdges set.
|
||||
private void removeSelfEdges(boolean save) {
|
||||
for (LayoutNode node : nodes) {
|
||||
@ -305,7 +267,7 @@ public class HierarchicalLayoutManager implements LayoutManager {
|
||||
for (LayoutNode n : nodes) {
|
||||
|
||||
for (LayoutEdge e : n.preds) {
|
||||
if (e.link != null) {
|
||||
if (e.link != null && !linkPositions.containsKey(e.link)) {
|
||||
ArrayList<Point> points = new ArrayList<>();
|
||||
|
||||
Point p = new Point(e.to.x + e.relativeTo, e.to.y + e.to.yOffset + e.link.getTo().getRelativePosition().y);
|
||||
@ -386,14 +348,11 @@ public class HierarchicalLayoutManager implements LayoutManager {
|
||||
linkPositions.put(e.link, points);
|
||||
}
|
||||
pointCount += points.size();
|
||||
|
||||
// No longer needed!
|
||||
e.link = null;
|
||||
}
|
||||
}
|
||||
|
||||
for (LayoutEdge e : n.succs) {
|
||||
if (e.link != null) {
|
||||
if (e.link != null && !linkPositions.containsKey(e.link)) {
|
||||
ArrayList<Point> points = new ArrayList<>();
|
||||
Point p = new Point(e.from.x + e.relativeFrom, e.from.y + e.from.height - e.from.bottomYOffset + e.link.getFrom().getRelativePosition().y);
|
||||
points.add(p);
|
||||
@ -470,7 +429,6 @@ public class HierarchicalLayoutManager implements LayoutManager {
|
||||
}
|
||||
|
||||
pointCount += points.size();
|
||||
e.link = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -526,8 +484,8 @@ public class HierarchicalLayoutManager implements LayoutManager {
|
||||
}
|
||||
}
|
||||
|
||||
private static final Comparator<LayoutNode> nodePositionComparator = Comparator.comparingInt(n -> n.pos);
|
||||
private static final Comparator<LayoutNode> nodeProcessingDownComparator = (n1, n2) -> {
|
||||
public static final Comparator<LayoutNode> nodePositionComparator = Comparator.comparingInt(n -> n.pos);
|
||||
public static final Comparator<LayoutNode> nodeProcessingDownComparator = (n1, n2) -> {
|
||||
int n1VIP = 0;
|
||||
for (LayoutEdge e : n1.preds) {
|
||||
if (e.vip) {
|
||||
@ -554,7 +512,7 @@ public class HierarchicalLayoutManager implements LayoutManager {
|
||||
}
|
||||
return n1.preds.size() - n2.preds.size();
|
||||
};
|
||||
private static final Comparator<LayoutNode> nodeProcessingUpComparator = (n1, n2) -> {
|
||||
public static final Comparator<LayoutNode> nodeProcessingUpComparator = (n1, n2) -> {
|
||||
int n1VIP = 0;
|
||||
for (LayoutEdge e : n1.succs) {
|
||||
if (e.vip) {
|
||||
@ -661,7 +619,7 @@ public class HierarchicalLayoutManager implements LayoutManager {
|
||||
LayoutEdge e = n.preds.get(i);
|
||||
values[i] = e.from.x + e.relativeFrom - e.relativeTo;
|
||||
}
|
||||
return median(values);
|
||||
return Statistics.median(values);
|
||||
} else {
|
||||
int z = 0;
|
||||
int[] values = new int[vipCount];
|
||||
@ -671,7 +629,7 @@ public class HierarchicalLayoutManager implements LayoutManager {
|
||||
values[z++] = e.from.x + e.relativeFrom - e.relativeTo;
|
||||
}
|
||||
}
|
||||
return median(values);
|
||||
return Statistics.median(values);
|
||||
}
|
||||
}
|
||||
|
||||
@ -693,7 +651,7 @@ public class HierarchicalLayoutManager implements LayoutManager {
|
||||
i++;
|
||||
}
|
||||
|
||||
return median(values);
|
||||
return Statistics.median(values);
|
||||
}
|
||||
|
||||
private int calculateOptimalUp(LayoutNode n) {
|
||||
@ -709,16 +667,7 @@ public class HierarchicalLayoutManager implements LayoutManager {
|
||||
return values[i];
|
||||
}
|
||||
}
|
||||
return median(values);
|
||||
}
|
||||
|
||||
private int median(int[] values) {
|
||||
Arrays.sort(values);
|
||||
if (values.length % 2 == 0) {
|
||||
return (values[values.length / 2 - 1] + values[values.length / 2]) / 2;
|
||||
} else {
|
||||
return values[values.length / 2];
|
||||
}
|
||||
return Statistics.median(values);
|
||||
}
|
||||
|
||||
private void sweepUp() {
|
||||
@ -742,7 +691,7 @@ public class HierarchicalLayoutManager implements LayoutManager {
|
||||
}
|
||||
}
|
||||
|
||||
private static class NodeRow {
|
||||
public static class NodeRow {
|
||||
|
||||
private final TreeSet<LayoutNode> treeSet;
|
||||
private final ArrayList<Integer> space;
|
||||
@ -831,6 +780,9 @@ public class HierarchicalLayoutManager implements LayoutManager {
|
||||
if (!visited.contains(e.to)) {
|
||||
visited.add(e.to);
|
||||
layers[i + 1].add(e.to);
|
||||
if (!nodes.contains(e.to)) {
|
||||
nodes.add(e.to);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1221,7 +1173,7 @@ public class HierarchicalLayoutManager implements LayoutManager {
|
||||
} else {
|
||||
ArrayList<LayoutNode> currentNodes = new ArrayList<>(nodes);
|
||||
for (LayoutNode n : currentNodes) {
|
||||
for (LayoutEdge e : n.succs) {
|
||||
for (LayoutEdge e : List.copyOf(n.succs)) {
|
||||
processSingleEdge(e);
|
||||
}
|
||||
}
|
||||
@ -1229,10 +1181,10 @@ public class HierarchicalLayoutManager implements LayoutManager {
|
||||
}
|
||||
|
||||
private void processSingleEdge(LayoutEdge e) {
|
||||
LayoutNode n = e.from;
|
||||
if (e.to.layer > n.layer + 1) {
|
||||
LayoutNode n = e.to;
|
||||
if (e.to.layer - 1 > e.from.layer) {
|
||||
LayoutEdge last = e;
|
||||
for (int i = n.layer + 1; i < last.to.layer; i++) {
|
||||
for (int i = n.layer - 1; i > last.from.layer; i--) {
|
||||
last = addBetween(last, i);
|
||||
}
|
||||
}
|
||||
@ -1240,22 +1192,23 @@ public class HierarchicalLayoutManager implements LayoutManager {
|
||||
|
||||
private LayoutEdge addBetween(LayoutEdge e, int layer) {
|
||||
LayoutNode n = new LayoutNode();
|
||||
n.width = dummyWidth;
|
||||
n.height = dummyHeight;
|
||||
n.width = DUMMY_WIDTH;
|
||||
n.height = DUMMY_HEIGHT;
|
||||
n.layer = layer;
|
||||
n.preds.add(e);
|
||||
n.succs.add(e);
|
||||
nodes.add(n);
|
||||
LayoutEdge result = new LayoutEdge();
|
||||
result.vip = e.vip;
|
||||
n.succs.add(result);
|
||||
result.from = n;
|
||||
result.relativeFrom = n.width / 2;
|
||||
result.to = e.to;
|
||||
result.relativeTo = e.relativeTo;
|
||||
e.relativeTo = n.width / 2;
|
||||
e.to.preds.remove(e);
|
||||
e.to.preds.add(result);
|
||||
e.to = n;
|
||||
n.preds.add(result);
|
||||
result.to = n;
|
||||
result.relativeTo = n.width / 2;
|
||||
result.from = e.from;
|
||||
result.relativeFrom = e.relativeFrom;
|
||||
result.link = e.link;
|
||||
e.relativeFrom = n.width / 2;
|
||||
e.from.succs.remove(e);
|
||||
e.from.succs.add(result);
|
||||
e.from = n;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) 2023, 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.hierarchicallayout;
|
||||
|
||||
import com.sun.hotspot.igv.layout.Link;
|
||||
|
||||
public class LayoutEdge {
|
||||
|
||||
public LayoutNode from;
|
||||
public LayoutNode to;
|
||||
// Horizontal distance relative to start of 'from'.
|
||||
public int relativeFrom;
|
||||
// Horizontal distance relative to start of 'to'.
|
||||
public int relativeTo;
|
||||
public Link link;
|
||||
public boolean vip;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Edge " + from + ", " + to;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (c) 2023, 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.hierarchicallayout;
|
||||
|
||||
import com.sun.hotspot.igv.layout.Vertex;
|
||||
import java.util.*;
|
||||
|
||||
public class LayoutNode {
|
||||
|
||||
public int x;
|
||||
public int y;
|
||||
public int width;
|
||||
public int height;
|
||||
public int layer = -1;
|
||||
public int xOffset;
|
||||
public int yOffset;
|
||||
public int bottomYOffset;
|
||||
public Vertex vertex; // Only used for non-dummy nodes, otherwise null
|
||||
|
||||
public List<LayoutEdge> preds = new ArrayList<>();
|
||||
public List<LayoutEdge> succs = new ArrayList<>();
|
||||
public HashMap<Integer, Integer> outOffsets = new HashMap<>();
|
||||
public HashMap<Integer, Integer> inOffsets = new HashMap<>();
|
||||
public int pos = -1; // Position within layer
|
||||
|
||||
public int crossingNumber;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Node " + vertex;
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2023, 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
|
||||
@ -36,6 +36,7 @@ public class Settings {
|
||||
public static final int SEA_OF_NODES = 0;
|
||||
public static final int CLUSTERED_SEA_OF_NODES = 1;
|
||||
public static final int CONTROL_FLOW_GRAPH = 2;
|
||||
public static final int STABLE_SEA_OF_NODES = 3;
|
||||
}
|
||||
|
||||
public static final String NODE_TEXT = "nodeText";
|
||||
|
||||
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) 2023, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.util;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class Statistics {
|
||||
|
||||
public static int median(int[] values) {
|
||||
Arrays.sort(values);
|
||||
if (values.length % 2 == 0) {
|
||||
return (values[values.length / 2 - 1] + values[values.length / 2]) / 2;
|
||||
} else {
|
||||
return values[values.length / 2];
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -26,10 +26,7 @@ package com.sun.hotspot.igv.view;
|
||||
import com.sun.hotspot.igv.data.Properties;
|
||||
import com.sun.hotspot.igv.data.*;
|
||||
import com.sun.hotspot.igv.graph.*;
|
||||
import com.sun.hotspot.igv.hierarchicallayout.HierarchicalCFGLayoutManager;
|
||||
import com.sun.hotspot.igv.hierarchicallayout.HierarchicalClusterLayoutManager;
|
||||
import com.sun.hotspot.igv.hierarchicallayout.HierarchicalLayoutManager;
|
||||
import com.sun.hotspot.igv.hierarchicallayout.LinearLayoutManager;
|
||||
import com.sun.hotspot.igv.hierarchicallayout.*;
|
||||
import com.sun.hotspot.igv.layout.LayoutGraph;
|
||||
import com.sun.hotspot.igv.selectioncoordinator.SelectionCoordinator;
|
||||
import com.sun.hotspot.igv.util.ColorIcon;
|
||||
@ -87,6 +84,7 @@ public class DiagramScene extends ObjectScene implements DiagramViewer, DoubleCl
|
||||
private final DiagramViewModel model;
|
||||
private ModelState modelState;
|
||||
private boolean rebuilding;
|
||||
private final HierarchicalStableLayoutManager hierarchicalStableLayoutManager;
|
||||
|
||||
/**
|
||||
* The alpha level of partially visible figures.
|
||||
@ -487,6 +485,8 @@ public class DiagramScene extends ObjectScene implements DiagramViewer, DoubleCl
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
hierarchicalStableLayoutManager = new HierarchicalStableLayoutManager();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -688,10 +688,15 @@ public class DiagramScene extends ObjectScene implements DiagramViewer, DoubleCl
|
||||
return w1.isVisible() && w2.isVisible();
|
||||
}
|
||||
|
||||
private void doStableSeaLayout(HashSet<Figure> visibleFigures, HashSet<Connection> visibleConnections) {
|
||||
hierarchicalStableLayoutManager.updateLayout(visibleFigures, visibleConnections);
|
||||
}
|
||||
|
||||
private void doSeaLayout(HashSet<Figure> figures, HashSet<Connection> edges) {
|
||||
HierarchicalLayoutManager manager = new HierarchicalLayoutManager(HierarchicalLayoutManager.Combine.SAME_OUTPUTS);
|
||||
manager.setMaxLayerLength(10);
|
||||
manager.doLayout(new LayoutGraph(edges, figures));
|
||||
hierarchicalStableLayoutManager.setShouldRedrawLayout(true);
|
||||
}
|
||||
|
||||
private void doClusteredLayout(HashSet<Connection> edges) {
|
||||
@ -1187,7 +1192,9 @@ public class DiagramScene extends ObjectScene implements DiagramViewer, DoubleCl
|
||||
|
||||
HashSet<Figure> visibleFigures = getVisibleFigures();
|
||||
HashSet<Connection> visibleConnections = getVisibleConnections();
|
||||
if (getModel().getShowSea()) {
|
||||
if (getModel().getShowStableSea()) {
|
||||
doStableSeaLayout(visibleFigures, visibleConnections);
|
||||
} else if (getModel().getShowSea()) {
|
||||
doSeaLayout(visibleFigures, visibleConnections);
|
||||
} else if (getModel().getShowBlocks()) {
|
||||
doClusteredLayout(visibleConnections);
|
||||
|
||||
@ -62,6 +62,7 @@ public class DiagramViewModel extends RangeSliderModel implements ChangedListene
|
||||
private final ChangedEvent<DiagramViewModel> selectedNodesChangedEvent = new ChangedEvent<>(this);
|
||||
private final ChangedEvent<DiagramViewModel> hiddenNodesChangedEvent = new ChangedEvent<>(this);
|
||||
private ChangedListener<InputGraph> titleChangedListener = g -> {};
|
||||
private boolean showStableSea;
|
||||
private boolean showSea;
|
||||
private boolean showBlocks;
|
||||
private boolean showCFG;
|
||||
@ -90,6 +91,17 @@ public class DiagramViewModel extends RangeSliderModel implements ChangedListene
|
||||
}
|
||||
}
|
||||
|
||||
public boolean getShowStableSea() {
|
||||
return showStableSea;
|
||||
}
|
||||
|
||||
public void setShowStableSea(boolean enable) {
|
||||
showStableSea = enable;
|
||||
if (enable) {
|
||||
diagramChangedEvent.fire();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean getShowSea() {
|
||||
return showSea;
|
||||
}
|
||||
@ -216,6 +228,7 @@ public class DiagramViewModel extends RangeSliderModel implements ChangedListene
|
||||
filtersOrder = provider.getAllFiltersOrdered();
|
||||
|
||||
globalSelection = GlobalSelectionAction.get(GlobalSelectionAction.class).isSelected();
|
||||
showStableSea = Settings.get().getInt(Settings.DEFAULT_VIEW, Settings.DEFAULT_VIEW_DEFAULT) == Settings.DefaultView.STABLE_SEA_OF_NODES;
|
||||
showSea = Settings.get().getInt(Settings.DEFAULT_VIEW, Settings.DEFAULT_VIEW_DEFAULT) == Settings.DefaultView.SEA_OF_NODES;
|
||||
showBlocks = Settings.get().getInt(Settings.DEFAULT_VIEW, Settings.DEFAULT_VIEW_DEFAULT) == Settings.DefaultView.CLUSTERED_SEA_OF_NODES;
|
||||
showCFG = Settings.get().getInt(Settings.DEFAULT_VIEW, Settings.DEFAULT_VIEW_DEFAULT) == Settings.DefaultView.CONTROL_FLOW_GRAPH;
|
||||
|
||||
@ -175,6 +175,11 @@ public final class EditorTopComponent extends TopComponent implements TopCompone
|
||||
toolBar.addSeparator();
|
||||
ButtonGroup layoutButtons = new ButtonGroup();
|
||||
|
||||
JToggleButton stableSeaLayoutButton = new JToggleButton(new EnableStableSeaLayoutAction(this));
|
||||
stableSeaLayoutButton.setSelected(diagramViewModel.getShowStableSea());
|
||||
layoutButtons.add(stableSeaLayoutButton);
|
||||
toolBar.add(stableSeaLayoutButton);
|
||||
|
||||
JToggleButton seaLayoutButton = new JToggleButton(new EnableSeaLayoutAction(this));
|
||||
seaLayoutButton.setSelected(diagramViewModel.getShowSea());
|
||||
layoutButtons.add(seaLayoutButton);
|
||||
@ -191,6 +196,17 @@ public final class EditorTopComponent extends TopComponent implements TopCompone
|
||||
layoutButtons.add(cfgLayoutButton);
|
||||
toolBar.add(cfgLayoutButton);
|
||||
|
||||
diagramViewModel.getGraphChangedEvent().addListener(model -> {
|
||||
// HierarchicalStableLayoutManager is not reliable for difference graphs
|
||||
boolean isDiffGraph = model.getGraph().isDiffGraph();
|
||||
// deactivate HierarchicalStableLayoutManager for difference graphs
|
||||
stableSeaLayoutButton.setEnabled(!isDiffGraph);
|
||||
if (stableSeaLayoutButton.isSelected() && isDiffGraph) {
|
||||
// fallback to HierarchicalLayoutManager for difference graphs
|
||||
seaLayoutButton.setSelected(true);
|
||||
}
|
||||
});
|
||||
|
||||
toolBar.addSeparator();
|
||||
toolBar.add(new JToggleButton(new PredSuccAction(diagramViewModel.getShowNodeHull())));
|
||||
toolBar.add(new JToggleButton(new ShowEmptyBlocksAction(cfgLayoutAction, diagramViewModel.getShowEmptyBlocks())));
|
||||
|
||||
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (c) 2023, 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 com.sun.hotspot.igv.view.EditorTopComponent;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
|
||||
public class EnableStableSeaLayoutAction extends EnableLayoutAction {
|
||||
|
||||
public EnableStableSeaLayoutAction(EditorTopComponent etc) {
|
||||
super(etc);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String iconResource() {
|
||||
return "com/sun/hotspot/igv/view/images/stable_sea.png";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getDescription() {
|
||||
return "Show stable sea of nodes";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
editor.getModel().setShowStableSea(this.isSelected());
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 2.1 KiB |
Loading…
x
Reference in New Issue
Block a user