From ab2a390fca7a23b0e92f3a6d20b2e25d0feac530 Mon Sep 17 00:00:00 2001 From: dragonmacher <48328597+dragonmacher@users.noreply.github.com> Date: Mon, 29 Jul 2019 18:20:00 -0400 Subject: [PATCH] GT-2960 - Docking Actions - Consolidated the multiple methods of adding dynamic popup actions --- Ghidra/Features/Base/.launch/Ghidra.launch | 2 +- .../merge/tool/ListingMergePanelProvider.java | 6 +- .../plugin/core/bookmark/BookmarkPlugin.java | 7 +- .../core/codebrowser/CodeViewerProvider.java | 5 +- .../core/datamgr/DataTypeManagerPlugin.java | 7 +- .../FunctionComparisonProvider.java | 7 +- .../ui/InstructionTable.java | 3 +- .../instructionsearch/ui/PreviewTable.java | 4 +- .../main/OpenVersionedFileDialog.java | 42 +++++- .../src/main/java/ghidra/test/TestTool.java | 2 +- .../docking/DockingWindowManagerTest.java | 26 ++-- .../dialogs/NumberInputDialogTest.java | 2 +- .../widgets/table/GhidraTableFilterTest.java | 2 +- .../src/test/java/ghidra/test/DummyTool.java | 11 ++ .../VTFunctionAssociationProvider.java | 8 +- .../VTMarkupItemsTableProvider.java | 8 +- .../java/docking/AbstractDockingTool.java | 11 ++ .../java/docking/ComponentLoadedListener.java | 6 +- .../java/docking/DialogComponentProvider.java | 6 +- ...ogComponentProviderPopupActionManager.java | 17 ++- .../main/java/docking/DockWinListener.java | 44 ------ .../src/main/java/docking/DockingTool.java | 22 +++ .../java/docking/DockingWindowManager.java | 68 ++++++--- .../action/DockingActionProviderIf.java | 8 +- .../docking/actions/PopupActionProvider.java | 47 +++++++ .../java/docking/widgets/table/GTable.java | 22 +-- .../test/java/docking/FakeDockingTool.java | 20 +-- .../ghidra/app/util/GenericHelpTopics.java | 5 + .../main/datatable/ProjectDataTablePanel.java | 2 +- .../main/datatree/VersionHistoryDialog.java | 44 +++--- .../main/datatree/VersionHistoryPanel.java | 131 ++++++++---------- .../VersionControlShowHistoryAction.java | 6 +- .../java/ghidra/framework/model/Tool.java | 7 - .../framework/plugintool/PluginTool.java | 63 ++------- .../framework/plugintool/PopupListener.java | 40 ------ .../framework/project/tool/GhidraTool.java | 2 +- .../screenshot/VersionControlScreenShots.java | 3 +- 37 files changed, 375 insertions(+), 341 deletions(-) delete mode 100644 Ghidra/Framework/Docking/src/main/java/docking/DockWinListener.java create mode 100644 Ghidra/Framework/Docking/src/main/java/docking/actions/PopupActionProvider.java delete mode 100644 Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/PopupListener.java diff --git a/Ghidra/Features/Base/.launch/Ghidra.launch b/Ghidra/Features/Base/.launch/Ghidra.launch index fdb4e215d2..ff35716420 100644 --- a/Ghidra/Features/Base/.launch/Ghidra.launch +++ b/Ghidra/Features/Base/.launch/Ghidra.launch @@ -24,5 +24,5 @@ - + diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/merge/tool/ListingMergePanelProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/merge/tool/ListingMergePanelProvider.java index b6c5d9a710..74ebc32519 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/merge/tool/ListingMergePanelProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/merge/tool/ListingMergePanelProvider.java @@ -1,6 +1,5 @@ /* ### * IP: GHIDRA - * REVIEWED: YES * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,8 +26,9 @@ import javax.swing.JComponent; import docking.ActionContext; import docking.WindowPosition; import docking.action.DockingActionIf; +import docking.actions.PopupActionProvider; -public class ListingMergePanelProvider extends ComponentProviderAdapter implements PopupListener { +public class ListingMergePanelProvider extends ComponentProviderAdapter implements PopupActionProvider { private ListingMergePanel mergePanel; public ListingMergePanelProvider(PluginTool tool, Plugin plugin, String owner, @@ -37,7 +37,7 @@ public class ListingMergePanelProvider extends ComponentProviderAdapter implemen setTitle("Listing Merge Tool"); setDefaultWindowPosition(WindowPosition.TOP); this.mergePanel = mergePanel; - tool.addPopupListener(this); + tool.addPopupActionProvider(this); } @Override diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/bookmark/BookmarkPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/bookmark/BookmarkPlugin.java index cf8ae6c1db..76a67d950b 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/bookmark/BookmarkPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/bookmark/BookmarkPlugin.java @@ -23,6 +23,7 @@ import javax.swing.SwingUtilities; import docking.ActionContext; import docking.action.*; +import docking.actions.PopupActionProvider; import docking.widgets.table.GTable; import ghidra.app.CorePluginPackage; import ghidra.app.events.ProgramSelectionPluginEvent; @@ -60,7 +61,7 @@ import resources.*; ) //@formatter:on public class BookmarkPlugin extends ProgramPlugin - implements DomainObjectListener, PopupListener, BookmarkService { + implements DomainObjectListener, PopupActionProvider, BookmarkService { private final static int MAX_DELETE_ACTIONS = 10; @@ -190,7 +191,7 @@ public class BookmarkPlugin extends ProgramPlugin public synchronized void dispose() { navUpdater.dispose(); - tool.removePopupListener(this); + tool.removePopupActionProvider(this); if (repaintMgr != null) { repaintMgr.dispose(); } @@ -227,7 +228,7 @@ public class BookmarkPlugin extends ProgramPlugin provider.setGoToService(goToService); markerService = tool.getService(MarkerService.class); - tool.addPopupListener(this); + tool.addPopupActionProvider(this); navUpdater = new NavUpdater(); repaintMgr = new SwingUpdateManager(500, () -> provider.repaint()); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/CodeViewerProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/CodeViewerProvider.java index a5f2651fa7..a5f7a7e067 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/CodeViewerProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/CodeViewerProvider.java @@ -29,6 +29,7 @@ import javax.swing.event.ChangeListener; import docking.*; import docking.action.*; +import docking.actions.PopupActionProvider; import docking.dnd.*; import docking.widgets.EventTrigger; import docking.widgets.fieldpanel.FieldPanel; @@ -57,7 +58,7 @@ import resources.ResourceManager; public class CodeViewerProvider extends NavigatableComponentProviderAdapter implements ProgramLocationListener, ProgramSelectionListener, Draggable, Droppable, - ChangeListener, StringSelectionListener, PopupListener { + ChangeListener, StringSelectionListener, PopupActionProvider { private static final String OLD_NAME = "CodeBrowserPlugin"; private static final String NAME = "Listing"; @@ -156,7 +157,7 @@ public class CodeViewerProvider extends NavigatableComponentProviderAdapter listingPanel.addIndexMapChangeListener(this); codeViewerClipboardProvider = new CodeBrowserClipboardProvider(tool, this); - tool.addPopupListener(this); + tool.addPopupActionProvider(this); } @Override diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypeManagerPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypeManagerPlugin.java index 2932a3e30b..a556b9f230 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypeManagerPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/datamgr/DataTypeManagerPlugin.java @@ -28,6 +28,7 @@ import javax.swing.tree.TreePath; import docking.ActionContext; import docking.action.*; +import docking.actions.PopupActionProvider; import docking.widgets.tree.GTreeNode; import generic.jar.ResourceFile; import generic.util.Path; @@ -78,7 +79,7 @@ import ghidra.util.task.TaskLauncher; ) //@formatter:on public class DataTypeManagerPlugin extends ProgramPlugin - implements DomainObjectListener, DataTypeManagerService, PopupListener { + implements DomainObjectListener, DataTypeManagerService, PopupActionProvider { private static final String SEACH_PROVIDER_NAME = "Search DataTypes Provider"; private static final int RECENTLY_USED_CACHE_SIZE = 10; @@ -158,7 +159,7 @@ public class DataTypeManagerPlugin extends ProgramPlugin if (codeViewerService != null) { codeViewerService.addProgramDropProvider(new DataDropOnBrowserHandler(this)); } - tool.addPopupListener(this); + tool.addPopupActionProvider(this); tool.setMenuGroup(new String[] { SyncRefreshAction.MENU_NAME }, "SYNC"); tool.setMenuGroup(new String[] { UpdateAction.MENU_NAME }, "SYNC"); tool.setMenuGroup(new String[] { CommitAction.MENU_NAME }, "SYNC"); @@ -263,7 +264,7 @@ public class DataTypeManagerPlugin extends ProgramPlugin @Override public void dispose() { - tool.removePopupListener(this); + tool.removePopupActionProvider(this); provider.dispose(); close(); dataTypeManagerHandler.dispose(); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/functioncompare/FunctionComparisonProvider.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/functioncompare/FunctionComparisonProvider.java index 883f334ae8..bbf677f241 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/functioncompare/FunctionComparisonProvider.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/functioncompare/FunctionComparisonProvider.java @@ -23,6 +23,7 @@ import javax.swing.Icon; import docking.ActionContext; import docking.action.DockingAction; import docking.action.DockingActionIf; +import docking.actions.PopupActionProvider; import docking.widgets.fieldpanel.internal.FieldPanelCoordinator; import ghidra.app.util.viewer.listingpanel.ListingCodeComparisonPanel; import ghidra.app.util.viewer.listingpanel.ListingPanel; @@ -37,7 +38,7 @@ import resources.ResourceManager; /** * This is the dockable provider that displays a FunctionComparisonPanel. */ -public class FunctionComparisonProvider extends ComponentProviderAdapter implements PopupListener { +public class FunctionComparisonProvider extends ComponentProviderAdapter implements PopupActionProvider { private static final String HELP_TOPIC = "FunctionComparison"; private static final Icon ICON = ResourceManager.loadImage("images/page_white_c.png"); @@ -120,7 +121,7 @@ public class FunctionComparisonProvider extends ComponentProviderAdapter impleme setTransient(); setTabText(functionComparisonPanel); addSpecificCodeComparisonActions(); - tool.addPopupListener(this); + tool.addPopupActionProvider(this); setHelpLocation(new HelpLocation(HELP_TOPIC, "Function Comparison")); } @@ -178,7 +179,7 @@ public class FunctionComparisonProvider extends ComponentProviderAdapter impleme @Override public void removeFromTool() { - tool.removePopupListener(this); + tool.removePopupActionProvider(this); super.removeFromTool(); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/ui/InstructionTable.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/ui/InstructionTable.java index 17adcbe1d3..9476016c80 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/ui/InstructionTable.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/ui/InstructionTable.java @@ -22,6 +22,7 @@ import java.util.List; import javax.swing.*; +import docking.ActionContext; import docking.DockingWindowManager; import docking.action.DockingActionIf; import docking.widgets.EmptyBorderButton; @@ -101,7 +102,7 @@ public class InstructionTable extends AbstractInstructionTable { * (which is all of them). */ @Override - public List getDockingActions() { + public List getPopupActions(ActionContext context) { return new ArrayList<>(); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/ui/PreviewTable.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/ui/PreviewTable.java index 85226e77ed..85cd1c61be 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/ui/PreviewTable.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/instructionsearch/ui/PreviewTable.java @@ -136,10 +136,10 @@ public class PreviewTable extends AbstractInstructionTable { * any existing menus; it simply adds to them. */ @Override - public List getDockingActions() { + public List getPopupActions(ActionContext context) { // Invoke the base class method to add default menu options. - List list = super.getDockingActions(); + List list = super.getPopupActions(context); // And now add our own. addCustomMenuItems(list); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/framework/main/OpenVersionedFileDialog.java b/Ghidra/Features/Base/src/main/java/ghidra/framework/main/OpenVersionedFileDialog.java index 5c87c12811..959a38d82f 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/framework/main/OpenVersionedFileDialog.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/framework/main/OpenVersionedFileDialog.java @@ -17,10 +17,14 @@ package ghidra.framework.main; import java.awt.BorderLayout; import java.awt.Dimension; +import java.awt.event.MouseEvent; import java.io.IOException; +import java.util.List; import javax.swing.*; +import docking.ActionContext; +import docking.action.DockingActionIf; import ghidra.framework.main.datatree.VersionHistoryPanel; import ghidra.framework.model.*; import ghidra.framework.plugintool.PluginTool; @@ -47,11 +51,13 @@ public class OpenVersionedFileDialog extends DataTreeDialog { private JSplitPane splitPane; private JButton historyButton; - private VersionHistoryPanel historyPanel; private JPanel mainPanel; private boolean historyIsShowing; private PluginTool tool; + private VersionHistoryPanel historyPanel; + private List popupActions; + /** * Constructor * @param tool tool where the file is being opened. @@ -178,13 +184,32 @@ public class OpenVersionedFileDialog extends DataTreeDialog { super.close(); } + @Override + protected void dialogShown() { + super.dialogShown(); + + for (DockingActionIf action : popupActions) { + addAction(action); + } + } + + @Override + protected void dialogClosed() { + super.dialogClosed(); + + for (DockingActionIf action : popupActions) { + removeAction(action); + } + } + private boolean createHistoryPanel() { try { historyPanel = new VersionHistoryPanel(tool, null); + popupActions = historyPanel.createPopupActions(); } catch (IOException ioe) { Msg.debug(getClass(), - "Error creating history panel for versioned file: " + ioe.getMessage()); + "Error creating history panel for versioned file: " + ioe.getMessage(), ioe); return false; } @@ -225,4 +250,17 @@ public class OpenVersionedFileDialog extends DataTreeDialog { } }); } + + @Override + public ActionContext getActionContext(MouseEvent event) { + ActionContext context = super.getActionContext(event); + if (context != null) { + return context; + } + + ActionContext actionContext = new ActionContext(null, event.getSource(), this); + actionContext.setMouseEvent(event); + + return actionContext; + } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/test/TestTool.java b/Ghidra/Features/Base/src/main/java/ghidra/test/TestTool.java index ceaf167763..0b5bdbc056 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/test/TestTool.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/test/TestTool.java @@ -32,7 +32,7 @@ public class TestTool extends GhidraTool { @Override protected DockingWindowManager createDockingWindowManager(boolean isDockable, boolean hasStatus, boolean isModal) { - return new DockingWindowManager(this, null, this, isModal, isDockable, hasStatus, null); + return new DockingWindowManager(this, null, isModal, isDockable, hasStatus, null); } @Override diff --git a/Ghidra/Features/Base/src/test.slow/java/docking/DockingWindowManagerTest.java b/Ghidra/Features/Base/src/test.slow/java/docking/DockingWindowManagerTest.java index e4b6ec6a77..d6899593ef 100644 --- a/Ghidra/Features/Base/src/test.slow/java/docking/DockingWindowManagerTest.java +++ b/Ghidra/Features/Base/src/test.slow/java/docking/DockingWindowManagerTest.java @@ -45,7 +45,7 @@ public class DockingWindowManagerTest extends AbstractDockingTest { // default window position. // - DockingWindowManager dwm = new DockingWindowManager(tool, (List) null, null); + DockingWindowManager dwm = new DockingWindowManager(tool, (List) null); ComponentProvider providerA = addProvider(dwm, "A", "a", RIGHT); ComponentProvider providerB = addProvider(dwm, "B", "b", BOTTOM); @@ -65,7 +65,7 @@ public class DockingWindowManagerTest extends AbstractDockingTest { // intragroup window position. Note: 'Stacked' is the default. // - DockingWindowManager dwm = new DockingWindowManager(tool, (List) null, null); + DockingWindowManager dwm = new DockingWindowManager(tool, (List) null); ComponentProvider providerA1 = addProvider(dwm, "A1", "a", RIGHT, STACK); ComponentProvider providerA2 = addProvider(dwm, "A2", "a", BOTTOM, STACK); @@ -83,7 +83,7 @@ public class DockingWindowManagerTest extends AbstractDockingTest { // intragroup window position. // - DockingWindowManager dwm = new DockingWindowManager(tool, (List) null, null); + DockingWindowManager dwm = new DockingWindowManager(tool, (List) null); ComponentProvider providerA1 = addProvider(dwm, "A1", "a", RIGHT, STACK); ComponentProvider providerA2 = addProvider(dwm, "A2", "a", LEFT, BOTTOM); @@ -100,7 +100,7 @@ public class DockingWindowManagerTest extends AbstractDockingTest { // intragroup window position. // - DockingWindowManager dwm = new DockingWindowManager(tool, (List) null, null); + DockingWindowManager dwm = new DockingWindowManager(tool, (List) null); ComponentProvider providerA1 = addProvider(dwm, "A1", "a", RIGHT, WINDOW); ComponentProvider providerA2 = addProvider(dwm, "A2", "a", LEFT, WINDOW); @@ -121,7 +121,7 @@ public class DockingWindowManagerTest extends AbstractDockingTest { // // note: the positions specified here are for default positions, not intragroup positions - DockingWindowManager dwm = new DockingWindowManager(tool, (List) null, null); + DockingWindowManager dwm = new DockingWindowManager(tool, (List) null); ComponentProvider providerA = addProvider(dwm, "A", "a", RIGHT, STACK); ComponentProvider providerAB = addProvider(dwm, "AB", "a.b", BOTTOM, STACK); @@ -142,7 +142,7 @@ public class DockingWindowManagerTest extends AbstractDockingTest { // // note: the positions specified here are for default positions, not intragroup positions - DockingWindowManager dwm = new DockingWindowManager(tool, (List) null, null); + DockingWindowManager dwm = new DockingWindowManager(tool, (List) null); ComponentProvider providerA = addProvider(dwm, "A", "a", RIGHT, BOTTOM); ComponentProvider providerAB = addProvider(dwm, "AB", "a.b", BOTTOM, TOP); @@ -180,7 +180,7 @@ public class DockingWindowManagerTest extends AbstractDockingTest { // Test that, for unrelated groups, the layout info stored in XML is re-used when providers // are shown after that XML is restored--even if the window positioning changes // - final DockingWindowManager dwm1 = new DockingWindowManager(tool, (List) null, null); + final DockingWindowManager dwm1 = new DockingWindowManager(tool, (List) null); ComponentProvider providerA = addProvider(dwm1, "A", "a", RIGHT); ComponentProvider providerB = addProvider(dwm1, "B", "b", BOTTOM); @@ -215,7 +215,7 @@ public class DockingWindowManagerTest extends AbstractDockingTest { // Test that, for related groups, the layout info stored in XML is re-used when providers // are shown after that XML is restored--even if the window positioning changes // - DockingWindowManager dwm1 = new DockingWindowManager(tool, (List) null, null); + DockingWindowManager dwm1 = new DockingWindowManager(tool, (List) null); ComponentProvider providerA = addProvider(dwm1, "A", "a", RIGHT); ComponentProvider providerAB = addProvider(dwm1, "AB", "a.b", BOTTOM); @@ -251,7 +251,7 @@ public class DockingWindowManagerTest extends AbstractDockingTest { // and that a subgroup 'a.b' will open relative to the parent. **Make sure that this // works when the parent is the first provider open. // - DockingWindowManager dwm = new DockingWindowManager(tool, (List) null, null); + DockingWindowManager dwm = new DockingWindowManager(tool, (List) null); ComponentProvider providerA = addProvider(dwm, "A", "a", TOP, RIGHT); ComponentProvider providerAB = addProvider(dwm, "AB", "a.b", RIGHT, BOTTOM); @@ -268,7 +268,7 @@ public class DockingWindowManagerTest extends AbstractDockingTest { // and that a subgroup 'a.b' will open relative to the parent. **Make sure that this // works when the subgroup is the first provider open. // - DockingWindowManager dwm = new DockingWindowManager(tool, (List) null, null); + DockingWindowManager dwm = new DockingWindowManager(tool, (List) null); ComponentProvider providerAB = addProvider(dwm, "AB", "a.b", RIGHT, BOTTOM); ComponentProvider providerA = addProvider(dwm, "A", "a", TOP, RIGHT); @@ -286,7 +286,7 @@ public class DockingWindowManagerTest extends AbstractDockingTest { // Test that two providers that don't share an owner (the plugin) can share a group and // open relative to each other. // - DockingWindowManager dwm = new DockingWindowManager(tool, (List) null, null); + DockingWindowManager dwm = new DockingWindowManager(tool, (List) null); ComponentProvider p1 = addProvider(dwm, "Owner_1", "Name_1", "group", TOP, TOP); ComponentProvider p2 = addProvider(dwm, "Owner_2", "Name_2", "group", BOTTOM, RIGHT); @@ -335,7 +335,7 @@ public class DockingWindowManagerTest extends AbstractDockingTest { */ - DockingWindowManager dwm = new DockingWindowManager(tool, (List) null, null); + DockingWindowManager dwm = new DockingWindowManager(tool, (List) null); ComponentProvider pA = addProvider(dwm, "Owner_1", "A", "a", LEFT, LEFT); ComponentProvider pB = addProvider(dwm, "Owner_2", "B", "b", RIGHT, RIGHT); @@ -408,7 +408,7 @@ public class DockingWindowManagerTest extends AbstractDockingTest { private DockingWindowManager createNewDockingWindowManagerFromXML(final Element element) { final DockingWindowManager dwm2 = - new DockingWindowManager(new DummyTool("Tool2"), (List) null, null); + new DockingWindowManager(new DummyTool("Tool2"), (List) null); runSwing(() -> { dwm2.setVisible(true); diff --git a/Ghidra/Features/Base/src/test.slow/java/docking/widgets/dialogs/NumberInputDialogTest.java b/Ghidra/Features/Base/src/test.slow/java/docking/widgets/dialogs/NumberInputDialogTest.java index 2a4d54d64e..bb5b2cbc7d 100644 --- a/Ghidra/Features/Base/src/test.slow/java/docking/widgets/dialogs/NumberInputDialogTest.java +++ b/Ghidra/Features/Base/src/test.slow/java/docking/widgets/dialogs/NumberInputDialogTest.java @@ -35,7 +35,7 @@ import ghidra.test.DummyTool; public class NumberInputDialogTest extends AbstractDockingTest { private DockingWindowManager dwm = - new DockingWindowManager(new DummyTool(), (List) null, null); + new DockingWindowManager(new DummyTool(), (List) null); private NumberInputDialog dialog; private JButton okButton; private JTextField textField; diff --git a/Ghidra/Features/Base/src/test.slow/java/docking/widgets/table/GhidraTableFilterTest.java b/Ghidra/Features/Base/src/test.slow/java/docking/widgets/table/GhidraTableFilterTest.java index 0d5d589179..0e11988bbc 100644 --- a/Ghidra/Features/Base/src/test.slow/java/docking/widgets/table/GhidraTableFilterTest.java +++ b/Ghidra/Features/Base/src/test.slow/java/docking/widgets/table/GhidraTableFilterTest.java @@ -51,7 +51,7 @@ public class GhidraTableFilterTest extends AbstractGhidraHeadedIntegrationTest { filteredModel = filterPanel.getTableFilterModel(); table.setAutoLookupColumn(4); - winMgr = new DockingWindowManager(new DummyTool(), null, null); + winMgr = new DockingWindowManager(new DummyTool(), null); winMgr.addComponent(new TestTableComponentProvider()); winMgr.setVisible(true); } diff --git a/Ghidra/Features/Base/src/test/java/ghidra/test/DummyTool.java b/Ghidra/Features/Base/src/test/java/ghidra/test/DummyTool.java index 3f01e155f2..e76bfb7fed 100644 --- a/Ghidra/Features/Base/src/test/java/ghidra/test/DummyTool.java +++ b/Ghidra/Features/Base/src/test/java/ghidra/test/DummyTool.java @@ -29,6 +29,7 @@ import org.jdom.Element; import docking.*; import docking.action.DockingActionIf; import docking.actions.DockingToolActions; +import docking.actions.PopupActionProvider; import ghidra.framework.model.*; import ghidra.framework.options.ToolOptions; import ghidra.framework.plugintool.PluginEvent; @@ -298,6 +299,16 @@ public class DummyTool implements Tool { //do nothing } + @Override + public void addPopupActionProvider(PopupActionProvider listener) { + // do nothing + } + + @Override + public void removePopupActionProvider(PopupActionProvider listener) { + // do nothing + } + @Override public Set getAllActions() { return Collections.emptySet(); diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/functionassociation/VTFunctionAssociationProvider.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/functionassociation/VTFunctionAssociationProvider.java index 2e9c934347..81454e1bf1 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/functionassociation/VTFunctionAssociationProvider.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/functionassociation/VTFunctionAssociationProvider.java @@ -31,6 +31,7 @@ import javax.swing.table.JTableHeader; import docking.ActionContext; import docking.WindowPosition; import docking.action.*; +import docking.actions.PopupActionProvider; import docking.menu.ActionState; import docking.menu.MultiStateDockingAction; import docking.widgets.EventTrigger; @@ -52,7 +53,6 @@ import ghidra.framework.model.*; import ghidra.framework.options.Options; import ghidra.framework.options.SaveState; import ghidra.framework.plugintool.ComponentProviderAdapter; -import ghidra.framework.plugintool.PopupListener; import ghidra.program.model.address.Address; import ghidra.program.model.listing.Function; import ghidra.program.model.listing.Program; @@ -67,7 +67,7 @@ import resources.ResourceManager; * Provider for the version tracking function association table. */ public class VTFunctionAssociationProvider extends ComponentProviderAdapter - implements VTControllerListener, PopupListener { + implements VTControllerListener, PopupActionProvider { private static final String FILTER_SETTINGS_KEY = "FUNCTION_FILTER_SETTINGS"; private static final String BASE_TITLE = "Version Tracking Functions"; @@ -125,7 +125,7 @@ public class VTFunctionAssociationProvider extends ComponentProviderAdapter createActions(); addGeneralCodeComparisonActions(); controller.addListener(this); - tool.addPopupListener(this); + tool.addPopupActionProvider(this); } private void createActions() { @@ -334,7 +334,7 @@ public class VTFunctionAssociationProvider extends ComponentProviderAdapter destinationFunctionsTable.dispose(); destinationTableFilterPanel.dispose(); - tool.removePopupListener(this); + tool.removePopupActionProvider(this); } public void reload() { diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/markuptable/VTMarkupItemsTableProvider.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/markuptable/VTMarkupItemsTableProvider.java index 78f7d6a7d5..fdc7939a91 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/markuptable/VTMarkupItemsTableProvider.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/gui/provider/markuptable/VTMarkupItemsTableProvider.java @@ -30,6 +30,7 @@ import javax.swing.table.*; import docking.*; import docking.action.*; +import docking.actions.PopupActionProvider; import docking.help.HelpService; import docking.widgets.EventTrigger; import docking.widgets.fieldpanel.FieldPanel; @@ -56,7 +57,6 @@ import ghidra.framework.model.DomainObjectChangedEvent; import ghidra.framework.options.Options; import ghidra.framework.options.SaveState; import ghidra.framework.plugintool.ComponentProviderAdapter; -import ghidra.framework.plugintool.PopupListener; import ghidra.program.model.address.*; import ghidra.program.model.listing.*; import ghidra.program.util.ProgramLocation; @@ -69,7 +69,7 @@ import resources.ResourceManager; * This provides the GUI for displaying and working with version tracking markup items. */ public class VTMarkupItemsTableProvider extends ComponentProviderAdapter - implements FilterDialogModel, VTControllerListener, PopupListener { + implements FilterDialogModel, VTControllerListener, PopupActionProvider { private static final String SHOW_COMPARISON_PANEL = "SHOW_COMPARISON_PANEL"; @@ -133,7 +133,7 @@ public class VTMarkupItemsTableProvider extends ComponentProviderAdapter iconTimer = new FilterIconFlashTimer<>(UNFILTERED_ICON, FILTERED_ICON, ancillaryFilterDialog, ancillaryFilterButton); - tool.addPopupListener(this); + tool.addPopupActionProvider(this); HelpLocation helpLocation = new HelpLocation("VersionTrackingPlugin", "Markup Items Table"); setHelpLocation(helpLocation); @@ -534,7 +534,7 @@ public class VTMarkupItemsTableProvider extends ComponentProviderAdapter filter.dispose(); } - tool.removePopupListener(this); + tool.removePopupActionProvider(this); } VTController getController() { diff --git a/Ghidra/Framework/Docking/src/main/java/docking/AbstractDockingTool.java b/Ghidra/Framework/Docking/src/main/java/docking/AbstractDockingTool.java index 893ad0be06..0c181c0a42 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/AbstractDockingTool.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/AbstractDockingTool.java @@ -21,6 +21,7 @@ import java.util.*; import javax.swing.JFrame; import docking.action.DockingActionIf; +import docking.actions.PopupActionProvider; import docking.actions.ToolActions; import ghidra.framework.options.ToolOptions; import ghidra.util.Swing; @@ -123,6 +124,16 @@ public abstract class AbstractDockingTool implements DockingTool { return toolActions.getAllActions(); } + @Override + public void addPopupActionProvider(PopupActionProvider provider) { + winMgr.addPopupActionProvider(provider); + } + + @Override + public void removePopupActionProvider(PopupActionProvider provider) { + winMgr.removePopupActionProvider(provider); + } + @Override public Set getDockingActionsByOwnerName(String owner) { return toolActions.getActions(owner); diff --git a/Ghidra/Framework/Docking/src/main/java/docking/ComponentLoadedListener.java b/Ghidra/Framework/Docking/src/main/java/docking/ComponentLoadedListener.java index 503c2c1ade..843a36eae4 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/ComponentLoadedListener.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/ComponentLoadedListener.java @@ -1,6 +1,5 @@ /* ### * IP: GHIDRA - * REVIEWED: YES * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,7 +15,12 @@ */ package docking; +import java.awt.Component; +/** + * A listener interface to know when a component has been + * made {@link Component#isDisplayable() displayable} + */ public interface ComponentLoadedListener { public void componentLoaded(DockingWindowManager windowManager); } diff --git a/Ghidra/Framework/Docking/src/main/java/docking/DialogComponentProvider.java b/Ghidra/Framework/Docking/src/main/java/docking/DialogComponentProvider.java index b9f35aa436..e8629339b4 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/DialogComponentProvider.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/DialogComponentProvider.java @@ -32,7 +32,7 @@ import docking.actions.ActionAdapter; import docking.actions.KeyBindingUtils; import docking.event.mouse.GMouseListenerAdapter; import docking.menu.DockingToolbarButton; -import docking.util.*; +import docking.util.AnimationUtils; import docking.widgets.label.GDHtmlLabel; import ghidra.util.*; import ghidra.util.exception.AssertException; @@ -43,9 +43,8 @@ import utility.function.Callback; * Base class used for creating dialogs in Ghidra. Subclass this to create a dialog provider that has * all the gui elements to appear in the dialog, then use tool.showDialog() to display your dialog. */ - public class DialogComponentProvider - implements TaskListener, StatusListener, ActionContextProvider { + implements ActionContextProvider, StatusListener, TaskListener { private static final Color WARNING_COLOR = new Color(0xff9900); @@ -1369,5 +1368,4 @@ public class DialogComponentProvider } } - } diff --git a/Ghidra/Framework/Docking/src/main/java/docking/DialogComponentProviderPopupActionManager.java b/Ghidra/Framework/Docking/src/main/java/docking/DialogComponentProviderPopupActionManager.java index 060f05c814..1fe5f87119 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/DialogComponentProviderPopupActionManager.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/DialogComponentProviderPopupActionManager.java @@ -73,7 +73,7 @@ public class DialogComponentProviderPopupActionManager { MenuGroupMap menuGroupMap = actionManager.getMenuGroupMap(); MenuManager menuMgr = new MenuManager("Popup", '\0', null, true, popupMenuHandler, menuGroupMap); - populatePopupMenuActions(actionContext, menuMgr); + populatePopupMenuActions(dwm, menuMgr, actionContext); if (menuMgr.isEmpty()) { return; } @@ -85,7 +85,8 @@ public class DialogComponentProviderPopupActionManager { popupMenu.show(c, e.getX(), e.getY()); } - private void populatePopupMenuActions(ActionContext actionContext, MenuManager menuMgr) { + private void populatePopupMenuActions(DockingWindowManager dwm, MenuManager menuMgr, + ActionContext actionContext) { Iterator iter = popupActions.iterator(); while (iter.hasNext()) { @@ -112,6 +113,18 @@ public class DialogComponentProviderPopupActionManager { } } } + + List tempActions = dwm.getTemporaryPopupActions(actionContext); + if (tempActions != null) { + for (DockingActionIf action : tempActions) { + MenuData popupMenuData = action.getPopupMenuData(); + if (popupMenuData != null && action.isValidContext(actionContext) && + action.isAddToPopup(actionContext)) { + action.setEnabled(action.isEnabledForContext(actionContext)); + menuMgr.addAction(action); + } + } + } } //================================================================================================== diff --git a/Ghidra/Framework/Docking/src/main/java/docking/DockWinListener.java b/Ghidra/Framework/Docking/src/main/java/docking/DockWinListener.java deleted file mode 100644 index 0d83231395..0000000000 --- a/Ghidra/Framework/Docking/src/main/java/docking/DockWinListener.java +++ /dev/null @@ -1,44 +0,0 @@ -/* ### - * IP: GHIDRA - * REVIEWED: YES - * - * 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. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package docking; - -import java.util.List; - -import docking.action.DockingActionIf; - -/** - * Listener interface for the object to be notified when the user closes the - * docking windows manager or initiates a popup menu. - */ -public interface DockWinListener { - /** - * Notification triggered when the user presses the "x" button in the main tool frame. - * Typical reaction is to dispose the dockingWindowManger and/or exit. - */ - void close(); - - /** - * Provides notification when a popup menu is about to be displayed - * and permits a list of temporary actions to be returned. Only - * those actions which have a suitable popup menu path will be - * considered. - * @param context the ActionContext - * @return list of temporary actions. - */ - List getPopupActions(ActionContext context); - -} diff --git a/Ghidra/Framework/Docking/src/main/java/docking/DockingTool.java b/Ghidra/Framework/Docking/src/main/java/docking/DockingTool.java index 2116bd64b7..21f388bc6a 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/DockingTool.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/DockingTool.java @@ -22,6 +22,7 @@ import javax.swing.ImageIcon; import docking.action.DockingActionIf; import docking.actions.DockingToolActions; +import docking.actions.PopupActionProvider; import ghidra.framework.options.ToolOptions; /** @@ -129,6 +130,19 @@ public interface DockingTool { */ public void removeLocalAction(ComponentProvider componentProvider, DockingActionIf action); + /** + * Adds the given popup action provider to this tool. This provider will be called each + * time the popup menu is about to be shown. + * @param provider the provider + */ + public void addPopupActionProvider(PopupActionProvider provider); + + /** + * Removes the given popup action provider + * @param provider the provider + */ + public void removePopupActionProvider(PopupActionProvider provider); + /** * Return a set of all actions in the tool. * @@ -273,4 +287,12 @@ public interface DockingTool { * @return the action manager */ public DockingToolActions getToolActions(); + + /** + * Suggests the tool to attempt to close(). This will be as though the user + * selected the close menu option on the tool or hit the closeWindow x button in + * the upper corner (Windows systems). + */ + public void close(); + } diff --git a/Ghidra/Framework/Docking/src/main/java/docking/DockingWindowManager.java b/Ghidra/Framework/Docking/src/main/java/docking/DockingWindowManager.java index 6beb26bf9d..a00a789feb 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/DockingWindowManager.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/DockingWindowManager.java @@ -30,8 +30,7 @@ import org.apache.commons.collections4.map.LazyMap; import org.jdom.Element; import docking.action.DockingActionIf; -import docking.actions.DockingToolActions; -import docking.actions.ToolActions; +import docking.actions.*; import docking.help.HelpService; import generic.util.WindowUtilities; import ghidra.framework.OperatingSystem; @@ -87,9 +86,10 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder private Map providerNameCache = new HashMap<>(); private Map preferenceStateMap = new HashMap<>(); - private DockWinListener docListener; private ActionToGuiMapper actionToGuiMapper; + private WeakSet popupActionProviders = + WeakDataStructureFactory.createSingleThreadAccessWeakSet(); private WeakSet contextListeners = WeakDataStructureFactory.createSingleThreadAccessWeakSet(); @@ -108,10 +108,9 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder * Constructs a new DockingWindowManager * @param tool the tool * @param images the images to use for windows in this window manager - * @param docListener the listener to be notified when the user closes the manager */ - public DockingWindowManager(DockingTool tool, List images, DockWinListener docListener) { - this(tool, images, docListener, false, true, true, null); + public DockingWindowManager(DockingTool tool, List images) { + this(tool, images, false, true, true, null); } /** @@ -119,20 +118,18 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder * * @param tool the tool * @param images the list of icons to set on the window - * @param docListener the listener to be notified when the user closes the manager * @param modal if true then the root window will be a modal dialog instead of a frame * @param isDocking true for normal operation, false to suppress docking support(removes * component headers and window menu) * @param hasStatusBar if true a status bar will be created for the main window * @param factory the drop target factory */ - public DockingWindowManager(DockingTool tool, List images, DockWinListener docListener, - boolean modal, boolean isDocking, boolean hasStatusBar, DropTargetFactory factory) { + public DockingWindowManager(DockingTool tool, List images, boolean modal, + boolean isDocking, boolean hasStatusBar, DropTargetFactory factory) { KeyBindingOverrideKeyEventDispatcher.install(); this.tool = tool; - this.docListener = docListener; this.isDocking = isDocking; this.hasStatusBar = hasStatusBar; if (images == null) { @@ -174,10 +171,6 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder return helpService; } - List getTemporaryPopupActions(ActionContext context) { - return docListener.getPopupActions(context); - } - private static synchronized void addInstance(DockingWindowManager winMgr) { instanceList.add(winMgr); } @@ -1084,7 +1077,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder * the main window frame. */ void close() { - docListener.close(); + tool.close(); } boolean isDocking() { @@ -2099,6 +2092,44 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder actionToGuiMapper.contextChanged(placeholder); } + /** + * Adds the given popup action provider to this tool. This provider will be called each + * time the popup menu is about to be shown. + * @param provider the provider + */ + public void addPopupActionProvider(PopupActionProvider provider) { + popupActionProviders.add(provider); + } + + /** + * Removes the given popup action provider + * @param provider the provider + */ + public void removePopupActionProvider(PopupActionProvider provider) { + popupActionProviders.remove(provider); + } + + /** + * Returns a list of temporary popup actions to be returned. Only those actions which have + * a suitable popup menu path will be considered. This mechanism allows clients to + * add transient actions to be added to the tool without the accompanying management overhead. + * + * @param context the ActionContext + * @return list of temporary actions + * @see #addPopupActionProvider(PopupActionProvider) + */ + List getTemporaryPopupActions(ActionContext context) { + + List actionList = new ArrayList<>(); + for (PopupActionProvider pl : popupActionProviders) { + List actions = pl.getPopupActions(context); + if (actions != null) { + actionList.addAll(actions); + } + } + return actionList; + } + public void addContextListener(DockingContextListener listener) { contextListeners.add(listener); } @@ -2122,12 +2153,9 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder * @param component the component that will be parented in a docking window system. * @param listener the listener to be notified the component was parented. */ - public static void registerComponentLoadedListener(final Component component, - final ComponentLoadedListener listener) { + public static void registerComponentLoadedListener(Component component, + ComponentLoadedListener listener) { - // We want to load our state after the column model is loaded. We are using this - // listener to know when the table has been added to the component hierarchy, as its - // model has been loaded by then. component.addHierarchyListener(new HierarchyListener() { @Override public void hierarchyChanged(HierarchyEvent e) { diff --git a/Ghidra/Framework/Docking/src/main/java/docking/action/DockingActionProviderIf.java b/Ghidra/Framework/Docking/src/main/java/docking/action/DockingActionProviderIf.java index 176987d272..2aff5ffbcc 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/action/DockingActionProviderIf.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/action/DockingActionProviderIf.java @@ -17,6 +17,8 @@ package docking.action; import java.util.List; +import docking.DockingTool; + /** * An interface for objects (really Components) to implement that signals they provide actions * for the Docking environment. This interface will be called when the implementor is the source @@ -25,8 +27,12 @@ import java.util.List; * As an example, a JTable that wishes to provide popup menu actions can implement this interface. * When the user right-clicks on said table, then Docking system will ask this object for its * actions. Further, in this example, the actions given will be inserted into the popup menu - * that is shown. + * that is shown. + * + * @deprecated use {@link DockingTool} */ +// Note: this API is not likely used by forward-facing clients and can be removed in the next release +@Deprecated(since = "9.1", forRemoval = true) public interface DockingActionProviderIf { /** diff --git a/Ghidra/Framework/Docking/src/main/java/docking/actions/PopupActionProvider.java b/Ghidra/Framework/Docking/src/main/java/docking/actions/PopupActionProvider.java new file mode 100644 index 0000000000..3f1b6c9edc --- /dev/null +++ b/Ghidra/Framework/Docking/src/main/java/docking/actions/PopupActionProvider.java @@ -0,0 +1,47 @@ +/* ### + * IP: GHIDRA + * + * 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. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package docking.actions; + +import java.util.List; + +import docking.ActionContext; +import docking.DockingTool; +import docking.action.DockingActionIf; + +/** + * Provides notification when the popup action menu is displayed. This interface allows + * temporary/transient actions (those not registered with the tool via + * {@link DockingTool#addAction(DockingActionIf)}) to be used in the popup context menu. + * + *

+ * Most clients will register actions directly with the tool. However, clients that have numerous + * actions that vary greatly with the context can use this method to only create those actions + * on demand as the popup is about to be shown, and only if their context is active. This + * mechanism can reduce the tool's action management overhead. + */ +public interface PopupActionProvider { + + /** + * Provides notification that the popup menu is about to be displayed and allows a set of + * temporary actions to be included in the popup menu. Actions returned will be + * included in the menu if they have a valid popup menu path and respond true to the + * {@link DockingActionIf#isValidContext(ActionContext)} call. + * + * @param context the ActionContext + * @return list of temporary popup actions; return null if there are no popup actions + */ + public List getPopupActions(ActionContext context); +} diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/GTable.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/GTable.java index 58e884d7a8..1a2de7d1c5 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/GTable.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/GTable.java @@ -32,6 +32,7 @@ import javax.swing.table.*; import docking.*; import docking.action.*; import docking.actions.KeyBindingUtils; +import docking.actions.PopupActionProvider; import docking.widgets.OptionDialog; import docking.widgets.dialogs.SettingsDialog; import docking.widgets.filechooser.GhidraFileChooser; @@ -69,7 +70,7 @@ import resources.ResourceManager; * * @see GTableFilterPanel */ -public class GTable extends JTable implements KeyStrokeConsumer, DockingActionProviderIf { +public class GTable extends JTable implements KeyStrokeConsumer, PopupActionProvider { private static final String LAST_EXPORT_FILE = "LAST_EXPORT_DIR"; @@ -510,20 +511,8 @@ public class GTable extends JTable implements KeyStrokeConsumer, DockingActionPr } @Override - public List getDockingActions() { - return getDefaultDockingActions(); - } + public List getPopupActions(ActionContext context) { - /** - * Returns the default actions of this table. Normally, the Docking Windows systems uses - * {@link #getDockingActions()} to get the correct actions to show. However, - * there are some cases where clients override what appears when you click on a table (such - * as in {@link DialogComponentProvider}s. For those clients that are creating their own - * action building, they need a way to get the default actions, hence this method. - * - * @return the default actions - */ - public List getDefaultDockingActions() { // we want these top-level groups to all appear together, with no separator DockingWindowManager dwm = DockingWindowManager.getInstance(this); dwm.setMenuGroup(new String[] { "Copy" }, actionMenuGroup, "1"); @@ -590,6 +579,10 @@ public class GTable extends JTable implements KeyStrokeConsumer, DockingActionPr createPopupActions(); initializeRowHeight(); + + DockingWindowManager.registerComponentLoadedListener(this, dwm -> { + dwm.getTool().addPopupActionProvider(this); + }); } private void initializeHeader(JTableHeader header) { @@ -1490,5 +1483,4 @@ public class GTable extends JTable implements KeyStrokeConsumer, DockingActionPr // ignored } } - } diff --git a/Ghidra/Framework/Docking/src/test/java/docking/FakeDockingTool.java b/Ghidra/Framework/Docking/src/test/java/docking/FakeDockingTool.java index bbbba7ab68..2696dbccaa 100644 --- a/Ghidra/Framework/Docking/src/test/java/docking/FakeDockingTool.java +++ b/Ghidra/Framework/Docking/src/test/java/docking/FakeDockingTool.java @@ -20,7 +20,6 @@ import java.util.List; import javax.swing.ImageIcon; -import docking.action.DockingActionIf; import docking.actions.ToolActions; import docking.framework.ApplicationInformationDisplayFactory; import ghidra.framework.options.ToolOptions; @@ -33,10 +32,9 @@ public class FakeDockingTool extends AbstractDockingTool { public FakeDockingTool() { - DockWinListener listener = new DummyListener(); List windowIcons = ApplicationInformationDisplayFactory.getWindowIcons(); - winMgr = new DockingWindowManager(this, windowIcons, listener, false /*isModal*/, - true /*isDockable*/, true /*hasStatus*/, null /*DropTargetFactory*/); + winMgr = new DockingWindowManager(this, windowIcons, false /*isModal*/, true /*isDockable*/, + true /*hasStatus*/, null /*DropTargetFactory*/); toolActions = new ToolActions(this, new ActionToGuiHelper(winMgr)); } @@ -60,16 +58,8 @@ public class FakeDockingTool extends AbstractDockingTool { return opt; } - private class DummyListener implements DockWinListener { - - @Override - public void close() { - // stub - } - - @Override - public List getPopupActions(ActionContext context) { - return null; - } + @Override + public void close() { + // stub } } diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/app/util/GenericHelpTopics.java b/Ghidra/Framework/Project/src/main/java/ghidra/app/util/GenericHelpTopics.java index 579fc9a760..2286853585 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/app/util/GenericHelpTopics.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/app/util/GenericHelpTopics.java @@ -44,6 +44,11 @@ public class GenericHelpTopics { */ public final static String REPOSITORY = "Repository"; + /** + * Help Topic for the version control. + */ + public final static String VERSION_CONTROL = "VersionControl"; + /** * Help Topic for tools. */ diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatable/ProjectDataTablePanel.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatable/ProjectDataTablePanel.java index d3fe4da3e8..bf265fbe23 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatable/ProjectDataTablePanel.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatable/ProjectDataTablePanel.java @@ -490,7 +490,7 @@ public class ProjectDataTablePanel extends JPanel { } @Override - public List getDockingActions() { + public List getPopupActions(ActionContext context) { // TODO we should at least add the 'copy' action diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/VersionHistoryDialog.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/VersionHistoryDialog.java index 6272482da1..4dbcdfe0db 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/VersionHistoryDialog.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/VersionHistoryDialog.java @@ -23,7 +23,6 @@ import javax.swing.SwingUtilities; import docking.ActionContext; import docking.DialogComponentProvider; import docking.action.DockingActionIf; -import docking.action.DockingActionProviderIf; import ghidra.app.util.GenericHelpTopics; import ghidra.framework.main.AppInfo; import ghidra.framework.main.FrontEndTool; @@ -31,24 +30,26 @@ import ghidra.framework.model.*; import ghidra.framework.store.FileSystem; import ghidra.util.HelpLocation; -public class VersionHistoryDialog extends DialogComponentProvider - implements ProjectListener, DockingActionProviderIf { +public class VersionHistoryDialog extends DialogComponentProvider implements ProjectListener { private VersionHistoryPanel versionPanel; private MyFolderListener listener = new MyFolderListener(); + private List popupActions; - public VersionHistoryDialog() { + public VersionHistoryDialog(DomainFile domainFile) { super("Version History", false); FrontEndTool frontEndTool = AppInfo.getFrontEndTool(); - setHelpLocation(new HelpLocation(GenericHelpTopics.REPOSITORY, "Show_History")); - versionPanel = new VersionHistoryPanel(frontEndTool, null, true); + setHelpLocation(new HelpLocation(GenericHelpTopics.VERSION_CONTROL, "Show_History")); + versionPanel = new VersionHistoryPanel(frontEndTool, domainFile, true); addWorkPanel(versionPanel); addDismissButton(); - versionPanel.addPopupActions(this); + + setDomainFile(domainFile); + popupActions = versionPanel.createPopupActions(); } - public void setDomainFile(DomainFile df) { + private void setDomainFile(DomainFile df) { versionPanel.setDomainFile(df); @@ -59,18 +60,24 @@ public class VersionHistoryDialog extends DialogComponentProvider setTitle("Version History for " + df.getName()); project.getProjectData().addDomainFolderChangeListener(listener); } - else { - setTitle("Version History"); - project.getProjectData().removeDomainFolderChangeListener(listener); + } + + @Override + protected void dialogShown() { + super.dialogShown(); + + for (DockingActionIf action : popupActions) { + addAction(action); } } @Override - protected void dismissCallback() { + protected void dialogClosed() { + super.dialogClosed(); - close(); - - setDomainFile(null); + for (DockingActionIf action : popupActions) { + removeAction(action); + } } @Override @@ -127,13 +134,8 @@ public class VersionHistoryDialog extends DialogComponentProvider @Override public ActionContext getActionContext(MouseEvent event) { - ActionContext actionContext = new ActionContext(null, this, this); + ActionContext actionContext = new ActionContext(null, versionPanel.getTable(), this); actionContext.setMouseEvent(event); return actionContext; } - - @Override - public List getDockingActions() { - return versionPanel.getDockingActions(); - } } diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/VersionHistoryPanel.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/VersionHistoryPanel.java index ffb621583b..91328086e4 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/VersionHistoryPanel.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatree/VersionHistoryPanel.java @@ -31,26 +31,29 @@ import javax.swing.event.ListSelectionListener; import javax.swing.table.TableColumn; import javax.swing.table.TableColumnModel; -import docking.*; +import docking.ActionContext; import docking.action.*; import docking.dnd.*; import docking.widgets.OptionDialog; import docking.widgets.table.*; +import ghidra.app.util.GenericHelpTopics; import ghidra.framework.client.ClientUtil; import ghidra.framework.main.GetVersionedObjectTask; import ghidra.framework.model.*; import ghidra.framework.plugintool.PluginTool; import ghidra.framework.store.ItemCheckoutStatus; import ghidra.framework.store.Version; -import ghidra.util.HTMLUtilities; -import ghidra.util.Msg; +import ghidra.util.*; import ghidra.util.task.*; /** - * Panel that shows version history in a JTable. + * Panel that shows version history in a JTable */ public class VersionHistoryPanel extends JPanel implements Draggable { + private static final HelpLocation HELP = + new HelpLocation(GenericHelpTopics.VERSION_CONTROL, "Show History"); + private PluginTool tool; private DomainFile domainFile; private String domainFilePath; @@ -79,7 +82,6 @@ public class VersionHistoryPanel extends JPanel implements Draggable { * @param tool tool * @param domainFile domain file * @param enableUserInteraction if true Draggable support will be enabled - * @throws IOException */ VersionHistoryPanel(PluginTool tool, DomainFile domainFile, boolean enableUserInteraction) { super(new BorderLayout()); @@ -94,11 +96,11 @@ public class VersionHistoryPanel extends JPanel implements Draggable { } /** - * Set the domain file to show its history. + * Set the domain file to show its history + * @param domainFile the file */ public void setDomainFile(DomainFile domainFile) { this.domainFile = domainFile; - domainFilePath = null; if (domainFile != null) { this.domainFilePath = domainFile.getPathname(); } @@ -122,21 +124,25 @@ public class VersionHistoryPanel extends JPanel implements Draggable { } /** - * Add the list selection listener to the history table. + * Add the list selection listener to the history table + * @param selectionListener the listener */ - public void addListSelectionListener(ListSelectionListener listener1) { - table.getSelectionModel().addListSelectionListener(listener1); + public void addListSelectionListener(ListSelectionListener selectionListener) { + table.getSelectionModel().addListSelectionListener(selectionListener); } /** * Remove the list selection listener from history table. + * @param selectionListener the listener */ - public void removeListSelectionListener(ListSelectionListener listener1) { - table.getSelectionModel().removeListSelectionListener(listener1); + public void removeListSelectionListener(ListSelectionListener selectionListener) { + table.getSelectionModel().removeListSelectionListener(selectionListener); } /** * Get the domain object for the selected version. + * @param consumer the consumer + * @param readOnly true if read only * @return null if there is no selection */ public DomainObject getSelectedVersion(Object consumer, boolean readOnly) { @@ -148,16 +154,10 @@ public class VersionHistoryPanel extends JPanel implements Draggable { return null; } - /** - * Return whether a version is selected. - */ public boolean isVersionSelected() { return !table.getSelectionModel().isSelectionEmpty(); } - /** - * Get the version number that was selected. - */ public int getSelectedVersionNumber() { int row = table.getSelectedRow(); if (row >= 0) { @@ -167,33 +167,21 @@ public class VersionHistoryPanel extends JPanel implements Draggable { return -1; } - /* (non-Javadoc) - * @see ghidra.util.bean.dnd.Draggable#dragCanceled() - */ @Override public void dragCanceled(DragSourceDropEvent event) { // no-op } - /* (non-Javadoc) - * @see ghidra.util.bean.dnd.Draggable#getDragAction() - */ @Override public int getDragAction() { return dragAction; } - /* (non-Javadoc) - * @see ghidra.util.bean.dnd.Draggable#getDragSourceListener() - */ @Override public DragSourceListener getDragSourceListener() { return dragSourceAdapter; } - /* (non-Javadoc) - * @see ghidra.util.bean.dnd.Draggable#getTransferable(java.awt.Point) - */ @Override public Transferable getTransferable(Point p) { int row = table.rowAtPoint(p); @@ -204,9 +192,6 @@ public class VersionHistoryPanel extends JPanel implements Draggable { return null; } - /* (non-Javadoc) - * @see ghidra.util.bean.dnd.Draggable#isStartDragOk(java.awt.dnd.DragGestureEvent) - */ @Override public boolean isStartDragOk(DragGestureEvent e) { int row = table.rowAtPoint(e.getDragOrigin()); @@ -216,9 +201,6 @@ public class VersionHistoryPanel extends JPanel implements Draggable { return false; } - /* (non-Javadoc) - * @see ghidra.util.bean.dnd.Draggable#move() - */ @Override public void move() { // no-op @@ -363,6 +345,38 @@ public class VersionHistoryPanel extends JPanel implements Draggable { openWith(null); } + public List createPopupActions() { + + List list = new ArrayList<>(); + list.add(new DeleteAction()); + + Project project = tool.getProject(); + ToolChest toolChest = project.getLocalToolChest(); + if (toolChest == null) { + return list; + } + + ToolTemplate[] templates = toolChest.getToolTemplates(); + if (templates.length == 0) { + return list; + } + + list.add(new OpenDefaultAction()); + for (ToolTemplate toolTemplate : templates) { + list.add(new OpenWithAction(toolTemplate.getName())); + } + + return list; + } + + GTable getTable() { + return table; + } + +//================================================================================================== +// Inner Classes +//================================================================================================== + private class MyCellRenderer extends GTableCellRenderer { @Override @@ -398,36 +412,11 @@ public class VersionHistoryPanel extends JPanel implements Draggable { } - public void addPopupActions(DialogComponentProvider provider) { - provider.addAction(new DeleteAction()); - } - - public List getDockingActions() { - List list = new ArrayList<>(table.getDefaultDockingActions()); - Project project = tool.getProject(); - ToolChest toolChest = project.getLocalToolChest(); - if (toolChest == null) { - return list; - } - - ToolTemplate[] templates = toolChest.getToolTemplates(); - if (templates.length == 0) { - return list; - } - - ToolTemplate defaultConfig = tool.getToolServices().getDefaultToolTemplate(domainFile); - if (defaultConfig != null) { - list.add(new OpenDefaultAction()); - } - for (final ToolTemplate toolTemplate : templates) { - list.add(new OpenWithAction(toolTemplate.getName())); - } - return list; - } - private abstract class HistoryTableAction extends DockingAction { + HistoryTableAction(String name) { super(name, "Version History Panel", false); + setHelpLocation(HELP); } @Override @@ -436,6 +425,15 @@ public class VersionHistoryPanel extends JPanel implements Draggable { if (mouseEvent == null) { return false; } + + if (context.getContextObject() != table) { + return false; + } + + if (domainFile == null) { + return false; + } + int rowAtPoint = table.rowAtPoint(mouseEvent.getPoint()); return rowAtPoint >= 0; } @@ -479,8 +477,6 @@ public class VersionHistoryPanel extends JPanel implements Draggable { setDescription("Opens the version using the " + toolName + " tool."); MenuData data = new MenuData(new String[] { "Open With", toolName }, "AAB"); setPopupMenuData(data); - DockingWindowManager dwm = DockingWindowManager.getInstance(table); - dwm.setMenuGroup(new String[] { "Open With" }, "AAB", "2"); } @Override @@ -526,9 +522,4 @@ public class VersionHistoryPanel extends JPanel implements Draggable { } } - - GTable getTable() { - return table; - } - } diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/VersionControlShowHistoryAction.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/VersionControlShowHistoryAction.java index 7421dc745e..b9d7549b09 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/VersionControlShowHistoryAction.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/projectdata/actions/VersionControlShowHistoryAction.java @@ -74,10 +74,8 @@ public class VersionControlShowHistoryAction extends VersionControlAction { if (domainFiles.size() != 1) { return; } - if (dialog == null) { - dialog = new VersionHistoryDialog(); - } - dialog.setDomainFile(domainFiles.get(0)); + + dialog = new VersionHistoryDialog(domainFiles.get(0)); tool.showDialog(dialog, tool.getToolFrame()); } diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/model/Tool.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/model/Tool.java index 9f72cbf106..823ab8141d 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/model/Tool.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/model/Tool.java @@ -56,13 +56,6 @@ public interface Tool extends DockingTool, ToolListener { */ public void exit(); - /** - * Suggests the tool to attempt to close(). This will be as though the user - * selected the close menu option on the tool or hit the closeWindow x button in - * the upper corner (Windows systems). - */ - public void close(); - /** * Can this tool be closed? * @param isExiting true if all of Ghidra is closing, false if just this tool is closing. diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/PluginTool.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/PluginTool.java index de97d4660d..99af2d9841 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/PluginTool.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/PluginTool.java @@ -22,7 +22,6 @@ import java.awt.*; import java.awt.event.KeyEvent; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; -import java.util.ArrayList; import java.util.List; import java.util.Set; import java.util.concurrent.atomic.AtomicReference; @@ -34,6 +33,7 @@ import org.jdom.Element; import docking.*; import docking.action.*; +import docking.actions.PopupActionProvider; import docking.actions.ToolActions; import docking.framework.AboutDialog; import docking.framework.ApplicationInformationDisplayFactory; @@ -58,24 +58,24 @@ import ghidra.framework.plugintool.util.*; import ghidra.framework.project.ProjectDataService; import ghidra.framework.project.tool.ToolIconURL; import ghidra.util.*; -import ghidra.util.datastruct.WeakDataStructureFactory; -import ghidra.util.datastruct.WeakSet; import ghidra.util.task.Task; import ghidra.util.task.TaskLauncher; /** - * Base class that is a container to manage plugins and their actions, and - * to coordinate the firing of plugin events and tool events. A - * PluginTool may have visible components supplied by - *

ComponentProviders 
. These components may be docked within the - * tool, or moved out into their own windows. - *

The PluginTool also manages tasks that run in the background, and - * options used by the plugins. - *

+ * Base class that is a container to manage plugins and their actions, and to coordinate the + * firing of plugin events and tool events. A PluginTool may have visible components supplied by + *
ComponentProviders 
. These components may be docked within the tool, or moved + * out into their own windows. + * + *

Plugins normally add actions via {@link #addAction(DockingActionIf)}. There is also + * an alternate method for getting actions to appear in the popup context menu (see + * {@link #addPopupActionProvider(PopupActionProvider)}). The popup listener mechanism is generally not + * needed and should only be used in special circumstances (see {@link PopupActionProvider}). + * + *

The PluginTool also manages tasks that run in the background, and options used by the plugins. * */ -public abstract class PluginTool extends AbstractDockingTool - implements Tool, DockWinListener, ServiceProvider { +public abstract class PluginTool extends AbstractDockingTool implements Tool, ServiceProvider { private static final String DOCKING_WINDOWS_ON_TOP = "Docking Windows On Top"; @@ -96,8 +96,6 @@ public abstract class PluginTool extends AbstractDockingTool private DialogManager dialogMgr; private PropertyChangeSupport propertyChangeMgr; - private WeakSet popupListeners = - WeakDataStructureFactory.createSingleThreadAccessWeakSet(); private OptionsChangeListener optionsListener = new ToolOptionsListener(); protected ManagePluginsDialog manageDialog; protected ExtensionTableProvider extensionTableProvider; @@ -192,7 +190,7 @@ public abstract class PluginTool extends AbstractDockingTool List windowIcons = ApplicationInformationDisplayFactory.getWindowIcons(); DockingWindowManager newManager = - new DockingWindowManager(this, windowIcons, this, isModal, isDockable, hasStatus, null); + new DockingWindowManager(this, windowIcons, isModal, isDockable, hasStatus, null); return newManager; } @@ -264,17 +262,6 @@ public abstract class PluginTool extends AbstractDockingTool return winMgr.isWindowsOnTop(); } - /** - * Add popup listener that is notified when the popup menu is about to be - * displayed. - * - * @param listener listener that is notified when the popup menu is to - * be displayed - */ - public void addPopupListener(PopupListener listener) { - popupListeners.add(listener); - } - /** * Returns the manage plugins dialog that is currently * being used. @@ -308,15 +295,6 @@ public abstract class PluginTool extends AbstractDockingTool showDialog(extensionTableProvider); } - /** - * Remove popup listener - * @param listener listener that is notified when the popup menu is to - * be displayed - */ - public void removePopupListener(PopupListener listener) { - popupListeners.remove(listener); - } - /** * Set whether a component's header should be shown; the header is the component that * is dragged in order to move the component within the tool, or out of the tool @@ -1102,19 +1080,6 @@ public abstract class PluginTool extends AbstractDockingTool eventMgr.clearLastEvents(); } - @Override - public List getPopupActions(ActionContext context) { - - List actionList = new ArrayList<>(); - for (PopupListener pl : popupListeners) { - List actions = pl.getPopupActions(context); - if (actions != null) { - actionList.addAll(actions); - } - } - return actionList; - } - /** * Close this tool: *

    diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/PopupListener.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/PopupListener.java deleted file mode 100644 index 5cca8158d7..0000000000 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/plugintool/PopupListener.java +++ /dev/null @@ -1,40 +0,0 @@ -/* ### - * IP: GHIDRA - * REVIEWED: YES - * - * 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. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package ghidra.framework.plugintool; - -import java.util.List; - -import docking.ActionContext; -import docking.action.DockingActionIf; - -/** - * PopupListener provides notification when the popup action - * menu is displayed. - */ -public interface PopupListener { - - /** - * Provides notification that the popup menu is about to be displayed - * and allows a set of temporary actions to be included in the popup menu. - * Actions returned will be included in the menu if they have a valid popup - * menu path and respond true to the isValidContext method. - * @param context the ActionContext - * @return list of temporary popup actions (null may be returned) - */ - List getPopupActions(ActionContext context); - -} diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/project/tool/GhidraTool.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/project/tool/GhidraTool.java index c9804a1f47..cadcb8c8d4 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/project/tool/GhidraTool.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/project/tool/GhidraTool.java @@ -84,7 +84,7 @@ public class GhidraTool extends PluginTool { @Override protected DockingWindowManager createDockingWindowManager(boolean isDockable, boolean hasStatus, boolean isModal) { - return new DockingWindowManager(this, null, this, isModal, isDockable, hasStatus, + return new DockingWindowManager(this, null, isModal, isDockable, hasStatus, new OpenFileDropHandlerFactory(this)); } diff --git a/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/VersionControlScreenShots.java b/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/VersionControlScreenShots.java index 95eccb2390..2ea3e10283 100644 --- a/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/VersionControlScreenShots.java +++ b/Ghidra/Test/IntegrationTest/src/screen/java/help/screenshot/VersionControlScreenShots.java @@ -136,9 +136,8 @@ public class VersionControlScreenShots extends GhidraScreenShotGenerator { @Test public void testVersionHistory() throws Exception { - VersionHistoryDialog dialog = new VersionHistoryDialog(); DomainFile df = createDomainFile(); - dialog.setDomainFile(df); + VersionHistoryDialog dialog = new VersionHistoryDialog(df); runSwing(() -> tool.showDialog(dialog)); VersionHistoryDialog d = waitForDialogComponent(dialog.getClass());