GT-2960 - Docking Actions - Consolidated the multiple methods of adding

dynamic popup actions
This commit is contained in:
dragonmacher 2019-07-29 18:20:00 -04:00
parent 785eb5a2a5
commit ab2a390fca
37 changed files with 375 additions and 341 deletions

View file

@ -24,5 +24,5 @@
<listAttribute key="org.eclipse.jdt.launching.MODULEPATH"/> <listAttribute key="org.eclipse.jdt.launching.MODULEPATH"/>
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="ghidra.GhidraRun"/> <stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="ghidra.GhidraRun"/>
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="Framework Utility"/> <stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="Framework Utility"/>
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-XX:+IgnoreUnrecognizedVMOptions -Djava.system.class.loader=ghidra.GhidraClassLoader -Dfile.encoding=UTF8 -Duser.country=US -Duser.language=en -Dsun.java2d.pmoffscreen=false -Dsun.java2d.xrender=true -Dsun.java2d.uiScale=1 -Dsun.java2d.d3d=false -Xdock:name=&quot;Ghidra&quot; -Dvisualvm.display.name=Ghidra"/> <stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-XX:+IgnoreUnrecognizedVMOptions -Djava.system.class.loader=ghidra.GhidraClassLoader -Dfile.encoding=UTF8 -Duser.country=US -Duser.language=en -Dsun.java2d.pmoffscreen=false -Dsun.java2d.xrender=false -Dsun.java2d.uiScale=1 -Dsun.java2d.d3d=false -Xdock:name=&quot;Ghidra&quot; -Dvisualvm.display.name=Ghidra"/>
</launchConfiguration> </launchConfiguration>

View file

@ -1,6 +1,5 @@
/* ### /* ###
* IP: GHIDRA * IP: GHIDRA
* REVIEWED: YES
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with 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.ActionContext;
import docking.WindowPosition; import docking.WindowPosition;
import docking.action.DockingActionIf; 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; private ListingMergePanel mergePanel;
public ListingMergePanelProvider(PluginTool tool, Plugin plugin, String owner, public ListingMergePanelProvider(PluginTool tool, Plugin plugin, String owner,
@ -37,7 +37,7 @@ public class ListingMergePanelProvider extends ComponentProviderAdapter implemen
setTitle("Listing Merge Tool"); setTitle("Listing Merge Tool");
setDefaultWindowPosition(WindowPosition.TOP); setDefaultWindowPosition(WindowPosition.TOP);
this.mergePanel = mergePanel; this.mergePanel = mergePanel;
tool.addPopupListener(this); tool.addPopupActionProvider(this);
} }
@Override @Override

View file

@ -23,6 +23,7 @@ import javax.swing.SwingUtilities;
import docking.ActionContext; import docking.ActionContext;
import docking.action.*; import docking.action.*;
import docking.actions.PopupActionProvider;
import docking.widgets.table.GTable; import docking.widgets.table.GTable;
import ghidra.app.CorePluginPackage; import ghidra.app.CorePluginPackage;
import ghidra.app.events.ProgramSelectionPluginEvent; import ghidra.app.events.ProgramSelectionPluginEvent;
@ -60,7 +61,7 @@ import resources.*;
) )
//@formatter:on //@formatter:on
public class BookmarkPlugin extends ProgramPlugin public class BookmarkPlugin extends ProgramPlugin
implements DomainObjectListener, PopupListener, BookmarkService { implements DomainObjectListener, PopupActionProvider, BookmarkService {
private final static int MAX_DELETE_ACTIONS = 10; private final static int MAX_DELETE_ACTIONS = 10;
@ -190,7 +191,7 @@ public class BookmarkPlugin extends ProgramPlugin
public synchronized void dispose() { public synchronized void dispose() {
navUpdater.dispose(); navUpdater.dispose();
tool.removePopupListener(this); tool.removePopupActionProvider(this);
if (repaintMgr != null) { if (repaintMgr != null) {
repaintMgr.dispose(); repaintMgr.dispose();
} }
@ -227,7 +228,7 @@ public class BookmarkPlugin extends ProgramPlugin
provider.setGoToService(goToService); provider.setGoToService(goToService);
markerService = tool.getService(MarkerService.class); markerService = tool.getService(MarkerService.class);
tool.addPopupListener(this); tool.addPopupActionProvider(this);
navUpdater = new NavUpdater(); navUpdater = new NavUpdater();
repaintMgr = new SwingUpdateManager(500, () -> provider.repaint()); repaintMgr = new SwingUpdateManager(500, () -> provider.repaint());

View file

@ -29,6 +29,7 @@ import javax.swing.event.ChangeListener;
import docking.*; import docking.*;
import docking.action.*; import docking.action.*;
import docking.actions.PopupActionProvider;
import docking.dnd.*; import docking.dnd.*;
import docking.widgets.EventTrigger; import docking.widgets.EventTrigger;
import docking.widgets.fieldpanel.FieldPanel; import docking.widgets.fieldpanel.FieldPanel;
@ -57,7 +58,7 @@ import resources.ResourceManager;
public class CodeViewerProvider extends NavigatableComponentProviderAdapter public class CodeViewerProvider extends NavigatableComponentProviderAdapter
implements ProgramLocationListener, ProgramSelectionListener, Draggable, Droppable, implements ProgramLocationListener, ProgramSelectionListener, Draggable, Droppable,
ChangeListener, StringSelectionListener, PopupListener { ChangeListener, StringSelectionListener, PopupActionProvider {
private static final String OLD_NAME = "CodeBrowserPlugin"; private static final String OLD_NAME = "CodeBrowserPlugin";
private static final String NAME = "Listing"; private static final String NAME = "Listing";
@ -156,7 +157,7 @@ public class CodeViewerProvider extends NavigatableComponentProviderAdapter
listingPanel.addIndexMapChangeListener(this); listingPanel.addIndexMapChangeListener(this);
codeViewerClipboardProvider = new CodeBrowserClipboardProvider(tool, this); codeViewerClipboardProvider = new CodeBrowserClipboardProvider(tool, this);
tool.addPopupListener(this); tool.addPopupActionProvider(this);
} }
@Override @Override

View file

@ -28,6 +28,7 @@ import javax.swing.tree.TreePath;
import docking.ActionContext; import docking.ActionContext;
import docking.action.*; import docking.action.*;
import docking.actions.PopupActionProvider;
import docking.widgets.tree.GTreeNode; import docking.widgets.tree.GTreeNode;
import generic.jar.ResourceFile; import generic.jar.ResourceFile;
import generic.util.Path; import generic.util.Path;
@ -78,7 +79,7 @@ import ghidra.util.task.TaskLauncher;
) )
//@formatter:on //@formatter:on
public class DataTypeManagerPlugin extends ProgramPlugin 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 String SEACH_PROVIDER_NAME = "Search DataTypes Provider";
private static final int RECENTLY_USED_CACHE_SIZE = 10; private static final int RECENTLY_USED_CACHE_SIZE = 10;
@ -158,7 +159,7 @@ public class DataTypeManagerPlugin extends ProgramPlugin
if (codeViewerService != null) { if (codeViewerService != null) {
codeViewerService.addProgramDropProvider(new DataDropOnBrowserHandler(this)); codeViewerService.addProgramDropProvider(new DataDropOnBrowserHandler(this));
} }
tool.addPopupListener(this); tool.addPopupActionProvider(this);
tool.setMenuGroup(new String[] { SyncRefreshAction.MENU_NAME }, "SYNC"); tool.setMenuGroup(new String[] { SyncRefreshAction.MENU_NAME }, "SYNC");
tool.setMenuGroup(new String[] { UpdateAction.MENU_NAME }, "SYNC"); tool.setMenuGroup(new String[] { UpdateAction.MENU_NAME }, "SYNC");
tool.setMenuGroup(new String[] { CommitAction.MENU_NAME }, "SYNC"); tool.setMenuGroup(new String[] { CommitAction.MENU_NAME }, "SYNC");
@ -263,7 +264,7 @@ public class DataTypeManagerPlugin extends ProgramPlugin
@Override @Override
public void dispose() { public void dispose() {
tool.removePopupListener(this); tool.removePopupActionProvider(this);
provider.dispose(); provider.dispose();
close(); close();
dataTypeManagerHandler.dispose(); dataTypeManagerHandler.dispose();

View file

@ -23,6 +23,7 @@ import javax.swing.Icon;
import docking.ActionContext; import docking.ActionContext;
import docking.action.DockingAction; import docking.action.DockingAction;
import docking.action.DockingActionIf; import docking.action.DockingActionIf;
import docking.actions.PopupActionProvider;
import docking.widgets.fieldpanel.internal.FieldPanelCoordinator; import docking.widgets.fieldpanel.internal.FieldPanelCoordinator;
import ghidra.app.util.viewer.listingpanel.ListingCodeComparisonPanel; import ghidra.app.util.viewer.listingpanel.ListingCodeComparisonPanel;
import ghidra.app.util.viewer.listingpanel.ListingPanel; import ghidra.app.util.viewer.listingpanel.ListingPanel;
@ -37,7 +38,7 @@ import resources.ResourceManager;
/** /**
* This is the dockable provider that displays a FunctionComparisonPanel. * 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 String HELP_TOPIC = "FunctionComparison";
private static final Icon ICON = ResourceManager.loadImage("images/page_white_c.png"); private static final Icon ICON = ResourceManager.loadImage("images/page_white_c.png");
@ -120,7 +121,7 @@ public class FunctionComparisonProvider extends ComponentProviderAdapter impleme
setTransient(); setTransient();
setTabText(functionComparisonPanel); setTabText(functionComparisonPanel);
addSpecificCodeComparisonActions(); addSpecificCodeComparisonActions();
tool.addPopupListener(this); tool.addPopupActionProvider(this);
setHelpLocation(new HelpLocation(HELP_TOPIC, "Function Comparison")); setHelpLocation(new HelpLocation(HELP_TOPIC, "Function Comparison"));
} }
@ -178,7 +179,7 @@ public class FunctionComparisonProvider extends ComponentProviderAdapter impleme
@Override @Override
public void removeFromTool() { public void removeFromTool() {
tool.removePopupListener(this); tool.removePopupActionProvider(this);
super.removeFromTool(); super.removeFromTool();
} }

View file

@ -22,6 +22,7 @@ import java.util.List;
import javax.swing.*; import javax.swing.*;
import docking.ActionContext;
import docking.DockingWindowManager; import docking.DockingWindowManager;
import docking.action.DockingActionIf; import docking.action.DockingActionIf;
import docking.widgets.EmptyBorderButton; import docking.widgets.EmptyBorderButton;
@ -101,7 +102,7 @@ public class InstructionTable extends AbstractInstructionTable {
* (which is all of them). * (which is all of them).
*/ */
@Override @Override
public List<DockingActionIf> getDockingActions() { public List<DockingActionIf> getPopupActions(ActionContext context) {
return new ArrayList<>(); return new ArrayList<>();
} }

