8293480: IGV: Update Bytecode and ControlFlow Component immediately when opening a new graph

Reviewed-by: rcastanedalo, chagedorn
This commit is contained in:
Tobias Holenstein 2022-09-21 08:08:13 +00:00
parent 8ecdaa6811
commit 4e7cb156c8
11 changed files with 200 additions and 267 deletions
src/utils/IdealGraphVisualizer
Bytecodes/src/main/java/com/sun/hotspot/igv/bytecodes
ControlFlow/src/main/java/com/sun/hotspot/igv/controlflow
Coordinator/src/main/java/com/sun/hotspot/igv/coordinator
FilterWindow/src/main/java/com/sun/hotspot/igv/filterwindow
Graph/src/main/java/com/sun/hotspot/igv/graph/services
Util/src/main/java/com/sun/hotspot/igv/util
View/src/main/java/com/sun/hotspot/igv/view

@ -23,13 +23,13 @@
*/
package com.sun.hotspot.igv.bytecodes;
import com.sun.hotspot.igv.data.ChangedListener;
import com.sun.hotspot.igv.data.Group;
import com.sun.hotspot.igv.data.InputGraph;
import com.sun.hotspot.igv.data.services.InputGraphProvider;
import com.sun.hotspot.igv.util.LookupHistory;
import java.awt.BorderLayout;
import java.io.Serializable;
import javax.swing.SwingUtilities;
import org.openide.ErrorManager;
import org.openide.explorer.ExplorerManager;
import org.openide.explorer.ExplorerUtils;
@ -41,13 +41,12 @@ import org.openide.windows.WindowManager;
/**
* @author Thomas Wuerthinger
*/
final class BytecodeViewTopComponent extends TopComponent implements ExplorerManager.Provider, LookupListener {
final class BytecodeViewTopComponent extends TopComponent implements ExplorerManager.Provider, ChangedListener<InputGraphProvider> {
private static BytecodeViewTopComponent instance;
private static final String PREFERRED_ID = "BytecodeViewTopComponent";
private ExplorerManager manager;
private BeanTreeView treeView;
private Lookup.Result result = null;
private final ExplorerManager manager;
private final BeanTreeView treeView;
private MethodNode rootNode;
private BytecodeViewTopComponent() {
@ -67,32 +66,10 @@ final class BytecodeViewTopComponent extends TopComponent implements ExplorerMan
associateLookup(ExplorerUtils.createLookup(manager, getActionMap()));
}
/** This method is called from within the constructor to
* initialize the form.
* WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor.
*/
// <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
private void initComponents() {
org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(0, 400, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(0, 300, Short.MAX_VALUE)
);
}// </editor-fold>//GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables
// End of variables declaration//GEN-END:variables
/**
* Gets default instance. Do not use directly: reserved for *.settings files only,
* i.e. deserialization routines; otherwise you could get a non-deserialized instance.
* To obtain the singleton instance, use {@link findInstance}.
* To obtain the singleton instance, use {@link #findInstance()}.
*/
public static synchronized BytecodeViewTopComponent getDefault() {
if (instance == null) {
@ -124,15 +101,12 @@ final class BytecodeViewTopComponent extends TopComponent implements ExplorerMan
@Override
public void componentOpened() {
Lookup.Template<InputGraphProvider> tpl = new Lookup.Template<>(InputGraphProvider.class);
result = Utilities.actionsGlobalContext().lookup(tpl);
result.addLookupListener(this);
LookupHistory.addListener(InputGraphProvider.class, this);
}
@Override
public void componentClosed() {
result.removeLookupListener(this);
result = null;
LookupHistory.removeListener(InputGraphProvider.class, this);
}
@Override
@ -169,23 +143,17 @@ final class BytecodeViewTopComponent extends TopComponent implements ExplorerMan
}
@Override
public void resultChanged(LookupEvent lookupEvent) {
final InputGraphProvider p = LookupHistory.getLast(InputGraphProvider.class);//)Utilities.actionsGlobalContext().lookup(InputGraphProvider.class);
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
if (p != null) {
InputGraph graph = p.getGraph();
if (graph != null) {
Group g = graph.getGroup();
rootNode.update(graph, g.getMethod());
return;
}
}
rootNode.update(null, null);
}
});
public void changed(InputGraphProvider lastProvider) {
if (lastProvider != null) {
InputGraph graph = lastProvider.getGraph();
if (graph != null) {
Group g = graph.getGroup();
rootNode.update(graph, g.getMethod());
return;
}
}
rootNode = new MethodNode(null, null, "");
manager.setRootContext(rootNode);
}
static final class ResolvableHelper implements Serializable {
@ -196,4 +164,26 @@ final class BytecodeViewTopComponent extends TopComponent implements ExplorerMan
return BytecodeViewTopComponent.getDefault();
}
}
/** This method is called from within the constructor to
* initialize the form.
* WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor.
*/
// <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
private void initComponents() {
org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(0, 400, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(0, 300, Short.MAX_VALUE)
);
}// </editor-fold>//GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables
// End of variables declaration//GEN-END:variables
}

