8343535: IGV: Colorize nodes on demand

Co-authored-by: Roberto Castañeda Lozano <rcastanedalo@openjdk.org>
Reviewed-by: chagedorn, rcastanedalo
This commit is contained in:
Tobias Holenstein 2024-11-11 13:25:42 +00:00
parent 5016132291
commit f3ba767604
7 changed files with 216 additions and 22 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 2024, 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
@ -222,6 +222,17 @@ public class DiagramScene extends ObjectScene implements DiagramViewer, DoubleCl
}
};
public void colorSelectedFigures(Color color) {
for (Figure figure : model.getSelectedFigures()) {
figure.setColor(color);
FigureWidget figureWidget = getWidget(figure);
if (figureWidget != null) {
figureWidget.refreshColor();
}
}
validateAll();
}
private Point getScrollPosition() {
return scrollPane.getViewport().getViewPosition();
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 2024, 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,10 +26,7 @@ package com.sun.hotspot.igv.view;
import com.sun.hotspot.igv.data.ChangedEvent;
import com.sun.hotspot.igv.data.InputNode;
import java.awt.Component;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.*;
import java.util.Collection;
import javax.swing.JComponent;
import org.openide.awt.UndoRedo;
@ -89,4 +86,6 @@ public interface DiagramViewer {
Rectangle getBounds();
JComponent getView();
void colorSelectedFigures(Color color);
}

View File

@ -99,6 +99,7 @@ public final class EditorTopComponent extends TopComponent implements TopCompone
};
Action[] actionsWithSelection = new Action[]{
ColorAction.get(ColorAction.class),
ExtractAction.get(ExtractAction.class),
HideAction.get(HideAction.class),
null,
@ -349,6 +350,10 @@ public final class EditorTopComponent extends TopComponent implements TopCompone
scene.addSelectedNodes(nodes, showIfHidden);
}
public void colorSelectedFigures(Color color) {
scene.colorSelectedFigures(color);
}
public void centerSelectedNodes() {
scene.centerSelectedFigures();
}

View File