View file

@ -136,10 +136,10 @@ public class PreviewTable extends AbstractInstructionTable {
* any existing menus; it simply adds to them. * any existing menus; it simply adds to them.
*/ */
@Override @Override
public List<DockingActionIf> getDockingActions() { public List<DockingActionIf> getPopupActions(ActionContext context) {
// Invoke the base class method to add default menu options. // Invoke the base class method to add default menu options.
List<DockingActionIf> list = super.getDockingActions(); List<DockingActionIf> list = super.getPopupActions(context);
// And now add our own. // And now add our own.
addCustomMenuItems(list); addCustomMenuItems(list);

View file

@ -17,10 +17,14 @@ package ghidra.framework.main;
import java.awt.BorderLayout; import java.awt.BorderLayout;
import java.awt.Dimension; import java.awt.Dimension;
import java.awt.event.MouseEvent;
import java.io.IOException; import java.io.IOException;
import java.util.List;
import javax.swing.*; import javax.swing.*;
import docking.ActionContext;
import docking.action.DockingActionIf;
import ghidra.framework.main.datatree.VersionHistoryPanel; import ghidra.framework.main.datatree.VersionHistoryPanel;
import ghidra.framework.model.*; import ghidra.framework.model.*;
import ghidra.framework.plugintool.PluginTool; import ghidra.framework.plugintool.PluginTool;
@ -47,11 +51,13 @@ public class OpenVersionedFileDialog extends DataTreeDialog {
private JSplitPane splitPane; private JSplitPane splitPane;
private JButton historyButton; private JButton historyButton;
private VersionHistoryPanel historyPanel;
private JPanel mainPanel; private JPanel mainPanel;
private boolean historyIsShowing; private boolean historyIsShowing;
private PluginTool tool; private PluginTool tool;
private VersionHistoryPanel historyPanel;
private List<DockingActionIf> popupActions;
/** /**
* Constructor * Constructor
* @param tool tool where the file is being opened. * @param tool tool where the file is being opened.
@ -178,13 +184,32 @@ public class OpenVersionedFileDialog extends DataTreeDialog {
super.close(); 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() { private boolean createHistoryPanel() {
try { try {
historyPanel = new VersionHistoryPanel(tool, null); historyPanel = new VersionHistoryPanel(tool, null);
popupActions = historyPanel.createPopupActions();
} }
catch (IOException ioe) { catch (IOException ioe) {
Msg.debug(getClass(), Msg.debug(getClass(),
"Error creating history panel for versioned file: " + ioe.getMessage()); "Error creating history panel for versioned file: " + ioe.getMessage(), ioe);
return false; 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;
}
} }

View file

@ -32,7 +32,7 @@ public class TestTool extends GhidraTool {
@Override @Override
protected DockingWindowManager createDockingWindowManager(boolean isDockable, boolean hasStatus, protected DockingWindowManager createDockingWindowManager(boolean isDockable, boolean hasStatus,
boolean isModal) { boolean isModal) {
return new DockingWindowManager(this, null, this, isModal, isDockable, hasStatus, null); return new DockingWindowManager(this, null, isModal, isDockable, hasStatus, null);
} }
@Override @Override

View file

@ -45,7 +45,7 @@ public class DockingWindowManagerTest extends AbstractDockingTest {
// default window position. // default window position.
// //
DockingWindowManager dwm = new DockingWindowManager(tool, (List<Image>) null, null); DockingWindowManager dwm = new DockingWindowManager(tool, (List<Image>) null);
ComponentProvider providerA = addProvider(dwm, "A", "a", RIGHT); ComponentProvider providerA = addProvider(dwm, "A", "a", RIGHT);
ComponentProvider providerB = addProvider(dwm, "B", "b", BOTTOM); ComponentProvider providerB = addProvider(dwm, "B", "b", BOTTOM);
@ -65,7 +65,7 @@ public class DockingWindowManagerTest extends AbstractDockingTest {
// intragroup window position. Note: 'Stacked' is the default. // intragroup window position. Note: 'Stacked' is the default.
// //
DockingWindowManager dwm = new DockingWindowManager(tool, (List<Image>) null, null); DockingWindowManager dwm = new DockingWindowManager(tool, (List<Image>) null);
ComponentProvider providerA1 = addProvider(dwm, "A1", "a", RIGHT, STACK); ComponentProvider providerA1 = addProvider(dwm, "A1", "a", RIGHT, STACK);
ComponentProvider providerA2 = addProvider(dwm, "A2", "a", BOTTOM, STACK); ComponentProvider providerA2 = addProvider(dwm, "A2", "a", BOTTOM, STACK);
@ -83,7 +83,7 @@ public class DockingWindowManagerTest extends AbstractDockingTest {
// intragroup window position. // intragroup window position.
// //
DockingWindowManager dwm = new DockingWindowManager(tool, (List<Image>) null, null); DockingWindowManager dwm = new DockingWindowManager(tool, (List<Image>) null);
ComponentProvider providerA1 = addProvider(dwm, "A1", "a", RIGHT, STACK); ComponentProvider providerA1 = addProvider(dwm, "A1", "a", RIGHT, STACK);
ComponentProvider providerA2 = addProvider(dwm, "A2", "a", LEFT, BOTTOM); ComponentProvider providerA2 = addProvider(dwm, "A2", "a", LEFT, BOTTOM);
@ -100,7 +100,7 @@ public class DockingWindowManagerTest extends AbstractDockingTest {
// intragroup window position. // intragroup window position.
// //
DockingWindowManager dwm = new DockingWindowManager(tool, (List<Image>) null, null); DockingWindowManager dwm = new DockingWindowManager(tool, (List<Image>) null);
ComponentProvider providerA1 = addProvider(dwm, "A1", "a", RIGHT, WINDOW); ComponentProvider providerA1 = addProvider(dwm, "A1", "a", RIGHT, WINDOW);
ComponentProvider providerA2 = addProvider(dwm, "A2", "a", LEFT, 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 // note: the positions specified here are for default positions, not intragroup positions
DockingWindowManager dwm = new DockingWindowManager(tool, (List<Image>) null, null); DockingWindowManager dwm = new DockingWindowManager(tool, (List<Image>) null);
ComponentProvider providerA = addProvider(dwm, "A", "a", RIGHT, STACK); ComponentProvider providerA = addProvider(dwm, "A", "a", RIGHT, STACK);
ComponentProvider providerAB = addProvider(dwm, "AB", "a.b", BOTTOM, 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 // note: the positions specified here are for default positions, not intragroup positions
DockingWindowManager dwm = new DockingWindowManager(tool, (List<Image>) null, null); DockingWindowManager dwm = new DockingWindowManager(tool, (List<Image>) null);
ComponentProvider providerA = addProvider(dwm, "A", "a", RIGHT, BOTTOM); ComponentProvider providerA = addProvider(dwm, "A", "a", RIGHT, BOTTOM);
ComponentProvider providerAB = addProvider(dwm, "AB", "a.b", BOTTOM, TOP); 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 // 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 // are shown after that XML is restored--even if the window positioning changes
// //
final DockingWindowManager dwm1 = new DockingWindowManager(tool, (List<Image>) null, null); final DockingWindowManager dwm1 = new DockingWindowManager(tool, (List<Image>) null);
ComponentProvider providerA = addProvider(dwm1, "A", "a", RIGHT); ComponentProvider providerA = addProvider(dwm1, "A", "a", RIGHT);
ComponentProvider providerB = addProvider(dwm1, "B", "b", BOTTOM); 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 // 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 // are shown after that XML is restored--even if the window positioning changes
// //
DockingWindowManager dwm1 = new DockingWindowManager(tool, (List<Image>) null, null); DockingWindowManager dwm1 = new DockingWindowManager(tool, (List<Image>) null);
ComponentProvider providerA = addProvider(dwm1, "A", "a", RIGHT); ComponentProvider providerA = addProvider(dwm1, "A", "a", RIGHT);
ComponentProvider providerAB = addProvider(dwm1, "AB", "a.b", BOTTOM); 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 // 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. // works when the parent is the first provider open.
// //
DockingWindowManager dwm = new DockingWindowManager(tool, (List<Image>) null, null); DockingWindowManager dwm = new DockingWindowManager(tool, (List<Image>) null);
ComponentProvider providerA = addProvider(dwm, "A", "a", TOP, RIGHT); ComponentProvider providerA = addProvider(dwm, "A", "a", TOP, RIGHT);
ComponentProvider providerAB = addProvider(dwm, "AB", "a.b", RIGHT, BOTTOM); 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 // 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. // works when the subgroup is the first provider open.
// //
DockingWindowManager dwm = new DockingWindowManager(tool, (List<Image>) null, null); DockingWindowManager dwm = new DockingWindowManager(tool, (List<Image>) null);
ComponentProvider providerAB = addProvider(dwm, "AB", "a.b", RIGHT, BOTTOM); ComponentProvider providerAB = addProvider(dwm, "AB", "a.b", RIGHT, BOTTOM);
ComponentProvider providerA = addProvider(dwm, "A", "a", TOP, RIGHT); 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 // Test that two providers that don't share an owner (the plugin) can share a group and
// open relative to each other. // open relative to each other.
// //
DockingWindowManager dwm = new DockingWindowManager(tool, (List<Image>) null, null); DockingWindowManager dwm = new DockingWindowManager(tool, (List<Image>) null);
ComponentProvider p1 = addProvider(dwm, "Owner_1", "Name_1", "group", TOP, TOP); ComponentProvider p1 = addProvider(dwm, "Owner_1", "Name_1", "group", TOP, TOP);
ComponentProvider p2 = addProvider(dwm, "Owner_2", "Name_2", "group", BOTTOM, RIGHT); 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<Image>) null, null); DockingWindowManager dwm = new DockingWindowManager(tool, (List<Image>) null);
ComponentProvider pA = addProvider(dwm, "Owner_1", "A", "a", LEFT, LEFT); ComponentProvider pA = addProvider(dwm, "Owner_1", "A", "a", LEFT, LEFT);
ComponentProvider pB = addProvider(dwm, "Owner_2", "B", "b", RIGHT, RIGHT); 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) { private DockingWindowManager createNewDockingWindowManagerFromXML(final Element element) {
final DockingWindowManager dwm2 = final DockingWindowManager dwm2 =
new DockingWindowManager(new DummyTool("Tool2"), (List<Image>) null, null); new DockingWindowManager(new DummyTool("Tool2"), (List<Image>) null);
runSwing(() -> { runSwing(() -> {
dwm2.setVisible(true); dwm2.setVisible(true);

View file

@ -35,7 +35,7 @@ import ghidra.test.DummyTool;
public class NumberInputDialogTest extends AbstractDockingTest { public class NumberInputDialogTest extends AbstractDockingTest {
private DockingWindowManager dwm = private DockingWindowManager dwm =
new DockingWindowManager(new DummyTool(), (List<Image>) null, null); new DockingWindowManager(new DummyTool(), (List<Image>) null);
private NumberInputDialog dialog; private NumberInputDialog dialog;
private JButton okButton; private JButton okButton;
private JTextField textField; private JTextField textField;

View file

@ -51,7 +51,7 @@ public class GhidraTableFilterTest extends AbstractGhidraHeadedIntegrationTest {
filteredModel = filterPanel.getTableFilterModel(); filteredModel = filterPanel.getTableFilterModel();
table.setAutoLookupColumn(4); table.setAutoLookupColumn(4);
winMgr = new DockingWindowManager(new DummyTool(), null, null); winMgr = new DockingWindowManager(new DummyTool(), null);
winMgr.addComponent(new TestTableComponentProvider()); winMgr.addComponent(new TestTableComponentProvider());
winMgr.setVisible(true); winMgr.setVisible(true);
} }

View file

@ -29,6 +29,7 @@ import org.jdom.Element;
import docking.*; import docking.*;
import docking.action.DockingActionIf; import docking.action.DockingActionIf;
import docking.actions.DockingToolActions; import docking.actions.DockingToolActions;
import docking.actions.PopupActionProvider;
import ghidra.framework.model.*; import ghidra.framework.model.*;
import ghidra.framework.options.ToolOptions; import ghidra.framework.options.ToolOptions;
import ghidra.framework.plugintool.PluginEvent; import ghidra.framework.plugintool.PluginEvent;
@ -298,6 +299,16 @@ public class DummyTool implements Tool {
//do nothing //do nothing
} }
@Override
public void addPopupActionProvider(PopupActionProvider listener) {
// do nothing
}
@Override
public void removePopupActionProvider(PopupActionProvider listener) {
// do nothing
}
@Override @Override
public Set<DockingActionIf> getAllActions() { public Set<DockingActionIf> getAllActions() {
return Collections.emptySet(); return Collections.emptySet();

View file

@ -31,6 +31,7 @@ import javax.swing.table.JTableHeader;
import docking.ActionContext; import docking.ActionContext;
import docking.WindowPosition; import docking.WindowPosition;
import docking.action.*; import docking.action.*;
import docking.actions.PopupActionProvider;
import docking.menu.ActionState; import docking.menu.ActionState;
import docking.menu.MultiStateDockingAction; import docking.menu.MultiStateDockingAction;
import docking.widgets.EventTrigger; import docking.widgets.EventTrigger;
@ -52,7 +53,6 @@ import ghidra.framework.model.*;
import ghidra.framework.options.Options; import ghidra.framework.options.Options;
import ghidra.framework.options.SaveState; import ghidra.framework.options.SaveState;
import ghidra.framework.plugintool.ComponentProviderAdapter; import ghidra.framework.plugintool.ComponentProviderAdapter;
import ghidra.framework.plugintool.PopupListener;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.listing.Function; import ghidra.program.model.listing.Function;
import ghidra.program.model.listing.Program; import ghidra.program.model.listing.Program;
@ -67,7 +67,7 @@ import resources.ResourceManager;
* Provider for the version tracking function association table. * Provider for the version tracking function association table.
*/ */
public class VTFunctionAssociationProvider extends ComponentProviderAdapter 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 FILTER_SETTINGS_KEY = "FUNCTION_FILTER_SETTINGS";
private static final String BASE_TITLE = "Version Tracking Functions"; private static final String BASE_TITLE = "Version Tracking Functions";
@ -125,7 +125,7 @@ public class VTFunctionAssociationProvider extends ComponentProviderAdapter
createActions(); createActions();
addGeneralCodeComparisonActions(); addGeneralCodeComparisonActions();
controller.addListener(this); controller.addListener(this);
tool.addPopupListener(this); tool.addPopupActionProvider(this);
} }
private void createActions() { private void createActions() {
@ -334,7 +334,7 @@ public class VTFunctionAssociationProvider extends ComponentProviderAdapter
destinationFunctionsTable.dispose(); destinationFunctionsTable.dispose();
destinationTableFilterPanel.dispose(); destinationTableFilterPanel.dispose();
tool.removePopupListener(this); tool.removePopupActionProvider(this);
} }
public void reload() { public void reload() {

View file

@ -30,6 +30,7 @@ import javax.swing.table.*;
import docking.*; import docking.*;
import docking.action.*; import docking.action.*;
import docking.actions.PopupActionProvider;
import docking.help.HelpService; import docking.help.HelpService;
import docking.widgets.EventTrigger; import docking.widgets.EventTrigger;
import docking.widgets.fieldpanel.FieldPanel; import docking.widgets.fieldpanel.FieldPanel;
@ -56,7 +57,6 @@ import ghidra.framework.model.DomainObjectChangedEvent;
import ghidra.framework.options.Options; import ghidra.framework.options.Options;
import ghidra.framework.options.SaveState; import ghidra.framework.options.SaveState;
import ghidra.framework.plugintool.ComponentProviderAdapter; import ghidra.framework.plugintool.ComponentProviderAdapter;
import ghidra.framework.plugintool.PopupListener;
import ghidra.program.model.address.*; import ghidra.program.model.address.*;
import ghidra.program.model.listing.*; import ghidra.program.model.listing.*;
import ghidra.program.util.ProgramLocation; 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. * This provides the GUI for displaying and working with version tracking markup items.
*/ */
public class VTMarkupItemsTableProvider extends ComponentProviderAdapter public class VTMarkupItemsTableProvider extends ComponentProviderAdapter
implements FilterDialogModel<VTMarkupItem>, VTControllerListener, PopupListener { implements FilterDialogModel<VTMarkupItem>, VTControllerListener, PopupActionProvider {
private static final String SHOW_COMPARISON_PANEL = "SHOW_COMPARISON_PANEL"; 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, iconTimer = new FilterIconFlashTimer<>(UNFILTERED_ICON, FILTERED_ICON,
ancillaryFilterDialog, ancillaryFilterButton); ancillaryFilterDialog, ancillaryFilterButton);
tool.addPopupListener(this); tool.addPopupActionProvider(this);
HelpLocation helpLocation = new HelpLocation("VersionTrackingPlugin", "Markup Items Table"); HelpLocation helpLocation = new HelpLocation("VersionTrackingPlugin", "Markup Items Table");
setHelpLocation(helpLocation); setHelpLocation(helpLocation);
@ -534,7 +534,7 @@ public class VTMarkupItemsTableProvider extends ComponentProviderAdapter
filter.dispose(); filter.dispose();
} }
tool.removePopupListener(this); tool.removePopupActionProvider(this);
} }
VTController getController() { VTController getController() {

View file

@ -21,6 +21,7 @@ import java.util.*;
import javax.swing.JFrame; import javax.swing.JFrame;
import docking.action.DockingActionIf; import docking.action.DockingActionIf;
import docking.actions.PopupActionProvider;
import docking.actions.ToolActions; import docking.actions.ToolActions;
import ghidra.framework.options.ToolOptions; import ghidra.framework.options.ToolOptions;
import ghidra.util.Swing; import ghidra.util.Swing;
@ -123,6 +124,16 @@ public abstract class AbstractDockingTool implements DockingTool {
return toolActions.getAllActions(); return toolActions.getAllActions();
} }
@Override
public void addPopupActionProvider(PopupActionProvider provider) {
winMgr.addPopupActionProvider(provider);
}
@Override
public void removePopupActionProvider(PopupActionProvider provider) {
winMgr.removePopupActionProvider(provider);
}
@Override @Override
public Set<DockingActionIf> getDockingActionsByOwnerName(String owner) { public Set<DockingActionIf> getDockingActionsByOwnerName(String owner) {
return toolActions.getActions(owner); return toolActions.getActions(owner);

View file

@ -1,6 +1,5 @@
/* ### /* ###
* IP: GHIDRA * IP: GHIDRA
* REVIEWED: YES
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -16,7 +15,12 @@
*/ */
package docking; 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 interface ComponentLoadedListener {
public void componentLoaded(DockingWindowManager windowManager); public void componentLoaded(DockingWindowManager windowManager);
} }

View file

@ -32,7 +32,7 @@ import docking.actions.ActionAdapter;
import docking.actions.KeyBindingUtils; import docking.actions.KeyBindingUtils;
import docking.event.mouse.GMouseListenerAdapter; import docking.event.mouse.GMouseListenerAdapter;
import docking.menu.DockingToolbarButton; import docking.menu.DockingToolbarButton;
import docking.util.*; import docking.util.AnimationUtils;
import docking.widgets.label.GDHtmlLabel; import docking.widgets.label.GDHtmlLabel;
import ghidra.util.*; import ghidra.util.*;
import ghidra.util.exception.AssertException; 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 * 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. * all the gui elements to appear in the dialog, then use tool.showDialog() to display your dialog.
*/ */
public class DialogComponentProvider public class DialogComponentProvider
implements TaskListener, StatusListener, ActionContextProvider { implements ActionContextProvider, StatusListener, TaskListener {
private static final Color WARNING_COLOR = new Color(0xff9900); private static final Color WARNING_COLOR = new Color(0xff9900);
@ -1369,5 +1368,4 @@ public class DialogComponentProvider
} }
} }
} }