@ -39,7 +39,7 @@ public final class SelectBytecodesAction extends CookieAction {
@Override
protected void performAction(Node[] activatedNodes) {
SelectBytecodesCookie c = activatedNodes[0].getCookie(SelectBytecodesCookie.class);
InputGraphProvider p = LookupHistory.getLast(InputGraphProvider.class);//Utilities.actionsGlobalContext().lookup(InputGraphProvider.class);
InputGraphProvider p = LookupHistory.getLast(InputGraphProvider.class);
if (p != null) {
p.setSelectedNodes(c.getNodes());
}

@ -133,7 +133,7 @@ public class ControlFlowScene extends GraphScene<InputBlock, InputBlockEdge> imp
}
public void selectionChanged() {
InputGraphProvider p = LookupHistory.getLast(InputGraphProvider.class);//)Utilities.actionsGlobalContext().lookup(InputGraphProvider.class);
InputGraphProvider p = LookupHistory.getLast(InputGraphProvider.class);
if (p != null) {
Set<InputNode> inputNodes = new HashSet<InputNode>();
for (BlockWidget w : selection) {

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 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
@ -23,19 +23,15 @@
*/
package com.sun.hotspot.igv.controlflow;
import com.sun.hotspot.igv.data.ChangedListener;
import com.sun.hotspot.igv.data.InputGraph;
import com.sun.hotspot.igv.data.services.InputGraphProvider;
import com.sun.hotspot.igv.util.LookupHistory;
import java.awt.BorderLayout;
import java.io.Serializable;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
import org.openide.ErrorManager;
import org.openide.util.Lookup;
import org.openide.util.LookupEvent;
import org.openide.util.LookupListener;
import org.openide.util.NbBundle;
import org.openide.util.Utilities;
import org.openide.windows.TopComponent;
import org.openide.windows.WindowManager;
@ -43,12 +39,11 @@ import org.openide.windows.WindowManager;
*
* @author Thomas Wuerthinger
*/
final class ControlFlowTopComponent extends TopComponent implements LookupListener {
final class ControlFlowTopComponent extends TopComponent implements ChangedListener<InputGraphProvider> {
private static ControlFlowTopComponent instance;
private Lookup.Result result = null;
private static final String PREFERRED_ID = "ControlFlowTopComponent";
private ControlFlowScene scene;
private final ControlFlowScene scene;
private ControlFlowTopComponent() {
initComponents();
@ -64,34 +59,10 @@ final class ControlFlowTopComponent extends TopComponent implements LookupListen
this.add(panel, BorderLayout.CENTER);
}
/** This method is called from within the constructor to
* initialize the form.
* WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor.
*/
// <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
private void initComponents() {
org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(0, 400, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(0, 300, Short.MAX_VALUE)
);
}// </editor-fold>//GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables
// End of variables declaration//GEN-END:variables
/**
* Gets default instance. Do not use directly: reserved for *.settings files only,
* i.e. deserialization routines; otherwise you could get a non-deserialized instance.
* To obtain the singleton instance, use {@link findInstance}.
* To obtain the singleton instance, use {@link #findInstance()}.
*/
public static synchronized ControlFlowTopComponent getDefault() {
if (instance == null) {
@ -123,30 +94,24 @@ final class ControlFlowTopComponent extends TopComponent implements LookupListen
@Override
public void componentOpened() {
Lookup.Template<InputGraphProvider> tpl = new Lookup.Template<InputGraphProvider>(InputGraphProvider.class);
result = Utilities.actionsGlobalContext().lookup(tpl);
result.addLookupListener(this);
LookupHistory.addListener(InputGraphProvider.class, this);
}
@Override
public void componentClosed() {
result.removeLookupListener(this);
result = null;
LookupHistory.removeListener(InputGraphProvider.class, this);
}
public void resultChanged(LookupEvent lookupEvent) {
final InputGraphProvider p = LookupHistory.getLast(InputGraphProvider.class);//Utilities.actionsGlobalContext().lookup(InputGraphProvider.class);
if (p != null) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
InputGraph g = p.getGraph();
if (g != null) {
scene.setGraph(g);
}
}
});
@Override
public void changed(InputGraphProvider lastProvider) {
if (lastProvider != null) {
InputGraph graph = lastProvider.getGraph();
if (graph != null) {
scene.setGraph(graph);
return;
}
}
scene.setGraph(new InputGraph(""));
}
@Override
@ -173,4 +138,26 @@ final class ControlFlowTopComponent extends TopComponent implements LookupListen
return ControlFlowTopComponent.getDefault();
}
}
/** This method is called from within the constructor to
* initialize the form.
* WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor.
*/
// <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
private void initComponents() {
org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(0, 400, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
.add(0, 300, Short.MAX_VALUE)
);
}// </editor-fold>//GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables
// End of variables declaration//GEN-END:variables
}

@ -25,8 +25,8 @@ package com.sun.hotspot.igv.coordinator;
import com.sun.hotspot.igv.connection.Server;
import com.sun.hotspot.igv.coordinator.actions.*;
import com.sun.hotspot.igv.data.ChangedListener;
import com.sun.hotspot.igv.data.GraphDocument;
import com.sun.hotspot.igv.data.Group;
import com.sun.hotspot.igv.data.InputGraph;
import com.sun.hotspot.igv.data.services.GroupCallback;
import com.sun.hotspot.igv.data.services.InputGraphProvider;
@ -48,8 +48,8 @@ import org.openide.awt.ToolbarPool;
import org.openide.explorer.ExplorerManager;
import org.openide.explorer.ExplorerUtils;
import org.openide.explorer.view.BeanTreeView;
import org.openide.util.*;
import org.openide.util.actions.NodeAction;
import org.openide.util.Exceptions;
import org.openide.util.NbBundle;
import org.openide.windows.TopComponent;
import org.openide.windows.WindowManager;
@ -57,13 +57,12 @@ import org.openide.windows.WindowManager;
*
* @author Thomas Wuerthinger
*/
public final class OutlineTopComponent extends TopComponent implements ExplorerManager.Provider, LookupListener {
public final class OutlineTopComponent extends TopComponent implements ExplorerManager.Provider, ChangedListener<InputGraphProvider> {
public static OutlineTopComponent instance;
public static final String PREFERRED_ID = "OutlineTopComponent";
private Lookup.Result result = null;
private ExplorerManager manager;
private GraphDocument document;
private final GraphDocument document;
private FolderNode root;
private Server server;
private Server binaryServer;
@ -100,13 +99,13 @@ public final class OutlineTopComponent extends TopComponent implements ExplorerM
this.add(toolbar, BorderLayout.NORTH);
toolbar.add(ImportAction.get(ImportAction.class));
toolbar.add(((NodeAction) SaveAsAction.get(SaveAsAction.class)).createContextAwareInstance(this.getLookup()));
toolbar.add(SaveAsAction.get(SaveAsAction.class).createContextAwareInstance(this.getLookup()));
saveAllAction = SaveAllAction.get(SaveAllAction.class);
saveAllAction.setEnabled(false);
toolbar.add(saveAllAction);
toolbar.add(((NodeAction) RemoveAction.get(RemoveAction.class)).createContextAwareInstance(this.getLookup()));
toolbar.add(RemoveAction.get(RemoveAction.class).createContextAwareInstance(this.getLookup()));
removeAllAction = RemoveAllAction.get(RemoveAllAction.class);
removeAllAction.setEnabled(false);
@ -129,14 +128,10 @@ public final class OutlineTopComponent extends TopComponent implements ExplorerM
private void initReceivers() {
final GroupCallback callback = new GroupCallback() {
@Override
public void started(Group g) {
synchronized(OutlineTopComponent.this) {
getDocument().addElement(g);
g.setParent(getDocument());
}
final GroupCallback callback = g -> {
synchronized(OutlineTopComponent.this) {
g.setParent(getDocument());
getDocument().addElement(g);
}
};
@ -144,28 +139,6 @@ public final class OutlineTopComponent extends TopComponent implements ExplorerM
binaryServer = new Server(getDocument(), callback, true);
}
// Fetch and select the latest active graph.
private void updateGraphSelection() {
final InputGraphProvider p = LookupHistory.getLast(InputGraphProvider.class);
if (p != null) {
try {
InputGraph graph = p.getGraph();
if (graph.isDiffGraph()) {
EditorTopComponent editor = EditorTopComponent.getActive();
if (editor != null) {
InputGraph firstGraph = editor.getModel().getFirstGraph();
InputGraph secondGraph = editor.getModel().getSecondGraph();
manager.setSelectedNodes(new GraphNode[]{FolderNode.getGraphNode(firstGraph), FolderNode.getGraphNode(secondGraph)});
}
} else {
manager.setSelectedNodes(new GraphNode[]{FolderNode.getGraphNode(graph)});
}
} catch (Exception e) {
Exceptions.printStackTrace(e);
}
}
}
public void clear() {
document.clear();
FolderNode.clearGraphNodeMap();
@ -185,7 +158,7 @@ public final class OutlineTopComponent extends TopComponent implements ExplorerM
/**
* Gets default instance. Do not use directly: reserved for *.settings files only,
* i.e. deserialization routines; otherwise you could get a non-deserialized instance.
* To obtain the singleton instance, use {@link findInstance}.
* To obtain the singleton instance, use {@link #findInstance()}.
*/
public static synchronized OutlineTopComponent getDefault() {
if (instance == null) {
@ -217,16 +190,13 @@ public final class OutlineTopComponent extends TopComponent implements ExplorerM
@Override
public void componentOpened() {
Lookup.Template<InputGraphProvider> tpl = new Lookup.Template<InputGraphProvider>(InputGraphProvider.class);
result = Utilities.actionsGlobalContext().lookup(tpl);
result.addLookupListener(this);
updateGraphSelection();
LookupHistory.addListener(InputGraphProvider.class, this);
this.requestActive();
}
@Override
public void componentClosed() {
result.removeLookupListener(this);
LookupHistory.removeListener(InputGraphProvider.class, this);
}
@Override
@ -253,14 +223,33 @@ public final class OutlineTopComponent extends TopComponent implements ExplorerM
}
@Override
public void resultChanged(LookupEvent lookupEvent) {
// Highlight the focused graph, if available, in the outline.
if (result.allItems().isEmpty()) {
return;
}
public void changed(InputGraphProvider lastProvider) {
// Wait for LookupHistory to be updated with the last active graph
// before selecting it.
SwingUtilities.invokeLater(() -> updateGraphSelection());
SwingUtilities.invokeLater(() -> {
GraphNode[] selection = new GraphNode[0];
if (lastProvider != null) {
// Try to fetch and select the latest active graph.
InputGraph graph = lastProvider.getGraph();
if (graph != null) {
if (graph.isDiffGraph()) {
EditorTopComponent editor = EditorTopComponent.getActive();
if (editor != null) {
InputGraph firstGraph = editor.getModel().getFirstGraph();
InputGraph secondGraph = editor.getModel().getSecondGraph();
selection = new GraphNode[]{FolderNode.getGraphNode(firstGraph), FolderNode.getGraphNode(secondGraph)};
}
} else {
selection = new GraphNode[]{FolderNode.getGraphNode(graph)};
}
}
}
try {
manager.setSelectedNodes(selection);
} catch (Exception e) {
Exceptions.printStackTrace(e);
}
});
}
@Override

@ -546,7 +546,7 @@ public final class FilterTopComponent extends TopComponent implements LookupList
/**
* Gets default instance. Do not use directly: reserved for *.settings files only,
* i.e. deserialization routines; otherwise you could get a non-deserialized instance.
* To obtain the singleton instance, use {@link findInstance}.
* To obtain the singleton instance, use {@link #findInstance()}.
*/
public static synchronized FilterTopComponent getDefault() {
if (instance == null) {

@ -1,38 +0,0 @@
/*
* Copyright (c) 2008, 2015, 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.graph.services;
import com.sun.hotspot.igv.data.ChangedEvent;
import com.sun.hotspot.igv.graph.Diagram;
/**
*
* @author Thomas Wuerthinger
*/
public interface DiagramProvider {
Diagram getDiagram();
ChangedEvent<DiagramProvider> getChangedEvent();
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 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
@ -23,6 +23,8 @@
*/
package com.sun.hotspot.igv.util;
import com.sun.hotspot.igv.data.ChangedListener;
import com.sun.hotspot.igv.data.Event;
import java.util.HashMap;
import java.util.Map;
import org.openide.util.Lookup.Result;
@ -38,7 +40,7 @@ public class LookupHistory {
private static Map<Class, LookupHistoryImpl> cache = new HashMap<>();
private static class LookupHistoryImpl<T> implements LookupListener {
private static class LookupHistoryImpl<T> extends Event<ChangedListener<T>> implements LookupListener {
private Class<T> klass;
private Result<T> result;
@ -49,17 +51,25 @@ public class LookupHistory {
result = Utilities.actionsGlobalContext().lookupResult(klass);
result.addLookupListener(this);
last = Utilities.actionsGlobalContext().lookup(klass);
fire();
}
public T getLast() {
return last;
}
@Override
protected void fire(ChangedListener<T> l) {
l.changed(last);
}
@Override
public void resultChanged(LookupEvent ev) {
T current = Utilities.actionsGlobalContext().lookup(klass);
if (current != null) {
last = current;
this.fire();
}
}
}
@ -70,10 +80,31 @@ public class LookupHistory {
}
}
public static <T> void terminate(Class<T> klass) {
if (cache.containsKey(klass)) {
cache.get(klass).fire();
}
}
@SuppressWarnings("unchecked")
public static <T> T getLast(Class<T> klass) {
init(klass);
assert cache.containsKey(klass);
return (T) cache.get(klass).getLast();
}
@SuppressWarnings("unchecked")
public static <T> void addListener(Class<T> klass, ChangedListener<T> listener) {
init(klass);
assert cache.containsKey(klass);
cache.get(klass).addListener(listener);
cache.get(klass).fire();
}
@SuppressWarnings("unchecked")
public static <T> void removeListener(Class<T> klass, ChangedListener<T> listener) {
if (cache.containsKey(klass)) {
cache.get(klass).removeListener(listener);
}
}
}

@ -60,7 +60,6 @@ public class DiagramViewModel extends RangeSliderModel implements ChangedListene
private FilterChain sequenceFilterChain;
private Diagram diagram;
private InputGraph inputGraph;
private ChangedEvent<DiagramViewModel> groupChangedEvent;
private ChangedEvent<DiagramViewModel> diagramChangedEvent;
private ChangedEvent<DiagramViewModel> viewChangedEvent;
private ChangedEvent<DiagramViewModel> hiddenNodesChangedEvent;
@ -96,9 +95,14 @@ public class DiagramViewModel extends RangeSliderModel implements ChangedListene
boolean viewChanged = false;
boolean viewPropertiesChanged = false;
boolean groupChanged = (group == newModel.group);
this.group = newModel.group;
if (groupChanged) {
if (group != newModel.group) {
if (group != null) {
group.getChangedEvent().removeListener(groupContentChangedListener);
}
group = newModel.group;
if (group != null) {
group.getChangedEvent().addListener(groupContentChangedListener);
}
filterGraphs();
}
@ -123,10 +127,6 @@ public class DiagramViewModel extends RangeSliderModel implements ChangedListene
viewPropertiesChanged |= (showNodeHull != newModel.showNodeHull);
this.showNodeHull = newModel.showNodeHull;
if (groupChanged) {
groupChangedEvent.fire();
}
if (diagramChanged) {
diagramChangedEvent.fire();
}
@ -213,6 +213,7 @@ public class DiagramViewModel extends RangeSliderModel implements ChangedListene
this.showNodeHull = true;
this.showEmptyBlocks = true;
this.group = g;
group.getChangedEvent().addListener(groupContentChangedListener);
filterGraphs();
assert filterChain != null;
this.filterChain = filterChain;
@ -227,26 +228,11 @@ public class DiagramViewModel extends RangeSliderModel implements ChangedListene
hiddenNodesChangedEvent = new ChangedEvent<>(this);
viewPropertiesChangedEvent = new ChangedEvent<>(this);
groupChangedEvent = new ChangedEvent<>(this);
groupChangedEvent.addListener(groupChangedListener);
groupChangedEvent.fire();
filterChain.getChangedEvent().addListener(filterChainChangedListener);
sequenceFilterChain.getChangedEvent().addListener(filterChainChangedListener);
}
private final ChangedListener<DiagramViewModel> groupChangedListener = new ChangedListener<DiagramViewModel>() {
private Group oldGroup;
@Override
public void changed(DiagramViewModel source) {
if (oldGroup != null) {
oldGroup.getChangedEvent().removeListener(groupContentChangedListener);
}
group.getChangedEvent().addListener(groupContentChangedListener);
oldGroup = group;
}
};
private final ChangedListener<Group> groupContentChangedListener = new ChangedListener<Group>() {
@Override
@ -511,6 +497,7 @@ public class DiagramViewModel extends RangeSliderModel implements ChangedListene
void close() {
filterChain.getChangedEvent().removeListener(filterChainChangedListener);
sequenceFilterChain.getChangedEvent().removeListener(filterChainChangedListener);
getChangedEvent().fire();
}
Iterable<InputGraph> getGraphsForward() {

@ -37,9 +37,11 @@ import org.openide.util.lookup.ServiceProvider;
@ServiceProvider(service=InputGraphProvider.class)
public class EditorInputGraphProvider implements InputGraphProvider {
private EditorTopComponent editor;
private final EditorTopComponent editor;
public EditorInputGraphProvider() {}
public EditorInputGraphProvider() {
editor = null;
}
public EditorInputGraphProvider(EditorTopComponent editor) {
this.editor = editor;
@ -47,21 +49,35 @@ public class EditorInputGraphProvider implements InputGraphProvider {
@Override
public InputGraph getGraph() {
return editor.getDiagramModel().getGraphToView();
if (editor != null && editor.isOpened()) {
return editor.getDiagramModel().getGraphToView();
} else {
return null;
}
}
@Override
public void setSelectedNodes(Set<InputNode> nodes) {
editor.setSelectedNodes(nodes);
if (editor != null && editor.isOpened()) {
editor.setSelectedNodes(nodes);
}
}
@Override
public Iterable<InputGraph> searchBackward() {
return editor.getDiagramModel().getGraphsBackward();
if (editor != null && editor.isOpened()) {
return editor.getDiagramModel().getGraphsBackward();
} else {
return null;
}
}
@Override
public Iterable<InputGraph> searchForward() {
return editor.getDiagramModel().getGraphsForward();
if (editor != null && editor.isOpened()) {
return editor.getDiagramModel().getGraphsForward();
} else {
return null;
}
}
}

@ -37,7 +37,6 @@ import com.sun.hotspot.igv.filter.FilterChain;
import com.sun.hotspot.igv.filter.FilterChainProvider;
import com.sun.hotspot.igv.graph.Diagram;
import com.sun.hotspot.igv.graph.Figure;
import com.sun.hotspot.igv.graph.services.DiagramProvider;
import com.sun.hotspot.igv.settings.Settings;
import com.sun.hotspot.igv.util.LookupHistory;
import com.sun.hotspot.igv.util.RangeSlider;
@ -124,31 +123,8 @@ public final class EditorTopComponent extends TopComponent implements PropertyCh
}
};
private DiagramProvider diagramProvider = new DiagramProvider() {
@Override
public Diagram getDiagram() {
return getModel().getDiagramToView();
}
@Override
public ChangedEvent<DiagramProvider> getChangedEvent() {
return diagramChangedEvent;
}
};
private ChangedEvent<DiagramProvider> diagramChangedEvent = new ChangedEvent<>(diagramProvider);
private void updateDisplayName() {
setDisplayName(getDiagram().getName());
setToolTipText(getDiagram().getGraph().getGroup().getName());
}
public EditorTopComponent(Diagram diagram) {
LookupHistory.init(InputGraphProvider.class);
LookupHistory.init(DiagramProvider.class);
this.setFocusable(true);
FilterChain filterChain = null;
FilterChain sequence = null;
@ -208,13 +184,16 @@ public final class EditorTopComponent extends TopComponent implements PropertyCh
scene = new DiagramScene(actions, actionsWithSelection, rangeSliderModel);
content = new InstanceContent();
graphContent = new InstanceContent();
this.associateLookup(new ProxyLookup(new Lookup[]{scene.getLookup(), new AbstractLookup(graphContent), new AbstractLookup(content)}));
content.add(exportCookie);
content.add(rangeSliderModel);
content.add(diagramProvider);
graphContent = new InstanceContent();
associateLookup(new ProxyLookup(scene.getLookup(), new AbstractLookup(graphContent), new AbstractLookup(content)));
rangeSliderModel.getDiagramChangedEvent().addListener(diagramChangedListener);
rangeSliderModel.getDiagramChangedEvent().addListener(source -> {
setDisplayName(getDiagram().getName());
setToolTipText(getDiagram().getGraph().getGroup().getName());
graphContent.set(Collections.singletonList(new EditorInputGraphProvider(this)), null);
});
rangeSliderModel.selectGraph(diagram.getGraph());
rangeSliderModel.getViewPropertiesChangedEvent().addListener(new ChangedListener<DiagramViewModel>() {
@Override
@ -383,7 +362,7 @@ public final class EditorTopComponent extends TopComponent implements PropertyCh
rangeSlider.setVisible(false);
}
updateDisplayName();
getModel().getDiagramChangedEvent().fire();
}
public DiagramViewModel getDiagramModel() {
@ -428,7 +407,11 @@ public final class EditorTopComponent extends TopComponent implements PropertyCh
}
public static EditorTopComponent getActive() {
return (EditorTopComponent) EditorTopComponent.getRegistry().getActivated();
try {
return (EditorTopComponent) EditorTopComponent.getRegistry().getActivated();
} catch (Exception e) {
return null;
}
}
/** This method is called from within the constructor to
@ -460,6 +443,7 @@ public final class EditorTopComponent extends TopComponent implements PropertyCh
public void componentClosed() {
super.componentClosed();
rangeSliderModel.close();
LookupHistory.terminate(InputGraphProvider.class);
}
@Override
@ -468,26 +452,13 @@ public final class EditorTopComponent extends TopComponent implements PropertyCh
}
private void closeOnRemovedOrEmptyGroup() {
Group group = getDiagram().getGraph().getGroup();
Group group = getDiagramModel().getGroup();
if (!group.getParent().getElements().contains(group) ||
group.getGraphs().isEmpty()) {
close();
}
}
private ChangedListener<DiagramViewModel> diagramChangedListener = new ChangedListener<DiagramViewModel>() {
@Override
public void changed(DiagramViewModel source) {
updateDisplayName();
Collection<Object> list = new ArrayList<>();
list.add(new EditorInputGraphProvider(EditorTopComponent.this));
graphContent.set(list, null);
diagramProvider.getChangedEvent().fire();
}
};
public boolean showPredSucc() {
return (Boolean) predSuccAction.getValue(PredSuccAction.STATE);
}