8345039: IGV: save user-defined node colors to XML

Co-authored-by: Roberto Castañeda Lozano <rcastanedalo@openjdk.org>
Co-authored-by: Christian Hagedorn <chagedorn@openjdk.org>
Reviewed-by: chagedorn, epeter, rcastanedalo
This commit is contained in:
Tobias Holenstein 2024-11-29 15:21:39 +00:00
parent 28b0f3eaa5
commit a80ccf2cd2
6 changed files with 75 additions and 6 deletions

View file

@ -23,6 +23,7 @@
*/
package com.sun.hotspot.igv.data;
import java.awt.Color;
import java.util.Objects;
/**
@ -67,4 +68,27 @@ public class InputNode extends Properties.Entity {
public String toString() {
return "Node " + id + " " + getProperties().toString();
}
public void setCustomColor(Color color) {
if (color != null) {
String hexColor = String.format("#%08X", color.getRGB());
getProperties().setProperty("color", hexColor);
} else {
getProperties().setProperty("color", null);
}
}
public Color getCustomColor() {
String hexColor = getProperties().get("color");
if (hexColor != null) {
try {
String hex = hexColor.startsWith("#") ? hexColor.substring(1) : hexColor;
int argb = (int) Long.parseLong(hex, 16);
return new Color(argb, true);
} catch (Exception ignored) {
return null;
}
}
return null;
}
}

View file

@ -36,6 +36,7 @@ public class Diagram {
private final Map<InputNode, Figure> figures;
private final Map<InputBlock, Block> blocks;
private final InputGraph inputGraph;
private final String nodeText;
private final String shortNodeText;
private final String tinyNodeText;
@ -66,6 +67,7 @@ public class Diagram {
this.figures = new LinkedHashMap<>();
this.blocks = new LinkedHashMap<>(8);
this.blockConnections = new HashSet<>();
this.inputGraph = graph;
this.cfg = false;
int curId = 0;
@ -128,6 +130,10 @@ public class Diagram {
}
}
public InputGraph getInputGraph() {
return inputGraph;
}
public Block getBlock(InputBlock b) {
assert blocks.containsKey(b);
return blocks.get(b);

View file

@ -23,6 +23,7 @@
*/
package com.sun.hotspot.igv.graph;
import com.sun.hotspot.igv.data.InputGraph;
import com.sun.hotspot.igv.data.InputNode;
import com.sun.hotspot.igv.data.Properties;
import com.sun.hotspot.igv.layout.Cluster;
@ -153,8 +154,13 @@ public class Figure extends Properties.Entity implements Vertex {
}
public Color getColor() {
Color customColor = inputNode.getCustomColor();
if (customColor != null) {
return customColor;
} else {
return color;
}
}
public void setWarning(String warning) {
this.warning = getProperties().resolveString(warning);
@ -415,4 +421,16 @@ public class Figure extends Properties.Entity implements Vertex {
public int compareTo(Vertex f) {
return toString().compareTo(f.toString());
}
public void setCustomColor(Color color) {
// Apply custom color not just to this input node but to all
// corresponding input nodes in the group.
InputGraph graph = diagram.getInputGraph();
for (InputGraph g : graph.getGroup().getGraphs()) {
InputNode n = g.getNode(inputNode.getId());
if (n != null) {
n.setCustomColor(color);
}
}
}
}

View file

@ -230,7 +230,7 @@ public class DiagramScene extends ObjectScene implements DiagramViewer, DoubleCl
public void colorSelectedFigures(Color color) {
for (Figure figure : model.getSelectedFigures()) {
figure.setColor(color);
figure.setCustomColor(color);
FigureWidget figureWidget = getWidget(figure);
if (figureWidget != null) {
figureWidget.refreshColor();

View file

@ -82,6 +82,7 @@ public final class ColorAction extends ModelAwareAction {
private static final JLabel selectedColorLabel = new JLabel("Preview");
private static final JColorChooser colorChooser = new JColorChooser(Color.WHITE);
private static final Color NO_COLOR = new Color(0, 0, 0, 0);
public ColorAction() {
initializeComponents();
@ -89,8 +90,8 @@ public final class ColorAction extends ModelAwareAction {
private void initializeComponents() {
selectedColorLabel.setPreferredSize(new Dimension(3 * 32, 32));
selectedColorLabel.setOpaque(true);
selectedColorLabel.setBackground(Color.WHITE);
selectedColorLabel.setOpaque(false); // Allow transparency
selectedColorLabel.setBackground(NO_COLOR); // Set transparent background
selectedColorLabel.setForeground(Color.BLACK); // Set text color
selectedColorLabel.setHorizontalAlignment(SwingConstants.CENTER); // Center the text
@ -100,6 +101,7 @@ public final class ColorAction extends ModelAwareAction {
Color selectedColor = colorChooser.getColor();
if (selectedColor != null) {
selectedColorLabel.setBackground(selectedColor);
selectedColorLabel.setOpaque(selectedColor.getAlpha() != 0);
selectedColorLabel.setForeground(FigureWidget.getTextColor(selectedColor));
}
});
@ -118,10 +120,27 @@ public final class ColorAction extends ModelAwareAction {
colorButton.setPreferredSize(new Dimension(16, 16));
colorButton.addActionListener(e -> {
selectedColorLabel.setBackground(color);
selectedColorLabel.setOpaque(color.getAlpha() != 0);
selectedColorLabel.setForeground(FigureWidget.getTextColor(color));
});
colorsPanel.add(colorButton);
}
// Add "No Color" button
JButton noColorButton = new JButton("No Color");
noColorButton.setOpaque(true);
noColorButton.setContentAreaFilled(true);
noColorButton.setBorderPainted(true);
noColorButton.setPreferredSize(new Dimension(90, 24));
noColorButton.setFocusPainted(false);
noColorButton.addActionListener(e -> {
selectedColorLabel.setBackground(NO_COLOR);
selectedColorLabel.setOpaque(false);
selectedColorLabel.setForeground(Color.BLACK);
});
colorsPanel.add(noColorButton);
// Add the preview label
colorsPanel.add(selectedColorLabel, 0);
colorsPanel.revalidate();
colorsPanel.repaint();
@ -148,9 +167,10 @@ public final class ColorAction extends ModelAwareAction {
dialogLoc = dialogHolder[0].getLocation();
// OK button action
Color selectedColor = selectedColorLabel.getBackground();
if (selectedColor != null) {
editor.colorSelectedFigures(selectedColor);
if (selectedColor.equals(NO_COLOR)) {
selectedColor = null;
}
editor.colorSelectedFigures(selectedColor);
},
null // Cancel button action
);

View file

@ -271,6 +271,7 @@ public class FigureWidget extends Widget implements Properties.Provider, PopupMe
@Override
protected void paintChildren() {
refreshColor();
Composite oldComposite = null;
if (boundary) {
oldComposite = getScene().getGraphics().getComposite();