View file

@ -73,7 +73,7 @@ public class DialogComponentProviderPopupActionManager {
MenuGroupMap menuGroupMap = actionManager.getMenuGroupMap(); MenuGroupMap menuGroupMap = actionManager.getMenuGroupMap();
MenuManager menuMgr = MenuManager menuMgr =
new MenuManager("Popup", '\0', null, true, popupMenuHandler, menuGroupMap); new MenuManager("Popup", '\0', null, true, popupMenuHandler, menuGroupMap);
populatePopupMenuActions(actionContext, menuMgr); populatePopupMenuActions(dwm, menuMgr, actionContext);
if (menuMgr.isEmpty()) { if (menuMgr.isEmpty()) {
return; return;
} }
@ -85,7 +85,8 @@ public class DialogComponentProviderPopupActionManager {
popupMenu.show(c, e.getX(), e.getY()); popupMenu.show(c, e.getX(), e.getY());
} }
private void populatePopupMenuActions(ActionContext actionContext, MenuManager menuMgr) { private void populatePopupMenuActions(DockingWindowManager dwm, MenuManager menuMgr,
ActionContext actionContext) {
Iterator<DockingActionIf> iter = popupActions.iterator(); Iterator<DockingActionIf> iter = popupActions.iterator();
while (iter.hasNext()) { while (iter.hasNext()) {
@ -112,6 +113,18 @@ public class DialogComponentProviderPopupActionManager {
} }
} }
} }
List<DockingActionIf> 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);
}
}
}
} }
//================================================================================================== //==================================================================================================

