From f3ba7676043756f7cf95d5215e18bd65e9f167e6 Mon Sep 17 00:00:00 2001 From: Tobias Holenstein Date: Mon, 11 Nov 2024 13:25:42 +0000 Subject: [PATCH] 8343535: IGV: Colorize nodes on demand MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Roberto CastaƱeda Lozano Reviewed-by: chagedorn, rcastanedalo --- .../sun/hotspot/igv/view/DiagramScene.java | 13 +- .../sun/hotspot/igv/view/DiagramViewer.java | 9 +- .../hotspot/igv/view/EditorTopComponent.java | 5 + .../hotspot/igv/view/actions/ColorAction.java | 170 ++++++++++++++++++ .../igv/view/actions/ExtractAction.java | 4 +- .../igv/view/widgets/FigureWidget.java | 37 ++-- .../com/sun/hotspot/igv/view/images/color.gif | Bin 0 -> 207 bytes 7 files changed, 216 insertions(+), 22 deletions(-) create mode 100644 src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/actions/ColorAction.java create mode 100644 src/utils/IdealGraphVisualizer/View/src/main/resources/com/sun/hotspot/igv/view/images/color.gif diff --git a/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/DiagramScene.java b/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/DiagramScene.java index e47518de4a7..f9c2e991d46 100644 --- a/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/DiagramScene.java +++ b/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/DiagramScene.java @@ -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(); } diff --git a/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/DiagramViewer.java b/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/DiagramViewer.java index 591bbe371a3..e8cfd2968dc 100644 --- a/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/DiagramViewer.java +++ b/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/DiagramViewer.java @@ -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); } diff --git a/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/EditorTopComponent.java b/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/EditorTopComponent.java index 617f59a591d..e24ffa476a2 100644 --- a/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/EditorTopComponent.java +++ b/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/EditorTopComponent.java @@ -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(); } diff --git a/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/actions/ColorAction.java b/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/actions/ColorAction.java new file mode 100644 index 00000000000..7a38587eb38 --- /dev/null +++ b/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/actions/ColorAction.java @@ -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 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(); + } +} diff --git a/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/actions/ExtractAction.java b/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/actions/ExtractAction.java index 24815527a0e..24547b19b6a 100644 --- a/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/actions/ExtractAction.java +++ b/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/actions/ExtractAction.java @@ -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 { diff --git a/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/widgets/FigureWidget.java b/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/widgets/FigureWidget.java index 7ac76fdefba..bbdf08dc8b8 100644 --- a/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/widgets/FigureWidget.java +++ b/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/widgets/FigureWidget.java @@ -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; diff --git a/src/utils/IdealGraphVisualizer/View/src/main/resources/com/sun/hotspot/igv/view/images/color.gif b/src/utils/IdealGraphVisualizer/View/src/main/resources/com/sun/hotspot/igv/view/images/color.gif new file mode 100644 index 0000000000000000000000000000000000000000..fb95a6f29589d10b649edb2204bc016b0cf30b5e GIT binary patch literal 207 zcmZ?wbh9u|6krfwIKlt|Oj6TAm0JI)F?`o%{H@KPnLV>o!+pW!FN%3lose>435{~v4&c0%zd3nv$YID-yI8e}H} ztIq?4K4(VX46BKYS1wx#_W`pb{G%QzUU0YRNdMF0Q* literal 0 HcmV?d00001