From 5e91d5e9ada004800f13bcaaed075238bad93c2d Mon Sep 17 00:00:00 2001 From: dragonmacher <48328597+dragonmacher@users.noreply.github.com> Date: Mon, 31 Aug 2026 18:42:55 -0400 Subject: [PATCH] GP-7200 - Added a refresh button to the Data Type Compare window --- .../Features/Base/data/base.theme.properties | 1 + .../core/datamgr/DataTypeComparePanel.java | 82 +++++++++++++------ .../core/datamgr/DataTypeCompareProvider.java | 15 ++++ .../core/datamgr/DataTypeSyncDialog.java | 7 +- .../core/datamgr/DataTypesProvider.java | 6 +- .../action/builder/AbstractActionBuilder.java | 6 ++ 6 files changed, 86 insertions(+), 31 deletions(-) diff --git a/Ghidra/Features/Base/data/base.theme.properties b/Ghidra/Features/Base/data/base.theme.properties index f461cc6537..5012f9cc33 100644 --- a/Ghidra/Features/Base/data/base.theme.properties +++ b/Ghidra/Features/Base/data/base.theme.properties @@ -186,6 +186,7 @@ font.splash.infopanel = SansSerif-BOLD-14 font.plugin.assembly.dual.text.field = font.monospaced font.plugin.console = font.monospaced +font.plugin.datamgr.compare.name = [font]system.font.control[bold] font.plugin.entropy.label.knot = sansserif-bold-12 font.plugin.function.text.editor = sansserif-plain-18 font.plugin.instruction.table.renderer = courier-plain-14 diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypeComparePanel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypeComparePanel.java index 5f5fd203d0..5b36ed18e4 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypeComparePanel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypeComparePanel.java @@ -16,34 +16,38 @@ package ghidra.app.plugin.core.datamgr; import java.awt.*; +import java.awt.event.MouseEvent; import javax.swing.*; -import docking.widgets.label.GDHtmlLabel; +import docking.widgets.label.GDLabel; import docking.widgets.textpane.GHtmlTextPane; import generic.theme.GThemeDefaults.Colors; +import generic.theme.Gui; import ghidra.app.util.ToolTipUtils; import ghidra.app.util.html.HTMLDataTypeRepresentation; -import ghidra.program.model.data.DataType; -import ghidra.util.HTMLUtilities; +import ghidra.program.model.data.*; /** * Panel that displays two data types side by side. */ class DataTypeComparePanel extends JPanel { + private static final String NAME_FONT_ID = "font.plugin.datamgr.compare.name"; private GHtmlTextPane leftDtPane; private GHtmlTextPane rightDtPane; private JPanel leftPanel; private JPanel rightPanel; private JLabel leftNameLabel; private JLabel rightNameLabel; - private String clientName; + private JLabel leftDescriptionLabel; + private JLabel rightDescriptionLabel; + private String localName; private String sourceName; - DataTypeComparePanel(String clientName, String sourceName) { + DataTypeComparePanel(String localName, String sourceName) { super(new GridLayout(0, 2)); - this.clientName = clientName; + this.localName = localName; this.sourceName = sourceName; init(); } @@ -54,13 +58,23 @@ class DataTypeComparePanel extends JPanel { leftPanel = new JPanel(new BorderLayout()); rightPanel = new JPanel(new BorderLayout()); - leftNameLabel = new GDHtmlLabel(); - rightNameLabel = new GDHtmlLabel(); - leftNameLabel.setBorder(BorderFactory.createEmptyBorder(2, 8, 2, 0)); - rightNameLabel.setBorder(BorderFactory.createEmptyBorder(2, 8, 2, 0)); + leftNameLabel = createLabelWidet(); + rightNameLabel = createLabelWidet(); + leftDescriptionLabel = createLabelWidet(); + rightDescriptionLabel = createLabelWidet(); - setLabelText(leftNameLabel, HTMLUtilities.escapeHTML(clientName) + ":"); - setLabelText(rightNameLabel, HTMLUtilities.escapeHTML(sourceName) + ":"); + leftNameLabel.setText(localName + ":"); + rightNameLabel.setText(sourceName + ":"); + + JPanel leftLabelPanel = new JPanel(); + leftLabelPanel.setLayout(new BoxLayout(leftLabelPanel, BoxLayout.PAGE_AXIS)); + leftLabelPanel.add(leftNameLabel); + leftLabelPanel.add(leftDescriptionLabel); + + JPanel rightLabelPanel = new JPanel(); + rightLabelPanel.setLayout(new BoxLayout(rightLabelPanel, BoxLayout.PAGE_AXIS)); + rightLabelPanel.add(rightNameLabel); + rightLabelPanel.add(rightDescriptionLabel); add(leftPanel); add(rightPanel); @@ -79,10 +93,31 @@ class DataTypeComparePanel extends JPanel { rightScrollPane.getVerticalScrollBar().setUnitIncrement(9); leftPanel.add(leftScrollPane); rightPanel.add(rightScrollPane); - leftPanel.add(leftNameLabel, BorderLayout.NORTH); - rightPanel.add(rightNameLabel, BorderLayout.NORTH); + leftPanel.add(leftLabelPanel, BorderLayout.NORTH); + rightPanel.add(rightLabelPanel, BorderLayout.NORTH); syncScrollers(leftScrollPane, rightScrollPane); + } + private JLabel createLabelWidet() { + JLabel label = new GDLabel() { + @Override + public String getToolTipText(MouseEvent e) { + FontMetrics fm = getFontMetrics(getFont()); + int textWidth = fm.stringWidth(getText()); + int availableWidth = getWidth() - getInsets().left - getInsets().right; + if (textWidth > availableWidth) { + return getText(); + } + return null; + } + }; + ToolTipManager.sharedInstance().registerComponent(label); + label.setBorder(BorderFactory.createEmptyBorder(2, 8, 2, 0)); + + Font font = Gui.getFont(NAME_FONT_ID); + label.setFont(font); + + return label; } private void syncScrollers(JScrollPane leftScrollPane, JScrollPane rightScrollPane) { @@ -104,11 +139,17 @@ class DataTypeComparePanel extends JPanel { * @param dataType2 the second data type to display. */ void setDataTypes(DataType dataType1, DataType dataType2) { - String path1 = dataType1 != null ? dataType1.getPathName() : ""; - String path2 = dataType2 != null ? dataType2.getPathName() : ""; - setLabelText(leftNameLabel, clientName + ":
" + path1); - setLabelText(rightNameLabel, sourceName + ":
" + path2); + DataTypePath path1 = dataType1 != null ? dataType1.getDataTypePath() : null; + DataTypePath path2 = dataType2 != null ? dataType2.getDataTypePath() : null; + + CategoryPath catPath1 = path1.getCategoryPath(); + CategoryPath catPath2 = path2.getCategoryPath(); + leftNameLabel.setText(localName + ':' + catPath1.getPath()); + rightNameLabel.setText(sourceName + ':' + catPath2.getPath()); + + leftDescriptionLabel.setText(path1.getDataTypeName()); + rightDescriptionLabel.setText(path2.getDataTypeName()); HTMLDataTypeRepresentation representation1 = ToolTipUtils.getHTMLRepresentation(dataType1); HTMLDataTypeRepresentation representation2 = ToolTipUtils.getHTMLRepresentation(dataType2); @@ -123,11 +164,6 @@ class DataTypeComparePanel extends JPanel { rightDtPane.setText(dt2Text); } - private void setLabelText(JLabel label, String text) { - label.setText(HTMLUtilities.wrapAsHTML(HTMLUtilities.bold(text))); - - } - public boolean isLeft(Component component) { return SwingUtilities.isDescendingFrom(component, leftPanel); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypeCompareProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypeCompareProvider.java index 57fa90da29..2e6b6f9b7d 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypeCompareProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypeCompareProvider.java @@ -26,6 +26,7 @@ import ghidra.app.services.DataTypeManagerService; import ghidra.program.model.data.DataType; import ghidra.program.model.data.DataTypeManager; import ghidra.util.HelpLocation; +import resources.Icons; /** * A provider that shows a comparison between two data types. @@ -60,6 +61,11 @@ public class DataTypeCompareProvider extends ComponentProvider { .popupMenuPath("Show Data Type") .onAction(this::showType) .buildAndInstallLocal(this); + + new ActionBuilder("Refresh", getOwner()) + .toolBarIcon(Icons.REFRESH_ICON) + .onAction(this::refresh) + .buildAndInstallLocal(this); } private void showType(ActionContext context) { @@ -74,6 +80,15 @@ public class DataTypeCompareProvider extends ComponentProvider { service.setDataTypeSelected(dt); } + private void refresh(ActionContext context) { + DataTypeManager leftDtm = leftDt.getDataTypeManager(); + DataTypeManager rightDtm = rightDt.getDataTypeManager(); + leftDt = leftDtm.resolve(leftDt, null); + rightDt = rightDtm.resolve(rightDt, null); + + compareComponent.setDataTypes(leftDt, rightDt); + } + private void build() { DataTypeManager leftDtm = leftDt.getDataTypeManager(); DataTypeManager rightDtm = rightDt.getDataTypeManager(); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypeSyncDialog.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypeSyncDialog.java index 749891120a..bdceee562a 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypeSyncDialog.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypeSyncDialog.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -100,9 +100,6 @@ public class DataTypeSyncDialog extends DialogComponentProvider implements DataT } - /* (non-Javadoc) - * @see ghidra.app.plugin.core.datamgr.DataTypeSyncListener#dataTypeSelected(ghidra.program.model.data.DataType) - */ @Override public void dataTypeSelected(DataTypeSyncInfo syncInfo) { if (syncInfo != null) { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypesProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypesProvider.java index 69620997db..84fc1f2832 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypesProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypesProvider.java @@ -300,8 +300,8 @@ public class DataTypesProvider extends ComponentProviderAdapter { addLocalAction(viewCheckOutsAction); } - private boolean hasFilter() { - return archiveGTree.isFiltered(); + private boolean isFiltered(DataType dt) { + return archiveGTree.isFiltered() || !filterState.passesFilters(dt); } public DtFilterState getFilterState() { @@ -791,7 +791,7 @@ public class DataTypesProvider extends ComponentProviderAdapter { DataTypeNode dataTypeNode = node.getNode(dataType); if (dataTypeNode == null) { - if (hasFilter()) { + if (isFiltered(dataType)) { plugin.setStatus("Unable to find " + dataType.getName() + ". It may be filtered out of view. (Data Type Manager)"); } diff --git a/Ghidra/Framework/Docking/src/main/java/docking/action/builder/AbstractActionBuilder.java b/Ghidra/Framework/Docking/src/main/java/docking/action/builder/AbstractActionBuilder.java index b0eef5138e..9ccaddfdb8 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/action/builder/AbstractActionBuilder.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/action/builder/AbstractActionBuilder.java @@ -25,6 +25,7 @@ import javax.swing.KeyStroke; import docking.*; import docking.action.*; import docking.actions.KeyBindingUtils; +import generic.theme.GIcon; import ghidra.util.HelpLocation; import ghidra.util.Msg; import resources.ResourceManager; @@ -440,6 +441,9 @@ public abstract class AbstractActionBuilder + * Clients should be passing in {@link GIcon}s so that icons can be changed via the theme + * framework. * * @param icon the icon to use in the action's tool bar * @return this builder (for chaining) @@ -457,7 +461,9 @@ public abstract class AbstractActionBuilder