View file

@ -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<DockingActionIf> getPopupActions(ActionContext context);
}

View file

@ -22,6 +22,7 @@ import javax.swing.ImageIcon;
import docking.action.DockingActionIf; import docking.action.DockingActionIf;
import docking.actions.DockingToolActions; import docking.actions.DockingToolActions;
import docking.actions.PopupActionProvider;
import ghidra.framework.options.ToolOptions; import ghidra.framework.options.ToolOptions;
/** /**
@ -129,6 +130,19 @@ public interface DockingTool {
*/ */
public void removeLocalAction(ComponentProvider componentProvider, DockingActionIf action); 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. * Return a set of all actions in the tool.
* *
@ -273,4 +287,12 @@ public interface DockingTool {
* @return the action manager * @return the action manager
*/ */
public DockingToolActions getToolActions(); 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();
} }

View file

@ -30,8 +30,7 @@ import org.apache.commons.collections4.map.LazyMap;
import org.jdom.Element; import org.jdom.Element;
import docking.action.DockingActionIf; import docking.action.DockingActionIf;
import docking.actions.DockingToolActions; import docking.actions.*;
import docking.actions.ToolActions;
import docking.help.HelpService; import docking.help.HelpService;
import generic.util.WindowUtilities; import generic.util.WindowUtilities;
import ghidra.framework.OperatingSystem; import ghidra.framework.OperatingSystem;
@ -87,9 +86,10 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder
private Map<String, ComponentProvider> providerNameCache = new HashMap<>(); private Map<String, ComponentProvider> providerNameCache = new HashMap<>();
private Map<String, PreferenceState> preferenceStateMap = new HashMap<>(); private Map<String, PreferenceState> preferenceStateMap = new HashMap<>();
private DockWinListener docListener;
private ActionToGuiMapper actionToGuiMapper; private ActionToGuiMapper actionToGuiMapper;
private WeakSet<PopupActionProvider> popupActionProviders =
WeakDataStructureFactory.createSingleThreadAccessWeakSet();
private WeakSet<DockingContextListener> contextListeners = private WeakSet<DockingContextListener> contextListeners =
WeakDataStructureFactory.createSingleThreadAccessWeakSet(); WeakDataStructureFactory.createSingleThreadAccessWeakSet();
@ -108,10 +108,9 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder
* Constructs a new DockingWindowManager * Constructs a new DockingWindowManager
* @param tool the tool * @param tool the tool
* @param images the images to use for windows in this window manager * @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<Image> images, DockWinListener docListener) { public DockingWindowManager(DockingTool tool, List<Image> images) {
this(tool, images, docListener, false, true, true, null); this(tool, images, false, true, true, null);
} }
/** /**
@ -119,20 +118,18 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder
* *
* @param tool the tool * @param tool the tool
* @param images the list of icons to set on the window * @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 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 * @param isDocking true for normal operation, false to suppress docking support(removes
* component headers and window menu) * component headers and window menu)
* @param hasStatusBar if true a status bar will be created for the main window * @param hasStatusBar if true a status bar will be created for the main window
* @param factory the drop target factory * @param factory the drop target factory
*/ */
public DockingWindowManager(DockingTool tool, List<Image> images, DockWinListener docListener, public DockingWindowManager(DockingTool tool, List<Image> images, boolean modal,
boolean modal, boolean isDocking, boolean hasStatusBar, DropTargetFactory factory) { boolean isDocking, boolean hasStatusBar, DropTargetFactory factory) {
KeyBindingOverrideKeyEventDispatcher.install(); KeyBindingOverrideKeyEventDispatcher.install();
this.tool = tool; this.tool = tool;
this.docListener = docListener;
this.isDocking = isDocking; this.isDocking = isDocking;
this.hasStatusBar = hasStatusBar; this.hasStatusBar = hasStatusBar;
if (images == null) { if (images == null) {
@ -174,10 +171,6 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder
return helpService; return helpService;
} }
List<DockingActionIf> getTemporaryPopupActions(ActionContext context) {
return docListener.getPopupActions(context);
}
private static synchronized void addInstance(DockingWindowManager winMgr) { private static synchronized void addInstance(DockingWindowManager winMgr) {
instanceList.add(winMgr); instanceList.add(winMgr);
} }
@ -1084,7 +1077,7 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder
* the main window frame. * the main window frame.
*/ */
void close() { void close() {
docListener.close(); tool.close();
} }
boolean isDocking() { boolean isDocking() {
@ -2099,6 +2092,44 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder
actionToGuiMapper.contextChanged(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<DockingActionIf> getTemporaryPopupActions(ActionContext context) {
List<DockingActionIf> actionList = new ArrayList<>();
for (PopupActionProvider pl : popupActionProviders) {
List<DockingActionIf> actions = pl.getPopupActions(context);
if (actions != null) {
actionList.addAll(actions);
}
}
return actionList;
}
public void addContextListener(DockingContextListener listener) { public void addContextListener(DockingContextListener listener) {
contextListeners.add(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 component the component that will be parented in a docking window system.
* @param listener the listener to be notified the component was parented. * @param listener the listener to be notified the component was parented.
*/ */
public static void registerComponentLoadedListener(final Component component, public static void registerComponentLoadedListener(Component component,
final ComponentLoadedListener listener) { 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() { component.addHierarchyListener(new HierarchyListener() {
@Override @Override
public void hierarchyChanged(HierarchyEvent e) { public void hierarchyChanged(HierarchyEvent e) {

View file

@ -17,6 +17,8 @@ package docking.action;
import java.util.List; import java.util.List;
import docking.DockingTool;
/** /**
* An interface for objects (really Components) to implement that signals they provide actions * 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 * for the Docking environment. This interface will be called when the implementor is the source
@ -26,7 +28,11 @@ import java.util.List;
* When the user right-clicks on said table, then Docking system will ask this object for its * 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 * 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 { public interface DockingActionProviderIf {
/** /**

View file

@ -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.
*
* <p>
* 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<DockingActionIf> getPopupActions(ActionContext context);
}

View file

@ -32,6 +32,7 @@ import javax.swing.table.*;
import docking.*; import docking.*;
import docking.action.*; import docking.action.*;
import docking.actions.KeyBindingUtils; import docking.actions.KeyBindingUtils;
import docking.actions.PopupActionProvider;
import docking.widgets.OptionDialog; import docking.widgets.OptionDialog;
import docking.widgets.dialogs.SettingsDialog; import docking.widgets.dialogs.SettingsDialog;
import docking.widgets.filechooser.GhidraFileChooser; import docking.widgets.filechooser.GhidraFileChooser;
@ -69,7 +70,7 @@ import resources.ResourceManager;
* *
* @see GTableFilterPanel * @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"; private static final String LAST_EXPORT_FILE = "LAST_EXPORT_DIR";
@ -510,20 +511,8 @@ public class GTable extends JTable implements KeyStrokeConsumer, DockingActionPr
} }
@Override @Override
public List<DockingActionIf> getDockingActions() { public List<DockingActionIf> getPopupActions(ActionContext context) {
return getDefaultDockingActions();
}
/**
* 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<DockingActionIf> getDefaultDockingActions() {
// we want these top-level groups to all appear together, with no separator // we want these top-level groups to all appear together, with no separator
DockingWindowManager dwm = DockingWindowManager.getInstance(this); DockingWindowManager dwm = DockingWindowManager.getInstance(this);
dwm.setMenuGroup(new String[] { "Copy" }, actionMenuGroup, "1"); dwm.setMenuGroup(new String[] { "Copy" }, actionMenuGroup, "1");
@ -590,6 +579,10 @@ public class GTable extends JTable implements KeyStrokeConsumer, DockingActionPr
createPopupActions(); createPopupActions();
initializeRowHeight(); initializeRowHeight();
DockingWindowManager.registerComponentLoadedListener(this, dwm -> {
dwm.getTool().addPopupActionProvider(this);
});
} }
private void initializeHeader(JTableHeader header) { private void initializeHeader(JTableHeader header) {
@ -1490,5 +1483,4 @@ public class GTable extends JTable implements KeyStrokeConsumer, DockingActionPr
// ignored // ignored
} }
} }
} }

View file

@ -20,7 +20,6 @@ import java.util.List;
import javax.swing.ImageIcon; import javax.swing.ImageIcon;
import docking.action.DockingActionIf;
import docking.actions.ToolActions; import docking.actions.ToolActions;
import docking.framework.ApplicationInformationDisplayFactory; import docking.framework.ApplicationInformationDisplayFactory;
import ghidra.framework.options.ToolOptions; import ghidra.framework.options.ToolOptions;
@ -33,10 +32,9 @@ public class FakeDockingTool extends AbstractDockingTool {
public FakeDockingTool() { public FakeDockingTool() {
DockWinListener listener = new DummyListener();
List<Image> windowIcons = ApplicationInformationDisplayFactory.getWindowIcons(); List<Image> windowIcons = ApplicationInformationDisplayFactory.getWindowIcons();
winMgr = new DockingWindowManager(this, windowIcons, listener, false /*isModal*/, winMgr = new DockingWindowManager(this, windowIcons, false /*isModal*/, true /*isDockable*/,
true /*isDockable*/, true /*hasStatus*/, null /*DropTargetFactory*/); true /*hasStatus*/, null /*DropTargetFactory*/);
toolActions = new ToolActions(this, new ActionToGuiHelper(winMgr)); toolActions = new ToolActions(this, new ActionToGuiHelper(winMgr));
} }
@ -60,16 +58,8 @@ public class FakeDockingTool extends AbstractDockingTool {
return opt; return opt;
} }
private class DummyListener implements DockWinListener {
@Override @Override
public void close() { public void close() {
// stub // stub
} }
@Override
public List<DockingActionIf> getPopupActions(ActionContext context) {
return null;
}
}
} }

View file

@ -44,6 +44,11 @@ public class GenericHelpTopics {
*/ */
public final static String REPOSITORY = "Repository"; public final static String REPOSITORY = "Repository";
/**
* Help Topic for the version control.
*/
public final static String VERSION_CONTROL = "VersionControl";
/** /**
* Help Topic for tools. * Help Topic for tools.
*/ */

View file

@ -490,7 +490,7 @@ public class ProjectDataTablePanel extends JPanel {
} }
@Override @Override
public List<DockingActionIf> getDockingActions() { public List<DockingActionIf> getPopupActions(ActionContext context) {
// TODO we should at least add the 'copy' action // TODO we should at least add the 'copy' action

View file

@ -23,7 +23,6 @@ import javax.swing.SwingUtilities;
import docking.ActionContext; import docking.ActionContext;
import docking.DialogComponentProvider; import docking.DialogComponentProvider;
import docking.action.DockingActionIf; import docking.action.DockingActionIf;
import docking.action.DockingActionProviderIf;
import ghidra.app.util.GenericHelpTopics; import ghidra.app.util.GenericHelpTopics;
import ghidra.framework.main.AppInfo; import ghidra.framework.main.AppInfo;
import ghidra.framework.main.FrontEndTool; import ghidra.framework.main.FrontEndTool;
@ -31,24 +30,26 @@ import ghidra.framework.model.*;
import ghidra.framework.store.FileSystem; import ghidra.framework.store.FileSystem;
import ghidra.util.HelpLocation; import ghidra.util.HelpLocation;
public class VersionHistoryDialog extends DialogComponentProvider public class VersionHistoryDialog extends DialogComponentProvider implements ProjectListener {
implements ProjectListener, DockingActionProviderIf {
private VersionHistoryPanel versionPanel; private VersionHistoryPanel versionPanel;
private MyFolderListener listener = new MyFolderListener(); private MyFolderListener listener = new MyFolderListener();
private List<DockingActionIf> popupActions;
public VersionHistoryDialog() { public VersionHistoryDialog(DomainFile domainFile) {
super("Version History", false); super("Version History", false);
FrontEndTool frontEndTool = AppInfo.getFrontEndTool(); FrontEndTool frontEndTool = AppInfo.getFrontEndTool();
setHelpLocation(new HelpLocation(GenericHelpTopics.REPOSITORY, "Show_History")); setHelpLocation(new HelpLocation(GenericHelpTopics.VERSION_CONTROL, "Show_History"));
versionPanel = new VersionHistoryPanel(frontEndTool, null, true); versionPanel = new VersionHistoryPanel(frontEndTool, domainFile, true);
addWorkPanel(versionPanel); addWorkPanel(versionPanel);
addDismissButton(); addDismissButton();
versionPanel.addPopupActions(this);
setDomainFile(domainFile);
popupActions = versionPanel.createPopupActions();
} }
public void setDomainFile(DomainFile df) { private void setDomainFile(DomainFile df) {
versionPanel.setDomainFile(df); versionPanel.setDomainFile(df);
@ -59,18 +60,24 @@ public class VersionHistoryDialog extends DialogComponentProvider
setTitle("Version History for " + df.getName()); setTitle("Version History for " + df.getName());
project.getProjectData().addDomainFolderChangeListener(listener); 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 @Override
protected void dismissCallback() { protected void dialogClosed() {
super.dialogClosed();
close(); for (DockingActionIf action : popupActions) {
removeAction(action);
setDomainFile(null); }
} }
@Override @Override
@ -127,13 +134,8 @@ public class VersionHistoryDialog extends DialogComponentProvider
@Override @Override
public ActionContext getActionContext(MouseEvent event) { public ActionContext getActionContext(MouseEvent event) {
ActionContext actionContext = new ActionContext(null, this, this); ActionContext actionContext = new ActionContext(null, versionPanel.getTable(), this);
actionContext.setMouseEvent(event); actionContext.setMouseEvent(event);
return actionContext; return actionContext;
} }
@Override
public List<DockingActionIf> getDockingActions() {
return versionPanel.getDockingActions();
}
} }

View file

@ -31,26 +31,29 @@ import javax.swing.event.ListSelectionListener;
import javax.swing.table.TableColumn; import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel; import javax.swing.table.TableColumnModel;
import docking.*; import docking.ActionContext;
import docking.action.*; import docking.action.*;
import docking.dnd.*; import docking.dnd.*;
import docking.widgets.OptionDialog; import docking.widgets.OptionDialog;
import docking.widgets.table.*; import docking.widgets.table.*;
import ghidra.app.util.GenericHelpTopics;
import ghidra.framework.client.ClientUtil; import ghidra.framework.client.ClientUtil;
import ghidra.framework.main.GetVersionedObjectTask; import ghidra.framework.main.GetVersionedObjectTask;
import ghidra.framework.model.*; import ghidra.framework.model.*;
import ghidra.framework.plugintool.PluginTool; import ghidra.framework.plugintool.PluginTool;
import ghidra.framework.store.ItemCheckoutStatus; import ghidra.framework.store.ItemCheckoutStatus;
import ghidra.framework.store.Version; import ghidra.framework.store.Version;
import ghidra.util.HTMLUtilities; import ghidra.util.*;
import ghidra.util.Msg;
import ghidra.util.task.*; 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 { public class VersionHistoryPanel extends JPanel implements Draggable {
private static final HelpLocation HELP =
new HelpLocation(GenericHelpTopics.VERSION_CONTROL, "Show History");
private PluginTool tool; private PluginTool tool;
private DomainFile domainFile; private DomainFile domainFile;
private String domainFilePath; private String domainFilePath;
@ -79,7 +82,6 @@ public class VersionHistoryPanel extends JPanel implements Draggable {
* @param tool tool * @param tool tool
* @param domainFile domain file * @param domainFile domain file
* @param enableUserInteraction if true Draggable support will be enabled * @param enableUserInteraction if true Draggable support will be enabled
* @throws IOException
*/ */
VersionHistoryPanel(PluginTool tool, DomainFile domainFile, boolean enableUserInteraction) { VersionHistoryPanel(PluginTool tool, DomainFile domainFile, boolean enableUserInteraction) {
super(new BorderLayout()); 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) { public void setDomainFile(DomainFile domainFile) {
this.domainFile = domainFile; this.domainFile = domainFile;
domainFilePath = null;
if (domainFile != null) { if (domainFile != null) {
this.domainFilePath = domainFile.getPathname(); 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) { public void addListSelectionListener(ListSelectionListener selectionListener) {
table.getSelectionModel().addListSelectionListener(listener1); table.getSelectionModel().addListSelectionListener(selectionListener);
} }
/** /**
* Remove the list selection listener from history table. * Remove the list selection listener from history table.
* @param selectionListener the listener
*/ */
public void removeListSelectionListener(ListSelectionListener listener1) { public void removeListSelectionListener(ListSelectionListener selectionListener) {
table.getSelectionModel().removeListSelectionListener(listener1); table.getSelectionModel().removeListSelectionListener(selectionListener);
} }
/** /**
* Get the domain object for the selected version. * 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 * @return null if there is no selection
*/ */
public DomainObject getSelectedVersion(Object consumer, boolean readOnly) { public DomainObject getSelectedVersion(Object consumer, boolean readOnly) {
@ -148,16 +154,10 @@ public class VersionHistoryPanel extends JPanel implements Draggable {
return null; return null;
} }
/**
* Return whether a version is selected.
*/
public boolean isVersionSelected() { public boolean isVersionSelected() {
return !table.getSelectionModel().isSelectionEmpty(); return !table.getSelectionModel().isSelectionEmpty();
} }
/**
* Get the version number that was selected.
*/
public int getSelectedVersionNumber() { public int getSelectedVersionNumber() {
int row = table.getSelectedRow(); int row = table.getSelectedRow();
if (row >= 0) { if (row >= 0) {
@ -167,33 +167,21 @@ public class VersionHistoryPanel extends JPanel implements Draggable {
return -1; return -1;
} }
/* (non-Javadoc)
* @see ghidra.util.bean.dnd.Draggable#dragCanceled()
*/
@Override @Override
public void dragCanceled(DragSourceDropEvent event) { public void dragCanceled(DragSourceDropEvent event) {
// no-op // no-op
} }
/* (non-Javadoc)
* @see ghidra.util.bean.dnd.Draggable#getDragAction()
*/
@Override @Override
public int getDragAction() { public int getDragAction() {
return dragAction; return dragAction;
} }
/* (non-Javadoc)
* @see ghidra.util.bean.dnd.Draggable#getDragSourceListener()
*/
@Override @Override
public DragSourceListener getDragSourceListener() { public DragSourceListener getDragSourceListener() {
return dragSourceAdapter; return dragSourceAdapter;
} }
/* (non-Javadoc)
* @see ghidra.util.bean.dnd.Draggable#getTransferable(java.awt.Point)
*/
@Override @Override
public Transferable getTransferable(Point p) { public Transferable getTransferable(Point p) {
int row = table.rowAtPoint(p); int row = table.rowAtPoint(p);
@ -204,9 +192,6 @@ public class VersionHistoryPanel extends JPanel implements Draggable {
return null; return null;
} }
/* (non-Javadoc)
* @see ghidra.util.bean.dnd.Draggable#isStartDragOk(java.awt.dnd.DragGestureEvent)
*/
@Override @Override
public boolean isStartDragOk(DragGestureEvent e) { public boolean isStartDragOk(DragGestureEvent e) {
int row = table.rowAtPoint(e.getDragOrigin()); int row = table.rowAtPoint(e.getDragOrigin());
@ -216,9 +201,6 @@ public class VersionHistoryPanel extends JPanel implements Draggable {
return false; return false;
} }
/* (non-Javadoc)
* @see ghidra.util.bean.dnd.Draggable#move()
*/
@Override @Override
public void move() { public void move() {
// no-op // no-op
@ -363,6 +345,38 @@ public class VersionHistoryPanel extends JPanel implements Draggable {
openWith(null); openWith(null);
} }
public List<DockingActionIf> createPopupActions() {
List<DockingActionIf> 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 { private class MyCellRenderer extends GTableCellRenderer {
@Override @Override
@ -398,36 +412,11 @@ public class VersionHistoryPanel extends JPanel implements Draggable {
} }
public void addPopupActions(DialogComponentProvider provider) {
provider.addAction(new DeleteAction());
}
public List<DockingActionIf> getDockingActions() {
List<DockingActionIf> 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 { private abstract class HistoryTableAction extends DockingAction {
HistoryTableAction(String name) { HistoryTableAction(String name) {
super(name, "Version History Panel", false); super(name, "Version History Panel", false);
setHelpLocation(HELP);
} }
@Override @Override
@ -436,6 +425,15 @@ public class VersionHistoryPanel extends JPanel implements Draggable {
if (mouseEvent == null) { if (mouseEvent == null) {
return false; return false;
} }
if (context.getContextObject() != table) {
return false;
}
if (domainFile == null) {
return false;
}
int rowAtPoint = table.rowAtPoint(mouseEvent.getPoint()); int rowAtPoint = table.rowAtPoint(mouseEvent.getPoint());
return rowAtPoint >= 0; return rowAtPoint >= 0;
} }
@ -479,8 +477,6 @@ public class VersionHistoryPanel extends JPanel implements Draggable {
setDescription("Opens the version using the " + toolName + " tool."); setDescription("Opens the version using the " + toolName + " tool.");
MenuData data = new MenuData(new String[] { "Open With", toolName }, "AAB"); MenuData data = new MenuData(new String[] { "Open With", toolName }, "AAB");
setPopupMenuData(data); setPopupMenuData(data);
DockingWindowManager dwm = DockingWindowManager.getInstance(table);
dwm.setMenuGroup(new String[] { "Open With" }, "AAB", "2");
} }
@Override @Override
@ -526,9 +522,4 @@ public class VersionHistoryPanel extends JPanel implements Draggable {
} }
} }
GTable getTable() {
return table;
}
} }

View file

@ -74,10 +74,8 @@ public class VersionControlShowHistoryAction extends VersionControlAction {
if (domainFiles.size() != 1) { if (domainFiles.size() != 1) {
return; return;
} }
if (dialog == null) {
dialog = new VersionHistoryDialog(); dialog = new VersionHistoryDialog(domainFiles.get(0));
}
dialog.setDomainFile(domainFiles.get(0));
tool.showDialog(dialog, tool.getToolFrame()); tool.showDialog(dialog, tool.getToolFrame());
} }

View file

@ -56,13 +56,6 @@ public interface Tool extends DockingTool, ToolListener {
*/ */
public void exit(); 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? * Can this tool be closed?
* @param isExiting true if all of Ghidra is closing, false if just this tool is closing. * @param isExiting true if all of Ghidra is closing, false if just this tool is closing.

View file

@ -22,7 +22,6 @@ import java.awt.*;
import java.awt.event.KeyEvent; import java.awt.event.KeyEvent;
import java.beans.PropertyChangeListener; import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport; import java.beans.PropertyChangeSupport;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
@ -34,6 +33,7 @@ import org.jdom.Element;
import docking.*; import docking.*;
import docking.action.*; import docking.action.*;
import docking.actions.PopupActionProvider;
import docking.actions.ToolActions; import docking.actions.ToolActions;
import docking.framework.AboutDialog; import docking.framework.AboutDialog;
import docking.framework.ApplicationInformationDisplayFactory; import docking.framework.ApplicationInformationDisplayFactory;
@ -58,24 +58,24 @@ import ghidra.framework.plugintool.util.*;
import ghidra.framework.project.ProjectDataService; import ghidra.framework.project.ProjectDataService;
import ghidra.framework.project.tool.ToolIconURL; import ghidra.framework.project.tool.ToolIconURL;
import ghidra.util.*; import ghidra.util.*;
import ghidra.util.datastruct.WeakDataStructureFactory;
import ghidra.util.datastruct.WeakSet;
import ghidra.util.task.Task; import ghidra.util.task.Task;
import ghidra.util.task.TaskLauncher; import ghidra.util.task.TaskLauncher;
/** /**
* Base class that is a container to manage plugins and their actions, and * Base class that is a container to manage plugins and their actions, and to coordinate the
* to coordinate the firing of plugin events and tool events. A * firing of plugin events and tool events. A PluginTool may have visible components supplied by
* PluginTool may have visible components supplied by * <pre>ComponentProviders </pre>. These components may be docked within the tool, or moved
* <pre>ComponentProviders </pre>. These components may be docked within the * out into their own windows.
* tool, or moved out into their own windows. *
* <p>The PluginTool also manages tasks that run in the background, and * <p>Plugins normally add actions via {@link #addAction(DockingActionIf)}. There is also
* options used by the plugins. * an alternate method for getting actions to appear in the popup context menu (see
* </p> * {@link #addPopupActionProvider(PopupActionProvider)}). The popup listener mechanism is generally not
* needed and should only be used in special circumstances (see {@link PopupActionProvider}).
*
* <p>The PluginTool also manages tasks that run in the background, and options used by the plugins.
* *
*/ */
public abstract class PluginTool extends AbstractDockingTool public abstract class PluginTool extends AbstractDockingTool implements Tool, ServiceProvider {
implements Tool, DockWinListener, ServiceProvider {
private static final String DOCKING_WINDOWS_ON_TOP = "Docking Windows On Top"; 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 DialogManager dialogMgr;
private PropertyChangeSupport propertyChangeMgr; private PropertyChangeSupport propertyChangeMgr;
private WeakSet<PopupListener> popupListeners =
WeakDataStructureFactory.createSingleThreadAccessWeakSet();
private OptionsChangeListener optionsListener = new ToolOptionsListener(); private OptionsChangeListener optionsListener = new ToolOptionsListener();
protected ManagePluginsDialog manageDialog; protected ManagePluginsDialog manageDialog;
protected ExtensionTableProvider extensionTableProvider; protected ExtensionTableProvider extensionTableProvider;
@ -192,7 +190,7 @@ public abstract class PluginTool extends AbstractDockingTool
List<Image> windowIcons = ApplicationInformationDisplayFactory.getWindowIcons(); List<Image> windowIcons = ApplicationInformationDisplayFactory.getWindowIcons();
DockingWindowManager newManager = DockingWindowManager newManager =
new DockingWindowManager(this, windowIcons, this, isModal, isDockable, hasStatus, null); new DockingWindowManager(this, windowIcons, isModal, isDockable, hasStatus, null);
return newManager; return newManager;
} }
@ -264,17 +262,6 @@ public abstract class PluginTool extends AbstractDockingTool
return winMgr.isWindowsOnTop(); 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 * Returns the manage plugins dialog that is currently
* being used. * being used.
@ -308,15 +295,6 @@ public abstract class PluginTool extends AbstractDockingTool
showDialog(extensionTableProvider); 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 * 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 * 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(); eventMgr.clearLastEvents();
} }
@Override
public List<DockingActionIf> getPopupActions(ActionContext context) {
List<DockingActionIf> actionList = new ArrayList<>();
for (PopupListener pl : popupListeners) {
List<DockingActionIf> actions = pl.getPopupActions(context);
if (actions != null) {
actionList.addAll(actions);
}
}
return actionList;
}
/** /**
* Close this tool: * Close this tool:
* <OL> * <OL>

View file

@ -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;
/**
* <code>PopupListener</code> 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<DockingActionIf> getPopupActions(ActionContext context);
}

View file

@ -84,7 +84,7 @@ public class GhidraTool extends PluginTool {
@Override @Override
protected DockingWindowManager createDockingWindowManager(boolean isDockable, boolean hasStatus, protected DockingWindowManager createDockingWindowManager(boolean isDockable, boolean hasStatus,
boolean isModal) { boolean isModal) {
return new DockingWindowManager(this, null, this, isModal, isDockable, hasStatus, return new DockingWindowManager(this, null, isModal, isDockable, hasStatus,
new OpenFileDropHandlerFactory(this)); new OpenFileDropHandlerFactory(this));
} }

View file

@ -136,9 +136,8 @@ public class VersionControlScreenShots extends GhidraScreenShotGenerator {
@Test @Test
public void testVersionHistory() throws Exception { public void testVersionHistory() throws Exception {
VersionHistoryDialog dialog = new VersionHistoryDialog();
DomainFile df = createDomainFile(); DomainFile df = createDomainFile();
dialog.setDomainFile(df); VersionHistoryDialog dialog = new VersionHistoryDialog(df);
runSwing(() -> tool.showDialog(dialog)); runSwing(() -> tool.showDialog(dialog));
VersionHistoryDialog d = waitForDialogComponent(dialog.getClass()); VersionHistoryDialog d = waitForDialogComponent(dialog.getClass());