mirror of
https://github.com/JetBrains/JetBrainsRuntime.git
synced 2025-12-06 09:29:38 +01:00
8302738: IGV: refine 'Simplify graph' filter
Reviewed-by: tholenstein, chagedorn
(cherry picked from commit 345669c29d)
This commit is contained in:
committed by
Vitaly Provodin
parent
99829d13a0
commit
0dbe5c52e5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2015, 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
|
||||
@@ -26,6 +26,7 @@ package com.sun.hotspot.igv.filter;
|
||||
|
||||
import com.sun.hotspot.igv.data.ChangedEvent;
|
||||
import com.sun.hotspot.igv.data.Properties;
|
||||
import com.sun.hotspot.igv.graph.Figure;
|
||||
import org.openide.cookies.OpenCookie;
|
||||
|
||||
/**
|
||||
@@ -60,4 +61,14 @@ public abstract class AbstractFilter implements Filter {
|
||||
protected void fireChangedEvent() {
|
||||
changedEvent.fire();
|
||||
}
|
||||
|
||||
protected static String getFirstMatchingProperty(Figure figure, String[] propertyNames) {
|
||||
for (String propertyName : propertyNames) {
|
||||
String s = figure.getProperties().resolveString(propertyName);
|
||||
if (s != null && !s.isEmpty()) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -23,13 +23,9 @@
|
||||
*/
|
||||
package com.sun.hotspot.igv.filter;
|
||||
|
||||
import com.sun.hotspot.igv.data.Properties;
|
||||
import com.sun.hotspot.igv.data.Properties.PropertyMatcher;
|
||||
import com.sun.hotspot.igv.graph.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -53,12 +49,11 @@ public class CombineFilter extends AbstractFilter {
|
||||
@Override
|
||||
public void apply(Diagram diagram) {
|
||||
|
||||
Properties.PropertySelector<Figure> selector = new Properties.PropertySelector<>(diagram.getFigures());
|
||||
for (CombineRule r : rules) {
|
||||
|
||||
List<Figure> list = selector.selectMultiple(r.getFirstMatcher());
|
||||
Set<Figure> figuresToRemove = new HashSet<>();
|
||||
for (Figure f : list) {
|
||||
List<Figure> first = r.getFirstSelector().selected(diagram);
|
||||
List<Figure> second = r.getSecondSelector().selected(diagram);
|
||||
for (Figure f : first) {
|
||||
|
||||
List<Figure> successors = new ArrayList<>(f.getSuccessors());
|
||||
if (r.isReversed()) {
|
||||
@@ -75,8 +70,8 @@ public class CombineFilter extends AbstractFilter {
|
||||
}
|
||||
|
||||
slot.getSource().addSourceNode(f.getInputNode());
|
||||
if (r.getShortProperty() != null) {
|
||||
String s = f.getProperties().get(r.getShortProperty());
|
||||
if (r.getPropertyNames() != null && r.getPropertyNames().length > 0) {
|
||||
String s = r.getFirstMatchingProperty(f);
|
||||
if (s != null && s.length() > 0) {
|
||||
slot.setShortName(s);
|
||||
slot.setText(s);
|
||||
@@ -103,15 +98,12 @@ public class CombineFilter extends AbstractFilter {
|
||||
newConn.setStyle(c.getStyle());
|
||||
}
|
||||
}
|
||||
|
||||
figuresToRemove.add(f);
|
||||
}
|
||||
} else {
|
||||
|
||||
for (Figure succ : successors) {
|
||||
if (succ.getPredecessors().size() == 1 && succ.getInputSlots().size() == 1) {
|
||||
if (succ.getProperties().selectSingle(r.getSecondMatcher()) != null && succ.getOutputSlots().size() == 1) {
|
||||
|
||||
if (succ.getPredecessors().size() == 1) {
|
||||
if (second.contains(succ) && succ.getOutputSlots().size() <= 1) {
|
||||
|
||||
OutputSlot oldSlot = null;
|
||||
for (OutputSlot s : f.getOutputSlots()) {
|
||||
@@ -124,15 +116,19 @@ public class CombineFilter extends AbstractFilter {
|
||||
|
||||
assert oldSlot != null;
|
||||
|
||||
OutputSlot nextSlot = succ.getOutputSlots().get(0);
|
||||
OutputSlot nextSlot = null;
|
||||
if (succ.getOutputSlots().size() == 1) {
|
||||
nextSlot = succ.getOutputSlots().get(0);
|
||||
}
|
||||
|
||||
int pos = 0;
|
||||
if (succ.getProperties().get("con") != null) {
|
||||
pos = Integer.parseInt(succ.getProperties().get("con"));
|
||||
}
|
||||
OutputSlot slot = f.createOutputSlot(pos);
|
||||
slot.getSource().addSourceNode(succ.getInputNode());
|
||||
if (r.getShortProperty() != null) {
|
||||
String s = succ.getProperties().get(r.getShortProperty());
|
||||
if (r.getPropertyNames() != null && r.getPropertyNames().length > 0) {
|
||||
String s = r.getFirstMatchingProperty(succ);
|
||||
if (s != null && s.length() > 0) {
|
||||
slot.setShortName(s);
|
||||
slot.setText(s);
|
||||
@@ -155,14 +151,15 @@ public class CombineFilter extends AbstractFilter {
|
||||
}
|
||||
}
|
||||
}
|
||||
for (FigureConnection c : nextSlot.getConnections()) {
|
||||
FigureConnection newConn = diagram.createConnection(c.getInputSlot(), slot, c.getLabel());
|
||||
newConn.setColor(c.getColor());
|
||||
newConn.setStyle(c.getStyle());
|
||||
if (nextSlot != null) {
|
||||
for (FigureConnection c : nextSlot.getConnections()) {
|
||||
FigureConnection newConn = diagram.createConnection(c.getInputSlot(), slot, c.getLabel());
|
||||
newConn.setColor(c.getColor());
|
||||
newConn.setStyle(c.getStyle());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
figuresToRemove.add(succ);
|
||||
diagram.removeFigure(succ);
|
||||
|
||||
if (oldSlot.getConnections().size() == 0) {
|
||||
f.removeSlot(oldSlot);
|
||||
@@ -172,8 +169,6 @@ public class CombineFilter extends AbstractFilter {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
diagram.removeAllFigures(figuresToRemove);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -183,41 +178,36 @@ public class CombineFilter extends AbstractFilter {
|
||||
|
||||
public static class CombineRule {
|
||||
|
||||
private PropertyMatcher first;
|
||||
private PropertyMatcher second;
|
||||
private Selector first;
|
||||
private Selector second;
|
||||
private boolean reversed;
|
||||
private String shortProperty;
|
||||
private String[] propertyNames;
|
||||
|
||||
public CombineRule(PropertyMatcher first, PropertyMatcher second) {
|
||||
this(first, second, false);
|
||||
|
||||
}
|
||||
|
||||
public CombineRule(PropertyMatcher first, PropertyMatcher second, boolean reversed) {
|
||||
this(first, second, reversed, null);
|
||||
}
|
||||
|
||||
public CombineRule(PropertyMatcher first, PropertyMatcher second, boolean reversed, String shortProperty) {
|
||||
public CombineRule(Selector first, Selector second, boolean reversed, String[] propertyNames) {
|
||||
this.first = first;
|
||||
this.second = second;
|
||||
this.reversed = reversed;
|
||||
this.shortProperty = shortProperty;
|
||||
this.propertyNames = propertyNames;
|
||||
}
|
||||
|
||||
public boolean isReversed() {
|
||||
return reversed;
|
||||
}
|
||||
|
||||
public PropertyMatcher getFirstMatcher() {
|
||||
public Selector getFirstSelector() {
|
||||
return first;
|
||||
}
|
||||
|
||||
public PropertyMatcher getSecondMatcher() {
|
||||
public Selector getSecondSelector() {
|
||||
return second;
|
||||
}
|
||||
|
||||
public String getShortProperty() {
|
||||
return shortProperty;
|
||||
public String[] getPropertyNames() {
|
||||
return propertyNames;
|
||||
}
|
||||
|
||||
public String getFirstMatchingProperty(Figure figure) {
|
||||
return AbstractFilter.getFirstMatchingProperty(figure, propertyNames);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* 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.filter;
|
||||
|
||||
import com.sun.hotspot.igv.graph.Diagram;
|
||||
import com.sun.hotspot.igv.graph.Figure;
|
||||
import com.sun.hotspot.igv.graph.Selector;
|
||||
import java.util.function.UnaryOperator;
|
||||
import java.util.List;
|
||||
|
||||
public class EditPropertyFilter extends AbstractFilter {
|
||||
|
||||
private String name;
|
||||
private Selector selector;
|
||||
private final String inputPropertyName;
|
||||
private final String outputPropertyName;
|
||||
private final UnaryOperator<String> editFunction;
|
||||
|
||||
public EditPropertyFilter(String name, Selector selector,
|
||||
String inputPropertyName, String outputPropertyName,
|
||||
UnaryOperator<String> editFunction) {
|
||||
this.name = name;
|
||||
this.selector = selector;
|
||||
this.inputPropertyName = inputPropertyName;
|
||||
this.outputPropertyName = outputPropertyName;
|
||||
this.editFunction = editFunction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply(Diagram diagram) {
|
||||
List<Figure> list = selector.selected(diagram);
|
||||
for (Figure f : list) {
|
||||
String inputVal = f.getProperties().get(inputPropertyName);
|
||||
String outputVal = editFunction.apply(inputVal);
|
||||
f.getProperties().setProperty(outputPropertyName, outputVal);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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.filter;
|
||||
|
||||
import com.sun.hotspot.igv.graph.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class RemoveEmptySlotsFilter extends AbstractFilter {
|
||||
|
||||
private String name;
|
||||
private Selector selector;
|
||||
|
||||
public RemoveEmptySlotsFilter(String name, Selector selector) {
|
||||
this.name = name;
|
||||
this.selector = selector;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply(Diagram diagram) {
|
||||
List<Figure> list = selector.selected(diagram);
|
||||
for (Figure f : list) {
|
||||
List<InputSlot> empty = new ArrayList<>();
|
||||
for (InputSlot is : f.getInputSlots()) {
|
||||
if (is.getConnections().isEmpty()) {
|
||||
empty.add(is);
|
||||
}
|
||||
}
|
||||
for (InputSlot is : empty) {
|
||||
f.removeSlot(is);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -48,53 +48,17 @@ public class RemoveInputsFilter extends AbstractFilter {
|
||||
|
||||
@Override
|
||||
public void apply(Diagram diagram) {
|
||||
|
||||
for (RemoveInputsRule r : rules) {
|
||||
|
||||
List<Figure> list = r.getSelector().selected(diagram);
|
||||
List<Figure> list = r.getNodeSelector().selected(diagram);
|
||||
List<Figure> slotList = r.getSlotSelector().selected(diagram);
|
||||
for (Figure f : list) {
|
||||
int z = 0;
|
||||
List<InputSlot> last = new ArrayList<>();
|
||||
for (InputSlot is : f.getInputSlots()) {
|
||||
if (z >= r.getStartingIndex() && z <= r.getEndIndex() && is.getConnections().size() > 0) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
List<FigureConnection> conns = is.getConnections();
|
||||
for (int i = 0; i < conns.size(); i++) {
|
||||
FigureConnection c = conns.get(i);
|
||||
OutputSlot os = c.getOutputSlot();
|
||||
Figure pred = os.getFigure();
|
||||
if (i != 0) {
|
||||
sb.append("<BR>");
|
||||
}
|
||||
sb.append(pred.getLines()[0]);
|
||||
List<FigureConnection> conns = is.getConnections();
|
||||
if (conns.size() == 1) {
|
||||
Figure i = conns.get(0).getOutputSlot().getFigure();
|
||||
if (slotList.contains(i)) {
|
||||
is.removeAllConnections();
|
||||
}
|
||||
is.removeAllConnections();
|
||||
is.setShortName("X");
|
||||
is.setText(sb.toString());
|
||||
last.add(is);
|
||||
} else {
|
||||
last.clear();
|
||||
}
|
||||
z++;
|
||||
}
|
||||
|
||||
if (last.size() > 3) {
|
||||
InputSlot first = last.get(0);
|
||||
first.setShortName("XX");
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < last.size(); i++) {
|
||||
InputSlot is2 = last.get(i);
|
||||
if (i != 0) {
|
||||
sb.append("<BR>");
|
||||
}
|
||||
sb.append(is2.getText());
|
||||
}
|
||||
|
||||
first.setText(sb.toString());
|
||||
|
||||
for (int i = 1; i < last.size(); i++) {
|
||||
f.removeSlot(last.get(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -107,34 +71,20 @@ public class RemoveInputsFilter extends AbstractFilter {
|
||||
|
||||
public static class RemoveInputsRule {
|
||||
|
||||
private Selector selector;
|
||||
private int startingIndex;
|
||||
private int endIndex;
|
||||
private Selector nodeSelector;
|
||||
private Selector slotSelector;
|
||||
|
||||
public RemoveInputsRule(Selector selector) {
|
||||
this(selector, 0);
|
||||
public RemoveInputsRule(Selector nodeSelector, Selector slotSelector) {
|
||||
this.nodeSelector = nodeSelector;
|
||||
this.slotSelector = slotSelector;
|
||||
}
|
||||
|
||||
public RemoveInputsRule(Selector selector, int startIndex) {
|
||||
this(selector, startIndex, Integer.MAX_VALUE);
|
||||
public Selector getNodeSelector() {
|
||||
return nodeSelector;
|
||||
}
|
||||
|
||||
public RemoveInputsRule(Selector selector, int startIndex, int endIndex) {
|
||||
this.startingIndex = startIndex;
|
||||
this.endIndex = endIndex;
|
||||
this.selector = selector;
|
||||
}
|
||||
|
||||
public int getStartingIndex() {
|
||||
return startingIndex;
|
||||
}
|
||||
|
||||
public int getEndIndex() {
|
||||
return endIndex;
|
||||
}
|
||||
|
||||
public Selector getSelector() {
|
||||
return selector;
|
||||
public Selector getSlotSelector() {
|
||||
return slotSelector;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -34,12 +34,12 @@ public class SplitFilter extends AbstractFilter {
|
||||
|
||||
private String name;
|
||||
private Selector selector;
|
||||
private String propertyName;
|
||||
private String[] propertyNames;
|
||||
|
||||
public SplitFilter(String name, Selector selector, String propertyName) {
|
||||
public SplitFilter(String name, Selector selector, String[] propertyNames) {
|
||||
this.name = name;
|
||||
this.selector = selector;
|
||||
this.propertyName = propertyName;
|
||||
this.propertyNames = propertyNames;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -52,23 +52,7 @@ public class SplitFilter extends AbstractFilter {
|
||||
List<Figure> list = selector.selected(d);
|
||||
|
||||
for (Figure f : list) {
|
||||
|
||||
for (InputSlot is : f.getInputSlots()) {
|
||||
for (FigureConnection c : is.getConnections()) {
|
||||
OutputSlot os = c.getOutputSlot();
|
||||
if (f.getInputNode() != null) {
|
||||
os.getSource().addSourceNode(f.getInputNode());
|
||||
os.setColor(f.getColor());
|
||||
}
|
||||
|
||||
|
||||
String s = f.getProperties().resolveString(propertyName);
|
||||
if (s != null) {
|
||||
os.setShortName(s);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
String s = AbstractFilter.getFirstMatchingProperty(f, propertyNames);
|
||||
for (OutputSlot os : f.getOutputSlots()) {
|
||||
for (FigureConnection c : os.getConnections()) {
|
||||
InputSlot is = c.getInputSlot();
|
||||
@@ -76,8 +60,6 @@ public class SplitFilter extends AbstractFilter {
|
||||
is.getSource().addSourceNode(f.getInputNode());
|
||||
is.setColor(f.getColor());
|
||||
}
|
||||
|
||||
String s = f.getProperties().resolveString(propertyName);
|
||||
if (s != null) {
|
||||
is.setShortName(s);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -21,61 +21,122 @@
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Thomas Wuerthinger
|
||||
*/
|
||||
|
||||
function colorize(property, regexp, color) {
|
||||
var f = new ColorFilter("");
|
||||
f.addRule(new ColorFilter.ColorRule(new MatcherSelector(new Properties.RegexpPropertyMatcher(property, regexp)), color));
|
||||
f.apply(graph);
|
||||
|
||||
// Split a string by whitespace, collapsing repeated ones.
|
||||
function split_string(s) {
|
||||
return s.split(/(\s+)/).filter(function(e) {return e.trim().length > 0;});
|
||||
}
|
||||
|
||||
// Select the node union in a list of selectors.
|
||||
function or(selectors) {
|
||||
return new OrSelector(selectors);
|
||||
}
|
||||
|
||||
// Select the node intersection in a list of selectors.
|
||||
function and(selectors) {
|
||||
return new AndSelector(selectors);
|
||||
}
|
||||
|
||||
// Select the nodes that are not selected by a given selector.
|
||||
function not(selector) {
|
||||
return new InvertSelector(selector);
|
||||
}
|
||||
|
||||
// Select the nodes that succeed those given by a selector.
|
||||
function successorOf(selector) {
|
||||
return new SuccessorSelector(selector);
|
||||
}
|
||||
|
||||
// Select the blocks where at least one node is selected by the given selector.
|
||||
function hasAnyNode(selector) {
|
||||
return new AnySelector(selector);
|
||||
}
|
||||
|
||||
// Select the nodes whose given property matches a given regular expression.
|
||||
function matches(property, regexp) {
|
||||
return new MatcherSelector(new Properties.RegexpPropertyMatcher(property, regexp));
|
||||
}
|
||||
|
||||
// Color the selected nodes.
|
||||
function colorize(selector, color) {
|
||||
var f = new ColorFilter("");
|
||||
f.addRule(new ColorFilter.ColorRule(selector, color));
|
||||
f.apply(graph);
|
||||
}
|
||||
|
||||
// Invisible connection style (used to hide edges).
|
||||
invisibleConnection = Connection.ConnectionStyle.INVISIBLE;
|
||||
|
||||
// Apply a given style (e.g. invisible) and color to the out edges of the
|
||||
// selected nodes.
|
||||
function styleOutputConnections(selector, color, style) {
|
||||
var f = new ConnectionFilter("");
|
||||
f.addRule(new ConnectionFilter.ConnectionStyleRule(selector, color, style));
|
||||
f.apply(graph);
|
||||
}
|
||||
|
||||
// Display a warning with the contents of a given property ('propertyToShow') in
|
||||
// the nodes whose given property ('propertyToMatch') matches a regular
|
||||
// expression.
|
||||
function warn(propertyToMatch, regexp, propertyToShow) {
|
||||
var f = new WarningFilter("", "[" + propertyToShow + "]");
|
||||
f.addRule(new WarningFilter.WarningRule(new MatcherSelector(new Properties.RegexpPropertyMatcher(propertyToMatch, regexp))));
|
||||
f.addRule(new WarningFilter.WarningRule(matches(propertyToMatch, regexp)));
|
||||
f.apply(graph);
|
||||
}
|
||||
|
||||
function remove(property, regexp) {
|
||||
// Remove edges with the same source and destination node.
|
||||
function removeSelfLoops() {
|
||||
var f = new RemoveSelfLoopsFilter("");
|
||||
f.apply(graph);
|
||||
}
|
||||
|
||||
// Remove the selected nodes.
|
||||
function remove(selector) {
|
||||
var f = new RemoveFilter("");
|
||||
f.addRule(new RemoveFilter.RemoveRule(new MatcherSelector(new Properties.RegexpPropertyMatcher(property, regexp))));
|
||||
f.addRule(new RemoveFilter.RemoveRule(selector));
|
||||
f.apply(graph);
|
||||
}
|
||||
|
||||
// Remove the selected nodes and nodes that become orphan after the removal.
|
||||
function removeIncludingOrphans(property, regexp) {
|
||||
var f = new RemoveFilter("");
|
||||
f.addRule(new RemoveFilter.RemoveRule(new MatcherSelector(new Properties.RegexpPropertyMatcher(property, regexp)), true));
|
||||
f.apply(graph);
|
||||
}
|
||||
|
||||
function split(property, regexp, propertyName) {
|
||||
if (propertyName == undefined) {
|
||||
propertyName = graph.getNodeText();
|
||||
}
|
||||
var f = new SplitFilter("", new MatcherSelector(new Properties.RegexpPropertyMatcher(property, regexp)), propertyName);
|
||||
f.apply(graph);
|
||||
}
|
||||
|
||||
function removeInputs(property, regexp, from, to) {
|
||||
var f = new RemoveInputsFilter("");
|
||||
if(from == undefined && to == undefined) {
|
||||
f.addRule(new RemoveInputsFilter.RemoveInputsRule(new MatcherSelector(new Properties.RegexpPropertyMatcher(property, regexp))));
|
||||
} else if(to == undefined) {
|
||||
f.addRule(new RemoveInputsFilter.RemoveInputsRule(new MatcherSelector(new Properties.RegexpPropertyMatcher(property, regexp)), from));
|
||||
} else {
|
||||
f.addRule(new RemoveInputsFilter.RemoveInputsRule(new MatcherSelector(new Properties.RegexpPropertyMatcher(property, regexp)), from, to));
|
||||
// Inline the selected nodes into their successors and display the first found
|
||||
// property in the given property list in the resulting input slots.
|
||||
function split(selector, propertyNames) {
|
||||
if (propertyNames == undefined) {
|
||||
propertyNames = [];
|
||||
}
|
||||
new SplitFilter("", selector, propertyNames).apply(graph);
|
||||
}
|
||||
|
||||
// Combine the selected (second) nodes into their selected (first) predecessors
|
||||
// and display the first found property in the given property list in the
|
||||
// resulting output slots.
|
||||
function combine(first, second, propertyNames) {
|
||||
if (propertyNames == undefined) {
|
||||
propertyNames = [];
|
||||
}
|
||||
var f = new CombineFilter("");
|
||||
f.addRule(new CombineFilter.CombineRule(first, second, false, propertyNames));
|
||||
f.apply(graph);
|
||||
}
|
||||
|
||||
// Remove (input and/or output) slots without connecting edges.
|
||||
function removeUnconnectedSlots(inputs, outputs) {
|
||||
var f = new UnconnectedSlotFilter(inputs, outputs);
|
||||
f.apply(graph);
|
||||
}
|
||||
|
||||
// Color nodes using a gradient based on the given property and min/max values.
|
||||
function colorizeGradient(property, min, max) {
|
||||
var f = new GradientColorFilter();
|
||||
f.setPropertyName(property);
|
||||
@@ -84,6 +145,8 @@ function colorizeGradient(property, min, max) {
|
||||
f.apply(graph);
|
||||
}
|
||||
|
||||
// Color nodes using a gradient based on the given property, min/max values, and
|
||||
// mode ("LINEAR" or "LOGARITHMIC").
|
||||
function colorizeGradientWithMode(property, min, max, mode) {
|
||||
var f = new GradientColorFilter();
|
||||
f.setPropertyName(property);
|
||||
@@ -93,6 +156,9 @@ function colorizeGradientWithMode(property, min, max, mode) {
|
||||
f.apply(graph);
|
||||
}
|
||||
|
||||
// Color nodes using a custom gradient based on the given property, min/max
|
||||
// values, mode ("LINEAR" or "LOGARITHMIC"), list of colors, list of fractions,
|
||||
// and number of shades.
|
||||
function colorizeGradientCustom(property, min, max, mode, colors, fractions, nshades) {
|
||||
var f = new GradientColorFilter();
|
||||
f.setPropertyName(property);
|
||||
@@ -105,6 +171,7 @@ function colorizeGradientCustom(property, min, max, mode, colors, fractions, nsh
|
||||
f.apply(graph);
|
||||
}
|
||||
|
||||
// Pre-defined colors for coloring filters.
|
||||
var black = Color.black;
|
||||
var blue = Color.blue;
|
||||
var cyan = Color.cyan;
|
||||
@@ -118,3 +185,38 @@ var pink = Color.pink
|
||||
var red = Color.red;
|
||||
var yellow = Color.yellow;
|
||||
var white = Color.white;
|
||||
|
||||
// Update the value of the given property in the selected nodes according to a
|
||||
// function that takes as input the old property value and returns the new
|
||||
// property value.
|
||||
function editSameProperty(selector, propertyName, editFunction) {
|
||||
var f = new EditPropertyFilter("", selector, propertyName, propertyName, editFunction);
|
||||
f.apply(graph);
|
||||
}
|
||||
|
||||
// Update the value of the given property ('outputPropertyName') in the selected
|
||||
// nodes according to a function that takes as input the value of a possibly
|
||||
// different property ('inputPropertyName') and returns the new property value.
|
||||
function editProperty(selector, inputPropertyName, outputPropertyName, editFunction) {
|
||||
var f = new EditPropertyFilter("", selector, inputPropertyName, outputPropertyName, editFunction);
|
||||
f.apply(graph);
|
||||
}
|
||||
|
||||
// Remove edges that go from the selected slots into the selected nodes.
|
||||
function removeInputs(nodeSelector, slotSelector) {
|
||||
var f = new RemoveInputsFilter("");
|
||||
f.addRule(new RemoveInputsFilter.RemoveInputsRule(nodeSelector, slotSelector));
|
||||
f.apply(graph);
|
||||
}
|
||||
|
||||
// Remove empty slots in the selected nodes, condensing all inputs as a result.
|
||||
function removeEmptySlots(selector) {
|
||||
new RemoveEmptySlotsFilter("", selector).apply(graph);
|
||||
}
|
||||
|
||||
// Remove the selected block.
|
||||
function removeBlock(selector) {
|
||||
var f = new RemoveBlockFilter("");
|
||||
f.addRule(new RemoveBlockFilter.RemoveBlockRule(selector));
|
||||
f.apply(graph);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2015, 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
|
||||
@@ -32,23 +32,24 @@ import java.util.List;
|
||||
*/
|
||||
public class AndSelector implements Selector {
|
||||
|
||||
private Selector selector1;
|
||||
private Selector selector2;
|
||||
private Selector[] selectors;
|
||||
|
||||
public AndSelector(Selector s1, Selector s2) {
|
||||
this.selector1 = s1;
|
||||
this.selector2 = s2;
|
||||
public AndSelector(Selector[] selectors) {
|
||||
this.selectors = selectors;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Figure> selected(Diagram d) {
|
||||
List<Figure> l1 = selector1.selected(d);
|
||||
List<Figure> l2 = selector2.selected(d);
|
||||
List<Figure> result = new ArrayList<>();
|
||||
for (Figure f : l2) {
|
||||
if (l1.contains(f)) {
|
||||
result.add(f);
|
||||
List<Figure> result = d.getFigures();
|
||||
for (Selector s : selectors) {
|
||||
List<Figure> selected = s.selected(d);
|
||||
List<Figure> newResult = new ArrayList<>();
|
||||
for (Figure f : result) {
|
||||
if (selected.contains(f)) {
|
||||
newResult.add(f);
|
||||
}
|
||||
}
|
||||
result = newResult;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -113,6 +113,14 @@ public class Diagram {
|
||||
}
|
||||
}
|
||||
|
||||
for (Figure f : figures) {
|
||||
int i = 0;
|
||||
for (InputSlot inputSlot : f.getInputSlots()) {
|
||||
inputSlot.setOriginalIndex(i);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
for (InputBlockEdge e : graph.getBlockEdges()) {
|
||||
Block p = getBlock(e.getFrom());
|
||||
Block s = getBlock(e.getTo());
|
||||
|
||||
@@ -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
|
||||
@@ -41,6 +41,7 @@ public class Figure extends Properties.Entity implements Vertex {
|
||||
public static final int TOP_CFG_HEIGHT = 7;
|
||||
public static final int BOTTOM_CFG_HEIGHT = 6;
|
||||
public static final int WARNING_WIDTH = 16;
|
||||
public static final double BOLD_LINE_FACTOR = 1.06;
|
||||
protected List<InputSlot> inputSlots;
|
||||
protected List<OutputSlot> outputSlots;
|
||||
private final InputNode inputNode;
|
||||
@@ -71,6 +72,9 @@ public class Figure extends Properties.Entity implements Vertex {
|
||||
if (hasInputList() && lines > 1) {
|
||||
lines++;
|
||||
}
|
||||
if (getProperties().get("extra_label") != null) {
|
||||
lines++;
|
||||
}
|
||||
heightCash = lines * metrics.getHeight() + INSET;
|
||||
if (diagram.isCFG()) {
|
||||
if (hasNamedInputSlot()) {
|
||||
@@ -120,7 +124,7 @@ public class Figure extends Properties.Entity implements Vertex {
|
||||
max = cur;
|
||||
}
|
||||
}
|
||||
widthCash = max + INSET;
|
||||
widthCash = (int)(max * BOLD_LINE_FACTOR) + INSET;
|
||||
if (getWarning() != null) {
|
||||
widthCash += WARNING_WIDTH;
|
||||
}
|
||||
@@ -164,7 +168,7 @@ public class Figure extends Properties.Entity implements Vertex {
|
||||
}
|
||||
|
||||
public boolean hasInputList() {
|
||||
return diagram.isCFG() && !getPredecessors().isEmpty();
|
||||
return diagram.isCFG() && !getInputSlots().isEmpty();
|
||||
}
|
||||
|
||||
public void setBlock(Block block) {
|
||||
@@ -320,8 +324,31 @@ public class Figure extends Properties.Entity implements Vertex {
|
||||
if (hasInputList()) {
|
||||
String inputList = " ← ";
|
||||
List<String> inputs = new ArrayList<>(getPredecessors().size());
|
||||
for (Figure p : getPredecessors()) {
|
||||
inputs.add(p.getProperties().resolveString(diagram.getTinyNodeText()));
|
||||
for (InputSlot is : getInputSlots()) {
|
||||
String inputLabel = null;
|
||||
if (is.getConnections().isEmpty()) {
|
||||
if (is.hasSourceNodes() && is.shouldShowName()) {
|
||||
inputLabel = "[" + is.getShortName() + "]";
|
||||
} else {
|
||||
inputLabel = "_";
|
||||
}
|
||||
} else {
|
||||
OutputSlot os = is.getConnections().get(0).getOutputSlot();
|
||||
Figure f = os.getFigure();
|
||||
String nodeTinyLabel = f.getProperties().resolveString(diagram.getTinyNodeText());
|
||||
if (os.hasSourceNodes() && os.shouldShowName()) {
|
||||
nodeTinyLabel += ":" + os.getShortName();
|
||||
}
|
||||
inputLabel = nodeTinyLabel;
|
||||
}
|
||||
assert(inputLabel != null);
|
||||
int gapSize = is.gapSize();
|
||||
if (gapSize == 1) {
|
||||
inputs.add("_");
|
||||
} else if (gapSize > 1) {
|
||||
inputs.add("…");
|
||||
}
|
||||
inputs.add(inputLabel);
|
||||
}
|
||||
inputList += String.join(" ", inputs);
|
||||
if (result.size() == 1) {
|
||||
@@ -333,6 +360,11 @@ public class Figure extends Properties.Entity implements Vertex {
|
||||
}
|
||||
}
|
||||
|
||||
String extraLabel = getProperties().get("extra_label");
|
||||
if (extraLabel != null) {
|
||||
result.add(extraLabel);
|
||||
}
|
||||
|
||||
lines = result.toArray(new String[0]);
|
||||
// Set the "label" property of the input node, so that by default
|
||||
// search is done on the node label (without line breaks). See also
|
||||
|
||||
@@ -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
|
||||
@@ -106,7 +106,7 @@ public class FigureConnection implements Connection {
|
||||
builder.append(" → ");
|
||||
builder.append(getInputSlot().getFigure().getProperties().resolveString(shortNodeText));
|
||||
builder.append(" [")
|
||||
.append(getInputSlot().getPosition())
|
||||
.append(getInputSlot().getOriginalIndex())
|
||||
.append("]");
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2015, 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
|
||||
@@ -32,8 +32,11 @@ import java.util.List;
|
||||
*/
|
||||
public class InputSlot extends Slot {
|
||||
|
||||
private int originalIndex;
|
||||
|
||||
protected InputSlot(Figure figure, int wantedIndex) {
|
||||
super(figure, wantedIndex);
|
||||
this.originalIndex = -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -47,13 +50,34 @@ public class InputSlot extends Slot {
|
||||
InputSlot s = inputSlots.remove(position);
|
||||
inputSlots.add(position, s);
|
||||
}
|
||||
|
||||
public int getOriginalIndex() {
|
||||
return originalIndex;
|
||||
}
|
||||
|
||||
public void setOriginalIndex(int originalIndex) {
|
||||
this.originalIndex = originalIndex;
|
||||
}
|
||||
|
||||
public int gapSize() {
|
||||
int index = getPosition();
|
||||
int originalIndex = getOriginalIndex();
|
||||
InputSlot prevSlot = index > 0 ? getFigure().getInputSlots().get(index - 1) : null;
|
||||
int prevOriginalIndex = index > 0 ? prevSlot.getOriginalIndex() : -1;
|
||||
return originalIndex - prevOriginalIndex - 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Point getRelativePosition() {
|
||||
int gap = getFigure().getWidth() - Figure.getSlotsWidth(getFigure().getInputSlots());
|
||||
double gapRatio = (double)gap / (double)(getFigure().getInputSlots().size() + 1);
|
||||
int gapAmount = (int)((getPosition() + 1)*gapRatio);
|
||||
return new Point(gapAmount + Figure.getSlotsWidth(Figure.getAllBefore(getFigure().getInputSlots(), this)) + getWidth()/2, -Figure.SLOT_START);
|
||||
//return new Point((getFigure().getWidth() / (getFigure().getInputSlots().size() * 2)) * (getPosition() * 2 + 1), -Figure.SLOT_START);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getToolTipText() {
|
||||
return super.getToolTipText() + " [" + originalIndex + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2015, 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
|
||||
@@ -23,6 +23,7 @@
|
||||
*/
|
||||
package com.sun.hotspot.igv.graph;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -31,27 +32,22 @@ import java.util.List;
|
||||
*/
|
||||
public class OrSelector implements Selector {
|
||||
|
||||
private Selector selector1;
|
||||
private Selector selector2;
|
||||
private Selector[] selectors;
|
||||
|
||||
/** Creates a new instance of OrSelector */
|
||||
public OrSelector(Selector s1, Selector s2) {
|
||||
this.selector1 = s1;
|
||||
this.selector2 = s2;
|
||||
public OrSelector(Selector[] selectors) {
|
||||
this.selectors = selectors;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Figure> selected(Diagram d) {
|
||||
|
||||
List<Figure> l1 = selector1.selected(d);
|
||||
List<Figure> l2 = selector2.selected(d);
|
||||
|
||||
for (Figure f : l2) {
|
||||
if (!l1.contains(f)) {
|
||||
l1.add(f);
|
||||
List<Figure> result = new ArrayList<>();
|
||||
for (Selector s : selectors) {
|
||||
for (Figure f : s.selected(d)) {
|
||||
if (!result.contains(f)) {
|
||||
result.add(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return l1;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,5 +46,15 @@ Alternatively the output can be sent to a file using
|
||||
with unique names being generated by adding a number onto the provided file
|
||||
name.
|
||||
|
||||
## Defining Custom Filters
|
||||
|
||||
IGV has a powerful filter mechanism with which nodes and blocks can be colored,
|
||||
hidden, updated, etc. according to user-defined rules. Filters are programmed in
|
||||
JavaScript using a set of predefined primitives and auxiliary functions. For
|
||||
more information, see the documentation in
|
||||
`Filter/src/main/resources/com/sun/hotspot/igv/filter/helper.js` and the default
|
||||
filters in
|
||||
`ServerCompiler/src/main/resources/com/sun/hotspot/igv/servercompiler/filters`.
|
||||
|
||||
More information about the tool is available at
|
||||
https://wiki.openjdk.org/display/HotSpot/IdealGraphVisualizer.
|
||||
|
||||
@@ -10,16 +10,16 @@ var otherEdgeColor = java.awt.Color.decode("#dfc025");
|
||||
var dataEdgeColor = java.awt.Color.decode("#3178c2");
|
||||
var memoryEdgeColor = java.awt.Color.decode("#828200");
|
||||
|
||||
colorize("category", "data", dataNodeColor);
|
||||
colorize("category", "memory", memoryNodeColor);
|
||||
colorize("category", "mixed", mixedNodeColor);
|
||||
colorize("category", "control", controlNodeColor);
|
||||
colorize("category", "other", otherNodeColor);
|
||||
colorize(matches("category", "data"), dataNodeColor);
|
||||
colorize(matches("category", "memory"), memoryNodeColor);
|
||||
colorize(matches("category", "mixed"), mixedNodeColor);
|
||||
colorize(matches("category", "control"), controlNodeColor);
|
||||
colorize(matches("category", "other"), otherNodeColor);
|
||||
|
||||
var f = new ColorFilter("Line Style filter");
|
||||
f.addRule(new ColorFilter.ColorRule(new MatcherSelector(new Properties.StringPropertyMatcher("category", "data")), null, dataEdgeColor, null));
|
||||
f.addRule(new ColorFilter.ColorRule(new MatcherSelector(new Properties.StringPropertyMatcher("category", "memory")), null, memoryEdgeColor, null));
|
||||
f.addRule(new ColorFilter.ColorRule(new MatcherSelector(new Properties.StringPropertyMatcher("category", "mixed")), null, mixedEdgeColor, null));
|
||||
f.addRule(new ColorFilter.ColorRule(new MatcherSelector(new Properties.StringPropertyMatcher("category", "control")), null, controlEdgeColor, null));
|
||||
f.addRule(new ColorFilter.ColorRule(new MatcherSelector(new Properties.StringPropertyMatcher("category", "other")), null, otherEdgeColor, null));
|
||||
f.addRule(new ColorFilter.ColorRule(matches("category", "data"), null, dataEdgeColor, null));
|
||||
f.addRule(new ColorFilter.ColorRule(matches("category", "memory"), null, memoryEdgeColor, null));
|
||||
f.addRule(new ColorFilter.ColorRule(matches("category", "mixed"), null, mixedEdgeColor, null));
|
||||
f.addRule(new ColorFilter.ColorRule(matches("category", "control"), null, controlEdgeColor, null));
|
||||
f.addRule(new ColorFilter.ColorRule(matches("category", "other"), null, otherEdgeColor, null));
|
||||
f.apply(graph);
|
||||
@@ -0,0 +1,66 @@
|
||||
// Condense the graph without information loss and make the structure of the
|
||||
// intermediate representation more explicit. This filter is most effective in
|
||||
// combination with "Simplify graph".
|
||||
|
||||
// Pretty-print Bool nodes to be shown as output slots.
|
||||
function replaceComparisonWithSign(dump_spec) {
|
||||
var comparison = dump_spec.replace('[','').replace(']','')
|
||||
switch (comparison) {
|
||||
case "eq": return "=";
|
||||
case "gt": return ">";
|
||||
case "lt": return "<";
|
||||
case "ne": return "≠";
|
||||
case "le": return "≤";
|
||||
case "ge": return "≥";
|
||||
default: return comparison;
|
||||
}
|
||||
}
|
||||
editSameProperty(matches("name", "Bool"), "dump_spec", replaceComparisonWithSign);
|
||||
|
||||
// Add a more informative text for null-pointer input slots.
|
||||
editSameProperty(and([matches("name", "ConP|ConN"), matches("dump_spec", "#.*NULL")]),
|
||||
"short_name",
|
||||
function(t) {return "null";});
|
||||
|
||||
// Pretty-print CatchProj nodes.
|
||||
function catchProjShortText(con) {
|
||||
switch (con) {
|
||||
case "0": return "F"; // fall-through
|
||||
case "1": return "T"; // throw
|
||||
default: return "?";
|
||||
}
|
||||
}
|
||||
editProperty(matches("name", "CatchProj"), "con", "short_name", catchProjShortText);
|
||||
|
||||
// Add short text to inlined Mach data parameters.
|
||||
editProperty(and([matches("name", "MachProj"),
|
||||
matches("category", "data"),
|
||||
successorOf(matches("name", "Start"))]),
|
||||
"dump_spec", "short_name",
|
||||
function(dump_spec) {return dump_spec;});
|
||||
|
||||
// Condense inputs in all nodes.
|
||||
var anyNode = matches("name", ".*");
|
||||
removeEmptySlots(anyNode);
|
||||
|
||||
// Inline ("split") Parm and start MachProj nodes, except control ones.
|
||||
split(and([matches("name", "Parm|MachProj"),
|
||||
not(matches("category", "control")),
|
||||
successorOf(matches("name", "Start"))]),
|
||||
["[short_name]"]);
|
||||
|
||||
// Combine single-input nodes.
|
||||
combine(anyNode, matches("name", "Proj|IfFalse|IfTrue|JProj|MachProj|JumpProj|CatchProj|Parm"));
|
||||
combine(anyNode, matches("name", "SCMemProj"), ["SCM"]);
|
||||
combine(matches("name", "SubTypeCheck|Cmp.*"), matches("name", "Bool"), ["[dump_spec]"]);
|
||||
combine(anyNode, matches("name", "Decode(N|NarrowPtr|NKlass)"), ["DC"]);
|
||||
combine(anyNode, matches("name", "Conv2B"), ["2B"]);
|
||||
combine(anyNode, matches("name", "Conv[LFD]2I"), ["2I"]);
|
||||
combine(anyNode, matches("name", "Conv[IFD]2L"), ["2L"]);
|
||||
combine(anyNode, matches("name", "Conv[ILD]2F"), ["2F"]);
|
||||
combine(anyNode, matches("name", "Conv[ILF]2D"), ["2D"]);
|
||||
|
||||
// Inline ("split") constant nodes.
|
||||
split(matches("name", "MachTemp"), ["T"]);
|
||||
split(matches("name", "ThreadLocal"), ["TL"]);
|
||||
split(matches("name", "(Con[A-Z]?)|ConNKlass|(loadCon.*)"), ["[short_name]", "[name]"]);
|
||||
@@ -0,0 +1,46 @@
|
||||
// This filter adds a new line to the label of selected nodes with custom
|
||||
// information. This is achieved by adding a special property 'extra_label' to
|
||||
// them with information extracted from other properties, typically 'dump_spec'.
|
||||
|
||||
// Add extra line to method calls with callee information.
|
||||
function callJavaInfo(dump_spec, regularPos, trapPos) {
|
||||
dump_components = split_string(dump_spec);
|
||||
if (dump_components.length < (trapPos + 1)) {
|
||||
return null;
|
||||
}
|
||||
var tm = /(uncommon_trap\(reason=\'(\w*)\')/.exec(dump_components[trapPos]);
|
||||
if (tm == null || typeof tm[2] == 'undefined') {
|
||||
return dump_components[regularPos];
|
||||
}
|
||||
return "trap: " + tm[2];
|
||||
}
|
||||
editProperty(matches("name", "CallStaticJava|CallDynamicJava|CallJava"), "dump_spec", "extra_label",
|
||||
function(dump_spec) {return callJavaInfo(dump_spec, 2, 2);});
|
||||
editProperty(matches("name", "CallStaticJavaDirect|CallDynamicJavaDirect"), "dump_spec", "extra_label",
|
||||
function(dump_spec) {return callJavaInfo(dump_spec, 1, 3);});
|
||||
|
||||
function callLeafInfo(dump_spec, pos) {
|
||||
dump_components = split_string(dump_spec);
|
||||
if (dump_components.length < pos + 1) {
|
||||
return null;
|
||||
}
|
||||
return dump_components[pos];
|
||||
}
|
||||
editProperty(matches("name", "CallLeaf|CallLeafNoFP"), "dump_spec", "extra_label",
|
||||
function(dump_spec) {return callLeafInfo(dump_spec, 1);});
|
||||
editProperty(matches("name", "CallLeafDirect|CallLeafDirectVector|CallLeafNoFPDirect"), "dump_spec", "extra_label",
|
||||
function(dump_spec) {return callLeafInfo(dump_spec, 0);});
|
||||
|
||||
// Add extra line to exception creation nodes with the name of the exception.
|
||||
function exceptionInfo(dump_spec) {
|
||||
dump_spec2 = dump_spec.replace('#','')
|
||||
dump_components = split_string(dump_spec2);
|
||||
if (dump_components.length < 1) {
|
||||
return null;
|
||||
}
|
||||
// dump_components[0] has a form like e.g. java/lang/NumberFormatException:NotNull,
|
||||
// we want to return only the simple class name ("NumberFormatException").
|
||||
simple_classname = dump_components[0].split("/").pop();
|
||||
return simple_classname.split(":")[0];
|
||||
}
|
||||
editProperty(matches("name", "CreateEx|CreateException"), "dump_spec", "extra_label", exceptionInfo);
|
||||
@@ -1,3 +1 @@
|
||||
var f = new RemoveFilter("Hide control subgraph");
|
||||
f.addRule(new RemoveFilter.RemoveRule(new MatcherSelector(new Properties.StringPropertyMatcher("category", "control"))));
|
||||
f.apply(graph);
|
||||
remove(matches("category", "control"));
|
||||
|
||||
@@ -1,5 +1 @@
|
||||
var f = new ConnectionFilter("Hide control edges");
|
||||
f.addRule(new ConnectionFilter.ConnectionStyleRule(new MatcherSelector(new Properties.StringPropertyMatcher("category", "control")),
|
||||
white,
|
||||
Connection.ConnectionStyle.INVISIBLE));
|
||||
f.apply(graph);
|
||||
styleOutputConnections(matches("category", "control"), white, invisibleConnection);
|
||||
|
||||
@@ -1,3 +1 @@
|
||||
var f = new RemoveFilter("Hide data subgraph");
|
||||
f.addRule(new RemoveFilter.RemoveRule(new MatcherSelector(new Properties.StringPropertyMatcher("category", "data"))));
|
||||
f.apply(graph);
|
||||
remove(matches("category", "data"));
|
||||
|
||||
@@ -1,5 +1 @@
|
||||
var f = new ConnectionFilter("Hide data edges");
|
||||
f.addRule(new ConnectionFilter.ConnectionStyleRule(new MatcherSelector(new Properties.StringPropertyMatcher("category", "data")),
|
||||
white,
|
||||
Connection.ConnectionStyle.INVISIBLE));
|
||||
f.apply(graph);
|
||||
styleOutputConnections(matches("category", "data"), white, invisibleConnection);
|
||||
|
||||
@@ -1,18 +1,2 @@
|
||||
// Hide exception blocks.
|
||||
|
||||
var f = new RemoveBlockFilter("Hide exception blocks");
|
||||
f.addRule(
|
||||
new RemoveBlockFilter.RemoveBlockRule(
|
||||
new AnySelector(
|
||||
new OrSelector(
|
||||
new MatcherSelector(
|
||||
new Properties.StringPropertyMatcher("name", "Rethrow")
|
||||
),
|
||||
new MatcherSelector(
|
||||
new Properties.StringPropertyMatcher("name", "RethrowException")
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
f.apply(graph);
|
||||
removeBlock(hasAnyNode(matches("name", "Rethrow|RethrowException")));
|
||||
|
||||
@@ -1,3 +1 @@
|
||||
var f = new RemoveFilter("Hide memory subgraph");
|
||||
f.addRule(new RemoveFilter.RemoveRule(new MatcherSelector(new Properties.StringPropertyMatcher("category", "memory"))));
|
||||
f.apply(graph);
|
||||
remove(matches("category", "memory"));
|
||||
|
||||
@@ -1,5 +1 @@
|
||||
var f = new ConnectionFilter("Hide memory edges");
|
||||
f.addRule(new ConnectionFilter.ConnectionStyleRule(new MatcherSelector(new Properties.StringPropertyMatcher("category", "memory")),
|
||||
white,
|
||||
Connection.ConnectionStyle.INVISIBLE));
|
||||
f.apply(graph);
|
||||
styleOutputConnections(matches("category", "memory"), white, invisibleConnection);
|
||||
|
||||
@@ -1,3 +1 @@
|
||||
var f = new RemoveFilter("Hide mixed subgraph");
|
||||
f.addRule(new RemoveFilter.RemoveRule(new MatcherSelector(new Properties.StringPropertyMatcher("category", "mixed"))));
|
||||
f.apply(graph);
|
||||
remove(matches("category", "mixed"));
|
||||
|
||||
@@ -1,5 +1 @@
|
||||
var f = new ConnectionFilter("Hide mixed edges");
|
||||
f.addRule(new ConnectionFilter.ConnectionStyleRule(new MatcherSelector(new Properties.StringPropertyMatcher("category", "mixed")),
|
||||
white,
|
||||
Connection.ConnectionStyle.INVISIBLE));
|
||||
f.apply(graph);
|
||||
styleOutputConnections(matches("category", "mixed"), white, invisibleConnection);
|
||||
|
||||
@@ -1,3 +1 @@
|
||||
var f = new RemoveFilter("Hide other subgraph");
|
||||
f.addRule(new RemoveFilter.RemoveRule(new MatcherSelector(new Properties.StringPropertyMatcher("category", "other"))));
|
||||
f.apply(graph);
|
||||
remove(matches("category", "other"));
|
||||
|
||||
@@ -1,5 +1 @@
|
||||
var f = new ConnectionFilter("Hide other edges");
|
||||
f.addRule(new ConnectionFilter.ConnectionStyleRule(new MatcherSelector(new Properties.StringPropertyMatcher("category", "other")),
|
||||
white,
|
||||
Connection.ConnectionStyle.INVISIBLE));
|
||||
f.apply(graph);
|
||||
styleOutputConnections(matches("category", "other"), white, invisibleConnection);
|
||||
|
||||
@@ -1,13 +1,2 @@
|
||||
// Remove root block and all nodes in it (hopefully just the Root node).
|
||||
|
||||
var f = new RemoveBlockFilter("Hide root block");
|
||||
f.addRule(
|
||||
new RemoveBlockFilter.RemoveBlockRule(
|
||||
new AnySelector(
|
||||
new MatcherSelector(
|
||||
new Properties.RegexpPropertyMatcher("name", "Root")
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
f.apply(graph);
|
||||
removeBlock(hasAnyNode(matches("name", "Root")));
|
||||
|
||||
@@ -1,13 +1,2 @@
|
||||
// Hide uncommon trap blocks.
|
||||
|
||||
var f = new RemoveBlockFilter("Hide uncommon trap blocks");
|
||||
f.addRule(
|
||||
new RemoveBlockFilter.RemoveBlockRule(
|
||||
new AnySelector(
|
||||
new MatcherSelector(
|
||||
new Properties.RegexpPropertyMatcher("dump_spec", ".*uncommon_trap.*")
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
f.apply(graph);
|
||||
removeBlock(hasAnyNode(matches("dump_spec", ".*uncommon_trap.*")));
|
||||
|
||||
@@ -1,27 +1,6 @@
|
||||
// Remove all nodes except control, mixed, and nodes of 'bottom' type that are
|
||||
// successors of control nodes (typically 'Halt', 'Return', etc.).
|
||||
|
||||
var f = new RemoveFilter("Show only control flow");
|
||||
f.addRule(
|
||||
new RemoveFilter.RemoveRule(
|
||||
new InvertSelector(
|
||||
new OrSelector(
|
||||
new MatcherSelector(
|
||||
new Properties.RegexpPropertyMatcher("category", "control|mixed")
|
||||
),
|
||||
new AndSelector(
|
||||
new SuccessorSelector(
|
||||
new MatcherSelector(
|
||||
new Properties.RegexpPropertyMatcher("type", "control")
|
||||
)
|
||||
),
|
||||
new MatcherSelector(
|
||||
new Properties.RegexpPropertyMatcher("type", "bottom")
|
||||
)
|
||||
)
|
||||
)
|
||||
),
|
||||
false
|
||||
)
|
||||
);
|
||||
f.apply(graph);
|
||||
remove(not(or([matches("name", "Root"),
|
||||
matches("category", "control|mixed"),
|
||||
and([matches("type", "bottom"),
|
||||
successorOf(matches("type", "control"))])])));
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
// Hide graph elements that are typically (but not always) unnecessary to
|
||||
// analyze the intermediate representation. This filter is most effective in
|
||||
// combination with "Condense graph".
|
||||
|
||||
// Remove self-loops (typical for region-like control nodes).
|
||||
removeSelfLoops();
|
||||
|
||||
// Hide secondary edges.
|
||||
remove(matches("short_name", "FP|RA|IO|RP"));
|
||||
|
||||
// Remove back-edges to the Root node.
|
||||
removeInputs(matches("name", "Root"), matches("name", ".*"));
|
||||
|
||||
// Remove top inputs from call-like nodes.
|
||||
removeInputs(matches("name", "SafePoint|CallStaticJava|CallDynamicJava|CallJava|CallLeaf|CallRuntime|AbstractLock|CallLeafNoFP|Call|CallStaticJavaDirect|Halt|Rethrow|ShouldNotReachHere|RethrowException|Return|Ret|MergeMem|Initialize|MemBarAcquire|MemBarRelease|Unlock|Lock|Allocate|AllocateArray"),
|
||||
and([matches("name", "Con"), matches("type", "top")]));
|
||||
@@ -1,19 +0,0 @@
|
||||
// Hide secondary edges.
|
||||
remove("dump_spec", "FramePtr|ReturnAdr|I_O");
|
||||
removeInputs("name", "Root");
|
||||
var f = new RemoveSelfLoopsFilter("Remove Self-Loops");
|
||||
f.apply(graph);
|
||||
removeInputs("name", "SafePoint|CallStaticJava|CallDynamicJava|CallJava|CallLeaf|CallRuntime|AbstractLock|CallLeafNoFP|Call|CallStaticJavaDirect", 5);
|
||||
removeInputs("name", "Unlock|Lock", 7);
|
||||
removeInputs("name", "Allocate", 7);
|
||||
removeInputs("name", "AllocateArray", 9);
|
||||
|
||||
// Combine projection nodes.
|
||||
var f = new CombineFilter("Combine Filter");
|
||||
f.addRule(new CombineFilter.CombineRule(new Properties.RegexpPropertyMatcher("name", ".*"), new Properties.RegexpPropertyMatcher("name", "Proj|IfFalse|IfTrue|JProj|MachProj|JumpProj|CatchProj")));
|
||||
f.addRule(new CombineFilter.CombineRule(new Properties.RegexpPropertyMatcher("name", "Cmp.*"), new Properties.RegexpPropertyMatcher("name", "Bool")));
|
||||
f.apply(graph);
|
||||
|
||||
// Inline (split) constant nodes.
|
||||
split("name", "BoxLock");
|
||||
split("name", "(Con.*)|(loadCon.*)", "[dump_spec]");
|
||||
@@ -13,13 +13,21 @@
|
||||
<attr name="enabled" boolvalue="true"/>
|
||||
<attr name="after" stringvalue="Color by execution frequency"/>
|
||||
</file>
|
||||
<file name="Simplify graph.js" url="filters/structural.filter">
|
||||
<file name="Show custom node info.js" url="filters/customNodeInfo.filter">
|
||||
<attr name="enabled" boolvalue="true"/>
|
||||
<attr name="after" stringvalue="Color by execution frequency"/>
|
||||
</file>
|
||||
<file name="Simplify graph.js" url="filters/simplifyGraph.filter">
|
||||
<attr name="enabled" boolvalue="false"/>
|
||||
<attr name="after" stringvalue="Show node warnings"/>
|
||||
<attr name="after" stringvalue="Show custom node info"/>
|
||||
</file>
|
||||
<file name="Condense graph.js" url="filters/condenseGraph.filter">
|
||||
<attr name="enabled" boolvalue="false"/>
|
||||
<attr name="after" stringvalue="Simplify graph"/>
|
||||
</file>
|
||||
<file name="Hide data subgraph.js" url="filters/hideData.filter">
|
||||
<attr name="enabled" boolvalue="false"/>
|
||||
<attr name="after" stringvalue="Simplify graph"/>
|
||||
<attr name="after" stringvalue="Condense graph"/>
|
||||
</file>
|
||||
<file name="Hide memory subgraph.js" url="filters/hideMemory.filter">
|
||||
<attr name="enabled" boolvalue="false"/>
|
||||
|
||||
@@ -106,7 +106,7 @@ public class FigureWidget extends Widget implements Properties.Provider, PopupMe
|
||||
middleWidget.setBackground(f.getColor());
|
||||
middleWidget.setOpaque(true);
|
||||
middleWidget.getActions().addAction(new DoubleClickAction(this));
|
||||
middleWidget.setCheckClipping(true);
|
||||
middleWidget.setCheckClipping(false);
|
||||
|
||||
dummyTop = new Widget(scene);
|
||||
int extraTopHeight =
|
||||
@@ -137,6 +137,7 @@ public class FigureWidget extends Widget implements Properties.Provider, PopupMe
|
||||
lw.setAlignment(LabelWidget.Alignment.CENTER);
|
||||
lw.setVerticalAlignment(LabelWidget.VerticalAlignment.CENTER);
|
||||
lw.setBorder(BorderFactory.createEmptyBorder());
|
||||
lw.setCheckClipping(false);
|
||||
}
|
||||
|
||||
if (getFigure().getWarning() != null) {
|
||||
|
||||
@@ -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
|
||||
@@ -23,9 +23,16 @@
|
||||
*/
|
||||
package com.sun.hotspot.igv.view.widgets;
|
||||
|
||||
import com.sun.hotspot.igv.graph.Diagram;
|
||||
import com.sun.hotspot.igv.graph.Figure;
|
||||
import com.sun.hotspot.igv.graph.FigureConnection;
|
||||
import com.sun.hotspot.igv.graph.InputSlot;
|
||||
import com.sun.hotspot.igv.view.DiagramScene;
|
||||
import java.awt.Canvas;
|
||||
import java.awt.Color;
|
||||
import java.awt.Font;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.util.List;
|
||||
import org.netbeans.api.visual.widget.Widget;
|
||||
|
||||
@@ -36,10 +43,12 @@ import org.netbeans.api.visual.widget.Widget;
|
||||
public class InputSlotWidget extends SlotWidget {
|
||||
|
||||
private InputSlot inputSlot;
|
||||
private DiagramScene scene;
|
||||
|
||||
public InputSlotWidget(InputSlot slot, DiagramScene scene, Widget parent, FigureWidget fw) {
|
||||
super(slot, scene, parent, fw);
|
||||
inputSlot = slot;
|
||||
this.scene = scene;
|
||||
}
|
||||
|
||||
public InputSlot getInputSlot() {
|
||||
@@ -58,4 +67,65 @@ public class InputSlotWidget extends SlotWidget {
|
||||
return getFigureWidget().getFigure().getDiagram().isCFG() ?
|
||||
calculateClientArea().height - 1 : Figure.SLOT_START;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintWidget() {
|
||||
super.paintWidget();
|
||||
if (getScene().getZoomFactor() < TEXT_ZOOM_FACTOR) {
|
||||
return;
|
||||
}
|
||||
// If there is a gap between the current slot and the previous one, and
|
||||
// both are visible, draw a label in between signaling the gap.
|
||||
int index = inputSlot.getPosition();
|
||||
int originalIndex = inputSlot.getOriginalIndex();
|
||||
InputSlot prevSlot = index > 0 ? inputSlot.getFigure().getInputSlots().get(index - 1) : null;
|
||||
int prevOriginalIndex = index > 0 ? prevSlot.getOriginalIndex() : -1;
|
||||
if (originalIndex > prevOriginalIndex + 1 &&
|
||||
hasVisibleConnection(inputSlot) && hasVisibleConnection(prevSlot) &&
|
||||
!scene.getModel().getShowCFG()) {
|
||||
Graphics2D g = scene.getGraphics();
|
||||
String label = "...";
|
||||
g.setColor(Color.BLACK);
|
||||
g.setFont(Diagram.SLOT_FONT.deriveFont(Font.BOLD));
|
||||
Rectangle2D labelRect = new Canvas().getFontMetrics(Diagram.SLOT_FONT).getStringBounds(label, g);
|
||||
int slotWidth = this.calculateClientArea().width;
|
||||
int xStart = this.getBounds().x + (inputSlot.hasSourceNodes() ? 0 : (slotWidth / 2));
|
||||
int prevXEnd;
|
||||
if (index > 0) {
|
||||
// Compute X coordinates of previous input slot comparing its
|
||||
// calculateClientArea() with that of the current slot.
|
||||
InputSlotWidget prevWidget = (InputSlotWidget)scene.findWidget(prevSlot);
|
||||
int prevSlotWidth = prevWidget.calculateClientArea().width;
|
||||
int xStartAbs = inputSlot.getRelativePosition().x - (slotWidth / 2);
|
||||
int prevXStartAbs = prevSlot.getRelativePosition().x - (prevSlotWidth / 2);
|
||||
int prevXStart = prevXStartAbs - xStartAbs;
|
||||
prevXEnd = prevXStart + (prevSlot.hasSourceNodes() ? prevSlotWidth : (prevSlotWidth / 2));
|
||||
} else {
|
||||
// No previous input slot, just set its position to the left of
|
||||
// the current one.
|
||||
prevXEnd = xStart - (int) (labelRect.getWidth()) - 4;
|
||||
}
|
||||
int midX = (prevXEnd + xStart) / 2;
|
||||
g.drawString(label, midX - (int)(labelRect.getWidth() / 2), 3);
|
||||
}
|
||||
}
|
||||
|
||||
// This method needs to be called at painting time, so that the right
|
||||
// FigureWidget::isVisible() result is picked up.
|
||||
private boolean hasVisibleConnection(InputSlot slot) {
|
||||
if (slot == null) {
|
||||
return true;
|
||||
}
|
||||
if (slot.hasSourceNodes()) {
|
||||
return true;
|
||||
}
|
||||
for (FigureConnection c : slot.getConnections()) {
|
||||
Figure f = c.getOutputSlot().getFigure();
|
||||
FigureWidget fw = (FigureWidget)scene.findWidget(f);
|
||||
if (fw.isVisible()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -46,8 +46,8 @@ public abstract class SlotWidget extends Widget implements DoubleClickHandler {
|
||||
|
||||
private Slot slot;
|
||||
private FigureWidget figureWidget;
|
||||
private static double TEXT_ZOOM_FACTOR = 0.9;
|
||||
private static double ZOOM_FACTOR = 0.6;
|
||||
protected static double TEXT_ZOOM_FACTOR = 0.9;
|
||||
protected static double ZOOM_FACTOR = 0.6;
|
||||
private DiagramScene diagramScene;
|
||||
|
||||
public SlotWidget(Slot slot, DiagramScene scene, Widget parent, FigureWidget fw) {
|
||||
@@ -58,7 +58,8 @@ public abstract class SlotWidget extends Widget implements DoubleClickHandler {
|
||||
if (slot.hasSourceNodes()) {
|
||||
this.setToolTipText("<HTML>" + slot.getToolTipText() + "</HTML>");
|
||||
}
|
||||
this.setCheckClipping(true);
|
||||
// No clipping, to let input slots draw gap markers outside their bounds.
|
||||
this.setCheckClipping(false);
|
||||
parent.addChild(this);
|
||||
|
||||
Point p = slot.getRelativePosition();
|
||||
|
||||
Reference in New Issue
Block a user