@ -0,0 +1,170 @@
/*
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
package com.sun.hotspot.igv.view.actions;
import com.sun.hotspot.igv.view.DiagramViewModel;
import com.sun.hotspot.igv.view.EditorTopComponent;
import com.sun.hotspot.igv.view.widgets.FigureWidget;
import java.awt.*;
import java.util.ArrayList;
import java.util.Arrays;
import javax.swing.*;
import org.openide.awt.ActionID;
import org.openide.awt.ActionReference;
import org.openide.awt.ActionReferences;
import org.openide.awt.ActionRegistration;
import org.openide.util.NbBundle;
import org.openide.util.NbBundle.Messages;
@ActionID(category = "View", id = "com.sun.hotspot.igv.view.actions.ColorAction")
@ActionRegistration(displayName = "#CTL_ColorAction")
@ActionReferences({
@ActionReference(path = "Menu/View", position = 360),
@ActionReference(path = "Shortcuts", name = "D-C")
})
@Messages({
"CTL_ColorAction=Color",
"HINT_ColorAction=Color current set of selected nodes"
})
public final class ColorAction extends ModelAwareAction {
@Override
protected String iconResource() {
return "com/sun/hotspot/igv/view/images/color.gif"; // NOI18N
}
@Override
protected String getDescription() {
return NbBundle.getMessage(ColorAction.class, "HINT_ColorAction");
}
@Override
public String getName() {
return NbBundle.getMessage(ColorAction.class, "CTL_ColorAction");
}
private static final ArrayList<Color> colors = new ArrayList<>(Arrays.asList(
Color.RED,
Color.ORANGE,
Color.YELLOW,
Color.GREEN,
Color.CYAN,
Color.BLUE,
Color.MAGENTA,
Color.PINK,
Color.DARK_GRAY,
Color.GRAY,
Color.LIGHT_GRAY,
Color.WHITE
));
private static final JLabel selectedColorLabel = new JLabel("Preview");
private static final JColorChooser colorChooser = new JColorChooser(Color.WHITE);
public ColorAction() {
initializeComponents();
}
private void initializeComponents() {
selectedColorLabel.setPreferredSize(new Dimension(3 * 32, 32));
selectedColorLabel.setOpaque(true);
selectedColorLabel.setBackground(Color.WHITE);
selectedColorLabel.setForeground(Color.BLACK); // Set text color
selectedColorLabel.setHorizontalAlignment(SwingConstants.CENTER); // Center the text
// Add a ChangeListener to react to color selection changes
colorChooser.getSelectionModel().addChangeListener(e -> {
Color selectedColor = colorChooser.getColor();
if (selectedColor != null) {
selectedColorLabel.setBackground(selectedColor);
selectedColorLabel.setForeground(FigureWidget.getTextColor(selectedColor));
}
});
// Create a panel to display recent colors
JPanel colorsPanel = new JPanel();
colorsPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
for (Color color : colors) {
JButton colorButton = new JButton();
colorButton.setBackground(color);
colorButton.setOpaque(true);
colorButton.setBorderPainted(false);
colorButton.setRolloverEnabled(false);
colorButton.setRequestFocusEnabled(false);
colorButton.setPreferredSize(new Dimension(16, 16));
colorButton.addActionListener(e -> {
selectedColorLabel.setBackground(color);
selectedColorLabel.setForeground(FigureWidget.getTextColor(color));
});
colorsPanel.add(colorButton);
}
colorsPanel.add(selectedColorLabel, 0);
colorsPanel.revalidate();
colorsPanel.repaint();
// Add recent colors panel below the color chooser
colorChooser.setPreviewPanel(colorsPanel);
}
// Variables to store the dialog position
private Point dialogLoc = null;
public void performAction(DiagramViewModel model) {
EditorTopComponent editor = EditorTopComponent.getActive();
if (editor != null) {
// Create the dialog with an OK button to select the color
final JDialog[] dialogHolder = new JDialog[1];
dialogHolder[0] = JColorChooser.createDialog(
null,
"Choose a Color",
true,
colorChooser,
e -> {
// Save the current location
dialogLoc = dialogHolder[0].getLocation();
// OK button action
Color selectedColor = selectedColorLabel.getBackground();
if (selectedColor != null) {
editor.colorSelectedFigures(selectedColor);
}
},
null // Cancel button action
);
// Set the dialog's position if previously saved
if (dialogLoc != null) {
dialogHolder[0].setLocation(dialogLoc);
}
dialogHolder[0].setVisible(true);
}
}
@Override
public boolean isEnabled(DiagramViewModel model) {
return model != null && !model.getSelectedNodes().isEmpty();
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 2024, 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
@ -42,7 +42,7 @@ import org.openide.util.NbBundle.Messages;
@ActionReference(path = "Shortcuts", name = "D-X")
})
@Messages({
"CTL_ExtractAction=Extract action",
"CTL_ExtractAction=Extract",
"HINT_ExtractAction=Extract current set of selected nodes"
})
public final class ExtractAction extends ModelAwareAction {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 2024, 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
@ -90,7 +90,20 @@ public class FigureWidget extends Widget implements Properties.Provider, PopupMe
if (getFigure().getProperties().get("extra_label") != null) {
LabelWidget extraLabelWidget = labelWidgets.get(labelWidgets.size() - 1);
extraLabelWidget.setFont(Diagram.FONT.deriveFont(Font.ITALIC));
extraLabelWidget.setForeground(selected ? getTextColor() : Color.DARK_GRAY);
extraLabelWidget.setForeground(getTextColorHelper(figure.getColor(), !selected));
}
}
public static Color getTextColor(Color color) {
return getTextColorHelper(color, false);
}
private static Color getTextColorHelper(Color bg, boolean useGrey) {
double brightness = bg.getRed() * 0.21 + bg.getGreen() * 0.72 + bg.getBlue() * 0.07;
if (brightness < 150) {
return useGrey ? Color.LIGHT_GRAY : Color.WHITE;
} else {
return useGrey ? Color.DARK_GRAY : Color.BLACK;
}
}
@ -113,7 +126,6 @@ public class FigureWidget extends Widget implements Properties.Provider, PopupMe
LayoutFactory.SerialAlignment.LEFT_TOP :
LayoutFactory.SerialAlignment.CENTER;
middleWidget.setLayout(LayoutFactory.createVerticalFlowLayout(textAlign, 0));
middleWidget.setBackground(f.getColor());
middleWidget.setOpaque(true);
middleWidget.getActions().addAction(new DoubleClickAction(this));
middleWidget.setCheckClipping(false);
@ -143,13 +155,13 @@ public class FigureWidget extends Widget implements Properties.Provider, PopupMe
textWidget.addChild(lw);
lw.setLabel(displayString);
lw.setFont(Diagram.FONT);
lw.setForeground(getTextColor());
lw.setAlignment(LabelWidget.Alignment.CENTER);
lw.setVerticalAlignment(LabelWidget.VerticalAlignment.CENTER);
lw.setBorder(BorderFactory.createEmptyBorder());
lw.setCheckClipping(false);
}
formatExtraLabel(false);
refreshColor();
if (getFigure().getWarning() != null) {
ImageWidget warningWidget = new ImageWidget(scene, warningSign);
@ -184,6 +196,13 @@ public class FigureWidget extends Widget implements Properties.Provider, PopupMe
this.setToolTipText(PropertiesConverter.convertToHTML(f.getProperties()));
}
public void refreshColor() {
middleWidget.setBackground(figure.getColor());
for (LabelWidget lw : labelWidgets) {
lw.setForeground(getTextColor(figure.getColor()));
}
}
@Override
protected void notifyStateChanged(ObjectState previousState, ObjectState state) {
super.notifyStateChanged(previousState, state);
@ -222,16 +241,6 @@ public class FigureWidget extends Widget implements Properties.Provider, PopupMe
return figure;
}
private Color getTextColor() {
Color bg = figure.getColor();
double brightness = bg.getRed() * 0.21 + bg.getGreen() * 0.72 + bg.getBlue() * 0.07;
if (brightness < 150) {
return Color.WHITE;
} else {
return Color.BLACK;
}
}
@Override
protected void paintChildren() {
Composite oldComposite = null;

Binary file not shown.

After

Width:  |  Height:  |  Size: 207 B