mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-05-27 17:55:33 +08:00
GT-2925 - Key Bindings - Support Window Menu Provider Key Bindings -
test and review fixes
This commit is contained in:
+5
-8
@@ -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.
|
||||||
@@ -23,20 +22,18 @@ import ghidra.program.model.address.AddressSetView;
|
|||||||
import ghidra.program.model.listing.Function;
|
import ghidra.program.model.listing.Function;
|
||||||
import ghidra.program.model.listing.FunctionIterator;
|
import ghidra.program.model.listing.FunctionIterator;
|
||||||
|
|
||||||
public class DeleteFunctionDefaultPlates extends GhidraScript {
|
public class DeleteFunctionDefaultPlatesScript extends GhidraScript {
|
||||||
|
|
||||||
private static String DEFAULT_PLATE = " FUNCTION";
|
private static String DEFAULT_PLATE = " FUNCTION";
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see ghidra.app.script.GhidraScript#run()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void run() throws Exception {
|
public void run() throws Exception {
|
||||||
|
|
||||||
AddressSetView set = currentProgram.getMemory();
|
AddressSetView set = currentProgram.getMemory();
|
||||||
if (currentSelection != null && !currentSelection.isEmpty()) {
|
if (currentSelection != null && !currentSelection.isEmpty()) {
|
||||||
set = currentSelection;
|
set = currentSelection;
|
||||||
}
|
}
|
||||||
int updateCount=0;
|
int updateCount = 0;
|
||||||
FunctionIterator iter = currentProgram.getFunctionManager().getFunctions(set, true);
|
FunctionIterator iter = currentProgram.getFunctionManager().getFunctions(set, true);
|
||||||
while (iter.hasNext()) {
|
while (iter.hasNext()) {
|
||||||
Function function = iter.next();
|
Function function = iter.next();
|
||||||
@@ -47,7 +44,7 @@ public class DeleteFunctionDefaultPlates extends GhidraScript {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (updateCount > 0) {
|
if (updateCount > 0) {
|
||||||
String cmt = updateCount > 1? "comments" : "comment";
|
String cmt = updateCount > 1 ? "comments" : "comment";
|
||||||
println("Removed " + updateCount + " default plate " + cmt + ".");
|
println("Removed " + updateCount + " default plate " + cmt + ".");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -148,6 +148,14 @@ public class CallTreePlugin extends ProgramPlugin {
|
|||||||
tool.showComponentProvider(provider, true);
|
tool.showComponentProvider(provider, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CallTreeProvider getPrimaryProvider() {
|
||||||
|
return primaryProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
DockingAction getShowCallTreeFromMenuAction() {
|
||||||
|
return showCallTreeFromMenuAction;
|
||||||
|
}
|
||||||
|
|
||||||
ProgramLocation getCurrentLocation() {
|
ProgramLocation getCurrentLocation() {
|
||||||
return currentLocation;
|
return currentLocation;
|
||||||
}
|
}
|
||||||
|
|||||||
+1
@@ -876,6 +876,7 @@ public class CallTreeProvider extends ComponentProviderAdapter implements Domain
|
|||||||
// changes, which means we will get here while setting the location, but our program
|
// changes, which means we will get here while setting the location, but our program
|
||||||
// will have been null'ed out.
|
// will have been null'ed out.
|
||||||
currentProgram = plugin.getCurrentProgram();
|
currentProgram = plugin.getCurrentProgram();
|
||||||
|
currentProgram.addListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
Function function = plugin.getFunction(location);
|
Function function = plugin.getFunction(location);
|
||||||
|
|||||||
+5
-10
@@ -915,18 +915,13 @@ public class CodeBrowserPlugin extends Plugin
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// note: this action gets added later when the TableService is added
|
||||||
tableFromSelectionAction.setEnabled(false);
|
tableFromSelectionAction.setEnabled(false);
|
||||||
tableFromSelectionAction.setMenuBarData(new MenuData(
|
tableFromSelectionAction.setMenuBarData(new MenuData(
|
||||||
new String[] { ToolConstants.MENU_SELECTION, "Create Table From Selection" }, null,
|
new String[] { ToolConstants.MENU_SELECTION, "Create Table From Selection" }, null,
|
||||||
"SelectUtils"));
|
"SelectUtils"));
|
||||||
tableFromSelectionAction
|
tableFromSelectionAction.setHelpLocation(
|
||||||
.setHelpLocation(new HelpLocation("CodeBrowserPlugin", "Selection_Table"));
|
new HelpLocation("CodeBrowserPlugin", "Selection_Table"));
|
||||||
|
|
||||||
// don't add the actions initially if the service isn't there
|
|
||||||
TableService tableService = tool.getService(TableService.class);
|
|
||||||
if (tableService != null) {
|
|
||||||
tool.addAction(tableFromSelectionAction);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private GhidraProgramTableModel<Address> createTableModel(CodeUnitIterator iterator,
|
private GhidraProgramTableModel<Address> createTableModel(CodeUnitIterator iterator,
|
||||||
@@ -1001,8 +996,8 @@ public class CodeBrowserPlugin extends Plugin
|
|||||||
public boolean goToField(Address a, String fieldName, int occurrence, int row, int col,
|
public boolean goToField(Address a, String fieldName, int occurrence, int row, int col,
|
||||||
boolean scroll) {
|
boolean scroll) {
|
||||||
|
|
||||||
boolean result = SystemUtilities
|
boolean result = SystemUtilities.runSwingNow(
|
||||||
.runSwingNow(() -> doGoToField(a, fieldName, occurrence, row, col, scroll));
|
() -> doGoToField(a, fieldName, occurrence, row, col, scroll));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-33
@@ -36,7 +36,6 @@ import docking.widgets.fieldpanel.FieldPanel;
|
|||||||
import docking.widgets.fieldpanel.HoverHandler;
|
import docking.widgets.fieldpanel.HoverHandler;
|
||||||
import docking.widgets.fieldpanel.internal.FieldPanelCoordinator;
|
import docking.widgets.fieldpanel.internal.FieldPanelCoordinator;
|
||||||
import docking.widgets.fieldpanel.support.*;
|
import docking.widgets.fieldpanel.support.*;
|
||||||
import ghidra.GhidraOptions;
|
|
||||||
import ghidra.app.nav.*;
|
import ghidra.app.nav.*;
|
||||||
import ghidra.app.plugin.core.clipboard.CodeBrowserClipboardProvider;
|
import ghidra.app.plugin.core.clipboard.CodeBrowserClipboardProvider;
|
||||||
import ghidra.app.plugin.core.codebrowser.actions.*;
|
import ghidra.app.plugin.core.codebrowser.actions.*;
|
||||||
@@ -63,8 +62,6 @@ public class CodeViewerProvider extends NavigatableComponentProviderAdapter
|
|||||||
|
|
||||||
private static final String TITLE = "Listing: ";
|
private static final String TITLE = "Listing: ";
|
||||||
|
|
||||||
private static final String OPERAND_OPTIONS_PREFIX = GhidraOptions.OPERAND_GROUP_TITLE + ".";
|
|
||||||
|
|
||||||
private static final Icon LISTING_FORMAT_EXPAND_ICON =
|
private static final Icon LISTING_FORMAT_EXPAND_ICON =
|
||||||
ResourceManager.loadImage("images/field.header.down.png");
|
ResourceManager.loadImage("images/field.header.down.png");
|
||||||
private static final Icon LISTING_FORMAT_COLLAPSE_ICON =
|
private static final Icon LISTING_FORMAT_COLLAPSE_ICON =
|
||||||
@@ -93,9 +90,6 @@ public class CodeViewerProvider extends NavigatableComponentProviderAdapter
|
|||||||
private ProgramDropProvider curDropProvider;
|
private ProgramDropProvider curDropProvider;
|
||||||
private ToggleDockingAction toggleHoverAction;
|
private ToggleDockingAction toggleHoverAction;
|
||||||
|
|
||||||
//TODO - Need to improve CodeUnit.getRepresentation format options interface before adding this
|
|
||||||
//TODO private ToggleOperandMarkupAction[] toggleOperandMarkupActions;
|
|
||||||
|
|
||||||
private ProgramLocation currentLocation;
|
private ProgramLocation currentLocation;
|
||||||
|
|
||||||
private ListingPanel otherPanel;
|
private ListingPanel otherPanel;
|
||||||
@@ -976,9 +970,9 @@ public class CodeViewerProvider extends NavigatableComponentProviderAdapter
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ToggleHoverAction extends ToggleDockingAction {
|
private class ToggleHoverAction extends ToggleDockingAction {
|
||||||
ToggleHoverAction() {
|
ToggleHoverAction() {
|
||||||
super("Toggle Mouse Hover Popups", CodeViewerProvider.this.getName());
|
super("Toggle Mouse Hover Popups", CodeViewerProvider.this.getOwner());
|
||||||
setEnabled(true);
|
setEnabled(true);
|
||||||
setToolBarData(new ToolBarData(HOVER_ON_ICON, "yyyz"));
|
setToolBarData(new ToolBarData(HOVER_ON_ICON, "yyyz"));
|
||||||
setSelected(true);
|
setSelected(true);
|
||||||
@@ -998,31 +992,6 @@ public class CodeViewerProvider extends NavigatableComponentProviderAdapter
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ToggleOperandMarkupAction extends ToggleDockingAction {
|
|
||||||
final String optionName;
|
|
||||||
|
|
||||||
ToggleOperandMarkupAction(String operandOption) {
|
|
||||||
super(operandOption, CodeViewerProvider.this.getName());
|
|
||||||
this.optionName = OPERAND_OPTIONS_PREFIX + operandOption;
|
|
||||||
boolean state =
|
|
||||||
tool.getOptions(GhidraOptions.CATEGORY_BROWSER_FIELDS).getBoolean(optionName, true);
|
|
||||||
setMenuBarData(new MenuData(new String[] { operandOption }));
|
|
||||||
setSelected(state);
|
|
||||||
setEnabled(true);
|
|
||||||
setHelpLocation(new HelpLocation("CodeBrowserPlugin", "Operands_Field"));
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object getOptionName() {
|
|
||||||
return optionName;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void actionPerformed(ActionContext context) {
|
|
||||||
boolean state = isSelected();
|
|
||||||
tool.getOptions(GhidraOptions.CATEGORY_BROWSER_FIELDS).setBoolean(optionName, state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class that allows clients to install transient highlighters while keeping the
|
* A class that allows clients to install transient highlighters while keeping the
|
||||||
* middle-mouse highlighting on at the same time.
|
* middle-mouse highlighting on at the same time.
|
||||||
|
|||||||
+2
-3
@@ -39,7 +39,7 @@ public class CollapseAllDataAction extends ProgramLocationContextAction {
|
|||||||
private CodeViewerProvider provider;
|
private CodeViewerProvider provider;
|
||||||
|
|
||||||
public CollapseAllDataAction(CodeViewerProvider provider) {
|
public CollapseAllDataAction(CodeViewerProvider provider) {
|
||||||
super("Collapse All Data", provider.getName());
|
super("Collapse All Data", provider.getOwner());
|
||||||
this.provider = provider;
|
this.provider = provider;
|
||||||
|
|
||||||
setPopupMenuData(new MenuData(new String[] { "Collapse All Data" }, null, "Structure"));
|
setPopupMenuData(new MenuData(new String[] { "Collapse All Data" }, null, "Structure"));
|
||||||
@@ -95,8 +95,7 @@ public class CollapseAllDataAction extends ProgramLocationContextAction {
|
|||||||
|
|
||||||
ProgramLocation location = context.getLocation();
|
ProgramLocation location = context.getLocation();
|
||||||
Data data = getTopLevelComponentData(location);
|
Data data = getTopLevelComponentData(location);
|
||||||
TaskLauncher.launchModal("Collapse Data",
|
TaskLauncher.launchModal("Collapse Data", monitor -> model.closeAllData(data, monitor));
|
||||||
monitor -> model.closeAllData(data, monitor));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private ListingModel getModel() {
|
private ListingModel getModel() {
|
||||||
|
|||||||
+1
-1
@@ -36,7 +36,7 @@ public class ExpandAllDataAction extends ProgramLocationContextAction {
|
|||||||
private CodeViewerProvider provider;
|
private CodeViewerProvider provider;
|
||||||
|
|
||||||
public ExpandAllDataAction(CodeViewerProvider provider) {
|
public ExpandAllDataAction(CodeViewerProvider provider) {
|
||||||
super("Expand All Data", provider.getName());
|
super("Expand All Data", provider.getOwner());
|
||||||
this.provider = provider;
|
this.provider = provider;
|
||||||
|
|
||||||
setPopupMenuData(new MenuData(new String[] { "Expand All Data" }, null, "Structure"));
|
setPopupMenuData(new MenuData(new String[] { "Expand All Data" }, null, "Structure"));
|
||||||
|
|||||||
+1
-1
@@ -39,7 +39,7 @@ public class ToggleExpandCollapseDataAction extends ProgramLocationContextAction
|
|||||||
private CodeViewerProvider provider;
|
private CodeViewerProvider provider;
|
||||||
|
|
||||||
public ToggleExpandCollapseDataAction(CodeViewerProvider provider) {
|
public ToggleExpandCollapseDataAction(CodeViewerProvider provider) {
|
||||||
super("Toggle Expand/Collapse Data", provider.getName());
|
super("Toggle Expand/Collapse Data", provider.getOwner());
|
||||||
this.provider = provider;
|
this.provider = provider;
|
||||||
|
|
||||||
setPopupMenuData(
|
setPopupMenuData(
|
||||||
|
|||||||
-1
@@ -466,7 +466,6 @@ class GhidraScriptActionManager {
|
|||||||
if (action == null) {
|
if (action == null) {
|
||||||
action = new ScriptAction(plugin, script);
|
action = new ScriptAction(plugin, script);
|
||||||
actionMap.put(script, action);
|
actionMap.put(script, action);
|
||||||
plugin.getTool().addAction(action);
|
|
||||||
}
|
}
|
||||||
return action;
|
return action;
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -347,7 +347,7 @@ public class SymbolTablePlugin extends Plugin implements DomainObjectListener {
|
|||||||
private void createSymActions() {
|
private void createSymActions() {
|
||||||
String popupGroup = "1";
|
String popupGroup = "1";
|
||||||
|
|
||||||
openRefsAction = new DockingAction("Symbol References", getName()) {
|
openRefsAction = new DockingAction("Symbol References", getName(), KeyBindingType.SHARED) {
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionContext context) {
|
public void actionPerformed(ActionContext context) {
|
||||||
refProvider.open();
|
refProvider.open();
|
||||||
@@ -359,7 +359,7 @@ public class SymbolTablePlugin extends Plugin implements DomainObjectListener {
|
|||||||
new MenuData(new String[] { "Symbol References" }, icon, popupGroup));
|
new MenuData(new String[] { "Symbol References" }, icon, popupGroup));
|
||||||
openRefsAction.setToolBarData(new ToolBarData(icon));
|
openRefsAction.setToolBarData(new ToolBarData(icon));
|
||||||
|
|
||||||
openRefsAction.setDescription("Symbol References");
|
openRefsAction.setDescription("Display Symbol References");
|
||||||
tool.addLocalAction(symProvider, openRefsAction);
|
tool.addLocalAction(symProvider, openRefsAction);
|
||||||
|
|
||||||
deleteAction = new DockingAction("Delete Symbols", getName()) {
|
deleteAction = new DockingAction("Delete Symbols", getName()) {
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ public interface PluginConstants {
|
|||||||
*/
|
*/
|
||||||
char ANYSINGLECHAR_WILDCARD_CHAR = '?';
|
char ANYSINGLECHAR_WILDCARD_CHAR = '?';
|
||||||
|
|
||||||
String CODE_BROWSER = "CodeBrowserPlugin";
|
String CODE_BROWSER = "Listing";
|
||||||
String MEMORY_MAP = "Memory Map";
|
String MEMORY_MAP = "Memory Map";
|
||||||
String BYTE_VIEWER = "ByteViewerPlugin";
|
String BYTE_VIEWER = "ByteViewerPlugin";
|
||||||
String BOOKMARKS = "Bookmarks";
|
String BOOKMARKS = "Bookmarks";
|
||||||
|
|||||||
@@ -159,6 +159,25 @@ public class ComponentProviderActionsTest extends AbstractGhidraHeadedIntegratio
|
|||||||
assertMenuItemHasKeyStroke(newKs);
|
assertMenuItemHasKeyStroke(newKs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSetKeyBinding_ViaDialog_FromWindowMenu_ToAlreadyBoundAction() {
|
||||||
|
|
||||||
|
//
|
||||||
|
// Test the conflicting key binding use case
|
||||||
|
//
|
||||||
|
|
||||||
|
HasDefaultKeyBindingComponentProvider otherProvider =
|
||||||
|
new HasDefaultKeyBindingComponentProvider(tool);
|
||||||
|
otherProvider.setVisible(true);
|
||||||
|
|
||||||
|
showProvider();
|
||||||
|
|
||||||
|
KeyStroke newKs = CONTROL_T;
|
||||||
|
applyBindingToDialog_FromWindowsMenu(newKs);
|
||||||
|
|
||||||
|
assertCollisionsWithKeyStroke();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSetKeyBinding_ViaOptions_WithoutToolbarAction() {
|
public void testSetKeyBinding_ViaOptions_WithoutToolbarAction() {
|
||||||
|
|
||||||
@@ -235,6 +254,14 @@ public class ComponentProviderActionsTest extends AbstractGhidraHeadedIntegratio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDefaultKeyBindingAppearsInWindowMenu() {
|
||||||
|
|
||||||
|
provider.setDefaultKeyBinding(new KeyBindingData(CONTROL_T));
|
||||||
|
showProvider();
|
||||||
|
assertWindowMenuActionHasKeyBinding(CONTROL_T);
|
||||||
|
}
|
||||||
|
|
||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
// Private Methods
|
// Private Methods
|
||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
@@ -279,7 +306,7 @@ public class ComponentProviderActionsTest extends AbstractGhidraHeadedIntegratio
|
|||||||
.stream()
|
.stream()
|
||||||
.filter(a -> a.getOwner().equals(DockingWindowManager.DOCKING_WINDOWS_OWNER))
|
.filter(a -> a.getOwner().equals(DockingWindowManager.DOCKING_WINDOWS_OWNER))
|
||||||
.findFirst()
|
.findFirst()
|
||||||
.get()
|
.orElseGet(() -> null)
|
||||||
;
|
;
|
||||||
//@formatter:on
|
//@formatter:on
|
||||||
});
|
});
|
||||||
@@ -310,7 +337,7 @@ public class ComponentProviderActionsTest extends AbstractGhidraHeadedIntegratio
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void assertNoToolbarAction() {
|
private void assertNoToolbarAction() {
|
||||||
assertNotNull("No toolbar action found for provider", getToolbarShowProviderAction());
|
assertNull("No toolbar action found for provider", getToolbarShowProviderAction());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertToolbarAction() {
|
private void assertToolbarAction() {
|
||||||
@@ -341,6 +368,13 @@ public class ComponentProviderActionsTest extends AbstractGhidraHeadedIntegratio
|
|||||||
expected, action.getMenuBarData().getMenuIcon());
|
expected, action.getMenuBarData().getMenuIcon());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void assertWindowMenuActionHasKeyBinding(KeyStroke ks) {
|
||||||
|
DockingActionIf action = getWindowMenuShowProviderAction();
|
||||||
|
assertEquals(
|
||||||
|
"Windows menu key bindings for provider does not match the value set on the provider",
|
||||||
|
ks, action.getKeyBinding());
|
||||||
|
}
|
||||||
|
|
||||||
private void assertCannotShowKeyBindingDialog_FromWindowsMenu() {
|
private void assertCannotShowKeyBindingDialog_FromWindowsMenu() {
|
||||||
// simulate the user mousing over the 'Window' menu's action
|
// simulate the user mousing over the 'Window' menu's action
|
||||||
DockingActionIf windowMenuAction = getWindowMenuShowProviderAction();
|
DockingActionIf windowMenuAction = getWindowMenuShowProviderAction();
|
||||||
@@ -367,6 +401,24 @@ public class ComponentProviderActionsTest extends AbstractGhidraHeadedIntegratio
|
|||||||
assertFalse("Invalid key stroke: " + ks, runSwing(() -> dialog.isVisible()));
|
assertFalse("Invalid key stroke: " + ks, runSwing(() -> dialog.isVisible()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void applyBindingToDialog_FromWindowsMenu(KeyStroke ks) {
|
||||||
|
DockingActionIf windowMenuAction = getWindowMenuShowProviderAction();
|
||||||
|
DockingWindowManager.setMouseOverAction(windowMenuAction);
|
||||||
|
|
||||||
|
performLaunchKeyStrokeDialogAction();
|
||||||
|
KeyEntryDialog dialog = waitForDialogComponent(KeyEntryDialog.class);
|
||||||
|
|
||||||
|
runSwing(() -> dialog.setKeyStroke(ks));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertCollisionsWithKeyStroke() {
|
||||||
|
KeyEntryDialog dialog = waitForDialogComponent(KeyEntryDialog.class);
|
||||||
|
|
||||||
|
JTextPane collisionPane = (JTextPane) getInstanceField("collisionPane", dialog);
|
||||||
|
String collisionText = runSwing(() -> collisionPane.getText());
|
||||||
|
assertTrue(collisionText.contains("Actions mapped to"));
|
||||||
|
}
|
||||||
|
|
||||||
private void assertMenuItemHasKeyStroke(KeyStroke expected) {
|
private void assertMenuItemHasKeyStroke(KeyStroke expected) {
|
||||||
|
|
||||||
DockingActionIf action = getWindowMenuShowProviderAction();
|
DockingActionIf action = getWindowMenuShowProviderAction();
|
||||||
@@ -415,6 +467,21 @@ public class ComponentProviderActionsTest extends AbstractGhidraHeadedIntegratio
|
|||||||
public JComponent getComponent() {
|
public JComponent getComponent() {
|
||||||
return component;
|
return component;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class HasDefaultKeyBindingComponentProvider extends ComponentProvider {
|
||||||
|
private JComponent component = new JTextField("Hey!");
|
||||||
|
|
||||||
|
HasDefaultKeyBindingComponentProvider(DockingTool tool) {
|
||||||
|
super(tool, HasDefaultKeyBindingComponentProvider.class.getSimpleName(),
|
||||||
|
"Fooberry Plugin");
|
||||||
|
|
||||||
|
setDefaultKeyBinding(new KeyBindingData(CONTROL_T));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JComponent getComponent() {
|
||||||
|
return component;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package docking.action;
|
|||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
import java.awt.event.KeyEvent;
|
import java.awt.event.KeyEvent;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
|
||||||
@@ -25,6 +26,7 @@ import org.junit.*;
|
|||||||
|
|
||||||
import docking.*;
|
import docking.*;
|
||||||
import docking.actions.KeyEntryDialog;
|
import docking.actions.KeyEntryDialog;
|
||||||
|
import docking.actions.ToolActions;
|
||||||
import ghidra.app.plugin.core.codebrowser.CodeBrowserPlugin;
|
import ghidra.app.plugin.core.codebrowser.CodeBrowserPlugin;
|
||||||
import ghidra.app.plugin.core.data.DataPlugin;
|
import ghidra.app.plugin.core.data.DataPlugin;
|
||||||
import ghidra.app.plugin.core.function.FunctionPlugin;
|
import ghidra.app.plugin.core.function.FunctionPlugin;
|
||||||
@@ -186,20 +188,26 @@ public class KeyEntryDialogTest extends AbstractGhidraHeadedIntegrationTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public DockingAction getKeyBindingAction() {
|
public DockingAction getKeyBindingAction() {
|
||||||
DockingWindowManager dwm = DockingWindowManager.getInstance(tool.getToolFrame());
|
|
||||||
ActionToGuiMapper dockingActionManager =
|
ToolActions toolActions = tool.getToolActions();
|
||||||
(ActionToGuiMapper) getInstanceField("actionManager", dwm);
|
KeyBindingsManager kbm =
|
||||||
return (DockingAction) getInstanceField("keyBindingsAction", dockingActionManager);
|
(KeyBindingsManager) getInstanceField("keyBindingsManager", toolActions);
|
||||||
|
Map<KeyStroke, DockingKeyBindingAction> dockingKeyMap =
|
||||||
|
(Map<KeyStroke, DockingKeyBindingAction>) getInstanceField("dockingKeyMap", kbm);
|
||||||
|
KeyStroke ks = KeyStroke.getKeyStroke(KeyEvent.VK_F4, 0);
|
||||||
|
DockingKeyBindingAction dockingAction = dockingKeyMap.get(ks);
|
||||||
|
DockingAction f4Action = (DockingAction) getInstanceField("docakbleAction", dockingAction);
|
||||||
|
return f4Action;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showDialog(final DockingAction actionToEdit) throws Exception {
|
private void showDialog(final DockingAction actionToEdit) throws Exception {
|
||||||
final DockingAction keyBindingAction = getKeyBindingAction();
|
DockingAction keyBindingAction = getKeyBindingAction();
|
||||||
executeOnSwingWithoutBlocking(() -> {
|
executeOnSwingWithoutBlocking(() -> {
|
||||||
DockingWindowManager.setMouseOverAction(actionToEdit);
|
DockingWindowManager.setMouseOverAction(actionToEdit);
|
||||||
performAction(keyBindingAction, false);
|
performAction(keyBindingAction, false);
|
||||||
});
|
});
|
||||||
|
|
||||||
keyEntryDialog = waitForDialogComponent(tool.getToolFrame(), KeyEntryDialog.class, 2000);
|
keyEntryDialog = waitForDialogComponent(KeyEntryDialog.class);
|
||||||
assertNotNull(keyEntryDialog);
|
assertNotNull(keyEntryDialog);
|
||||||
|
|
||||||
collisionPane = (JTextPane) getInstanceField("collisionPane", keyEntryDialog);
|
collisionPane = (JTextPane) getInstanceField("collisionPane", keyEntryDialog);
|
||||||
|
|||||||
+1
-1
@@ -718,7 +718,7 @@ public class BookmarkPluginTest extends AbstractGhidraHeadedIntegrationTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void showBookmarkProvider() throws Exception {
|
private void showBookmarkProvider() throws Exception {
|
||||||
DockingActionIf action = getAction(plugin, "Show Bookmarks");
|
DockingActionIf action = getAction(plugin, "Bookmarks");
|
||||||
performAction(action, true);
|
performAction(action, true);
|
||||||
table = plugin.getBookmarkTable();
|
table = plugin.getBookmarkTable();
|
||||||
waitForTable();
|
waitForTable();
|
||||||
|
|||||||
+18
-51
@@ -46,7 +46,6 @@ import ghidra.framework.plugintool.PluginTool;
|
|||||||
import ghidra.program.database.ProgramBuilder;
|
import ghidra.program.database.ProgramBuilder;
|
||||||
import ghidra.program.database.ProgramDB;
|
import ghidra.program.database.ProgramDB;
|
||||||
import ghidra.program.model.address.Address;
|
import ghidra.program.model.address.Address;
|
||||||
import ghidra.program.model.address.AddressFactory;
|
|
||||||
import ghidra.program.model.data.DataType;
|
import ghidra.program.model.data.DataType;
|
||||||
import ghidra.program.model.data.PointerDataType;
|
import ghidra.program.model.data.PointerDataType;
|
||||||
import ghidra.program.model.listing.Function;
|
import ghidra.program.model.listing.Function;
|
||||||
@@ -62,7 +61,6 @@ public class CallTreePluginTest extends AbstractGhidraHeadedIntegrationTest {
|
|||||||
private TestEnv env;
|
private TestEnv env;
|
||||||
private CodeBrowserPlugin codeBrowserPlugin;
|
private CodeBrowserPlugin codeBrowserPlugin;
|
||||||
private PluginTool tool;
|
private PluginTool tool;
|
||||||
private ProgramDB program;
|
|
||||||
private CallTreePlugin callTreePlugin;
|
private CallTreePlugin callTreePlugin;
|
||||||
private CallTreeProvider provider;
|
private CallTreeProvider provider;
|
||||||
private List<CallTreeProvider> providers;
|
private List<CallTreeProvider> providers;
|
||||||
@@ -70,14 +68,10 @@ public class CallTreePluginTest extends AbstractGhidraHeadedIntegrationTest {
|
|||||||
private GTree incomingTree;
|
private GTree incomingTree;
|
||||||
private GTree outgoingTree;
|
private GTree outgoingTree;
|
||||||
|
|
||||||
private DockingAction showProviderAction;
|
private ProgramBuilder builder;
|
||||||
|
private ProgramDB program;
|
||||||
|
|
||||||
private GoToService goToService;
|
private GoToService goToService;
|
||||||
private AddressFactory addressFactory;
|
|
||||||
|
|
||||||
public CallTreePluginTest() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
// cast to list
|
// cast to list
|
||||||
@@ -91,7 +85,6 @@ public class CallTreePluginTest extends AbstractGhidraHeadedIntegrationTest {
|
|||||||
|
|
||||||
callTreePlugin = env.getPlugin(CallTreePlugin.class);
|
callTreePlugin = env.getPlugin(CallTreePlugin.class);
|
||||||
providers = (List<CallTreeProvider>) getInstanceField("providers", callTreePlugin);
|
providers = (List<CallTreeProvider>) getInstanceField("providers", callTreePlugin);
|
||||||
showProviderAction = (DockingAction) getInstanceField("showProviderAction", callTreePlugin);
|
|
||||||
|
|
||||||
GoToServicePlugin goToPlugin = env.getPlugin(GoToServicePlugin.class);
|
GoToServicePlugin goToPlugin = env.getPlugin(GoToServicePlugin.class);
|
||||||
goToService = (GoToService) invokeInstanceMethod("getGotoService", goToPlugin);
|
goToService = (GoToService) invokeInstanceMethod("getGotoService", goToPlugin);
|
||||||
@@ -100,20 +93,18 @@ public class CallTreePluginTest extends AbstractGhidraHeadedIntegrationTest {
|
|||||||
env.showTool();
|
env.showTool();
|
||||||
|
|
||||||
program = createProgram();
|
program = createProgram();
|
||||||
addressFactory = program.getAddressFactory();
|
|
||||||
ProgramManager pm = tool.getService(ProgramManager.class);
|
ProgramManager pm = tool.getService(ProgramManager.class);
|
||||||
pm.openProgram(program.getDomainFile());
|
pm.openProgram(program.getDomainFile());
|
||||||
|
|
||||||
// setup a good start location
|
// setup a good start location
|
||||||
goTo(addr("5000"));
|
goTo(addr("5000"));
|
||||||
|
|
||||||
provider = getProvider();
|
provider = callTreePlugin.getPrimaryProvider();
|
||||||
|
tool.showComponentProvider(provider, true);
|
||||||
incomingTree = (GTree) getInstanceField("incomingTree", provider);
|
incomingTree = (GTree) getInstanceField("incomingTree", provider);
|
||||||
outgoingTree = (GTree) getInstanceField("outgoingTree", provider);
|
outgoingTree = (GTree) getInstanceField("outgoingTree", provider);
|
||||||
}
|
}
|
||||||
|
|
||||||
ProgramBuilder builder;
|
|
||||||
|
|
||||||
private ProgramDB createProgram() throws Exception {
|
private ProgramDB createProgram() throws Exception {
|
||||||
|
|
||||||
builder = new ProgramBuilder("Call Trees", ProgramBuilder._TOY);
|
builder = new ProgramBuilder("Call Trees", ProgramBuilder._TOY);
|
||||||
@@ -385,21 +376,21 @@ public class CallTreePluginTest extends AbstractGhidraHeadedIntegrationTest {
|
|||||||
assertNotNull("Provider did not update its information when made visible",
|
assertNotNull("Provider did not update its information when made visible",
|
||||||
providerFunction());
|
providerFunction());
|
||||||
|
|
||||||
final ToggleDockingAction navigateIncomingLoctionsAction =
|
ToggleDockingAction navigateIncomingLoctionsAction =
|
||||||
(ToggleDockingAction) getAction("Navigation Incoming Location Changes");
|
(ToggleDockingAction) getAction("Navigation Incoming Location Changes");
|
||||||
assertTrue(!navigateIncomingLoctionsAction.isSelected());
|
setToggleActionSelected(navigateIncomingLoctionsAction, provider.getActionContext(null),
|
||||||
|
false);
|
||||||
|
|
||||||
assertEquals("Provider's location does not match that of the listing.", currentFunction(),
|
assertEquals("Provider's location does not match that of the listing.", currentFunction(),
|
||||||
providerFunction());
|
providerFunction());
|
||||||
|
|
||||||
goTo(addr("0x6000"));
|
goTo(addr("0x6000"));
|
||||||
|
|
||||||
assertTrue("Provider's location matches that of the listing when not following " +
|
assertNotEquals("Provider's location matches that of the listing when not following " +
|
||||||
"location changes.", !currentFunction().equals(providerFunction()));
|
"location changes", currentFunction(), providerFunction());
|
||||||
|
|
||||||
performAction(navigateIncomingLoctionsAction, true);
|
performAction(navigateIncomingLoctionsAction, true);
|
||||||
|
|
||||||
assertEquals("Provider's location does not match that of the listing.", currentFunction(),
|
assertEquals("Provider's location does not match that of the listing", currentFunction(),
|
||||||
providerFunction());
|
providerFunction());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -779,21 +770,6 @@ public class CallTreePluginTest extends AbstractGhidraHeadedIntegrationTest {
|
|||||||
return functionManager.getFunctionAt(address);
|
return functionManager.getFunctionAt(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
private CallTreeProvider getProvider() {
|
|
||||||
final AtomicReference<CallTreeProvider> ref = new AtomicReference<>();
|
|
||||||
|
|
||||||
// run in swing, as two threads are accessing/manipulating a variable
|
|
||||||
runSwing(() -> {
|
|
||||||
if (providers.size() == 0) {
|
|
||||||
ref.set(showProvider());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ref.set(providers.get(0));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return ref.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
private CallTreeProvider getProvider(final String address) {
|
private CallTreeProvider getProvider(final String address) {
|
||||||
final CallTreeProvider[] providerBox = new CallTreeProvider[1];
|
final CallTreeProvider[] providerBox = new CallTreeProvider[1];
|
||||||
|
|
||||||
@@ -939,13 +915,13 @@ public class CallTreePluginTest extends AbstractGhidraHeadedIntegrationTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void fullyExpandIncomingNode(GTreeNode node) {
|
private void fullyExpandIncomingNode(GTreeNode node) {
|
||||||
DockingActionIf expandAction = getAction(callTreePlugin, "Fully Expand Selected Nodes");
|
DockingActionIf expandAction = getLocalAction(provider, "Fully Expand Selected Nodes");
|
||||||
performAction(expandAction, new ActionContext(provider, incomingTree), false);
|
performAction(expandAction, new ActionContext(provider, incomingTree), false);
|
||||||
waitForTree(node.getTree());
|
waitForTree(node.getTree());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void fullyExpandOutgoingNode(GTreeNode node) {
|
private void fullyExpandOutgoingNode(GTreeNode node) {
|
||||||
DockingActionIf expandAction = getAction(callTreePlugin, "Fully Expand Selected Nodes");
|
DockingActionIf expandAction = getLocalAction(provider, "Fully Expand Selected Nodes");
|
||||||
performAction(expandAction, new ActionContext(provider, outgoingTree), false);
|
performAction(expandAction, new ActionContext(provider, outgoingTree), false);
|
||||||
waitForTree(node.getTree());
|
waitForTree(node.getTree());
|
||||||
}
|
}
|
||||||
@@ -1054,11 +1030,11 @@ public class CallTreePluginTest extends AbstractGhidraHeadedIntegrationTest {
|
|||||||
String name = child.getName();
|
String name = child.getName();
|
||||||
Integer integer = map.get(name);
|
Integer integer = map.get(name);
|
||||||
if (integer == null) {
|
if (integer == null) {
|
||||||
integer = new Integer(0);
|
integer = 0;
|
||||||
}
|
}
|
||||||
int asInt = integer;
|
int asInt = integer;
|
||||||
asInt++;
|
asInt++;
|
||||||
map.put(name, new Integer(asInt));
|
map.put(name, asInt);
|
||||||
}
|
}
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
@@ -1088,10 +1064,7 @@ public class CallTreePluginTest extends AbstractGhidraHeadedIntegrationTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private DockingActionIf getAction(String actionName) {
|
private DockingActionIf getAction(String actionName) {
|
||||||
// make sure there is a provider from which to get actions
|
DockingActionIf action = getLocalAction(provider, actionName);
|
||||||
getProvider();
|
|
||||||
|
|
||||||
DockingActionIf action = getAction(tool, "CallTreePlugin", actionName);
|
|
||||||
return action;
|
return action;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1121,20 +1094,14 @@ public class CallTreePluginTest extends AbstractGhidraHeadedIntegrationTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Shows and returns a provider for the current address.
|
|
||||||
*/
|
|
||||||
private CallTreeProvider showProvider() {
|
|
||||||
performAction(showProviderAction, true);
|
|
||||||
return getProvider();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shows and returns a provider for the specified address.
|
* Shows and returns a provider for the specified address.
|
||||||
*/
|
*/
|
||||||
private CallTreeProvider showProvider(String address) {
|
private CallTreeProvider showProvider(String address) {
|
||||||
goTo(addr(address));
|
goTo(addr(address));
|
||||||
performAction(showProviderAction, true);
|
|
||||||
|
DockingAction action = callTreePlugin.getShowCallTreeFromMenuAction();
|
||||||
|
performAction(action);
|
||||||
return getProvider(address);
|
return getProvider(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+6
@@ -61,6 +61,9 @@ public class CodeBrowserScreenMovementTest extends AbstractProgramBasedTest {
|
|||||||
@Before
|
@Before
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
|
|
||||||
|
// warning: this test is sensitive to size and layout of the visible component providers;
|
||||||
|
// any layout changes may affect the values being tested below
|
||||||
|
|
||||||
initialize();
|
initialize();
|
||||||
|
|
||||||
fp = codeBrowser.getFieldPanel();
|
fp = codeBrowser.getFieldPanel();
|
||||||
@@ -115,6 +118,9 @@ public class CodeBrowserScreenMovementTest extends AbstractProgramBasedTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testBasicControls() throws Exception {
|
public void testBasicControls() throws Exception {
|
||||||
|
|
||||||
|
// warning: this test is sensitive to size and layout of the visible component providers;
|
||||||
|
// any layout changes may affect the values being tested below
|
||||||
|
|
||||||
fp = codeBrowser.getFieldPanel();
|
fp = codeBrowser.getFieldPanel();
|
||||||
ListingPanel panel = codeBrowser.getListingPanel();
|
ListingPanel panel = codeBrowser.getListingPanel();
|
||||||
JScrollBar scrollbar = panel.getVerticalScrollBar();
|
JScrollBar scrollbar = panel.getVerticalScrollBar();
|
||||||
|
|||||||
+1
-1
@@ -68,7 +68,7 @@ public class ExpandCollapseDataActionsTest extends AbstractGhidraHeadedIntegrati
|
|||||||
pm.openProgram(program.getDomainFile());
|
pm.openProgram(program.getDomainFile());
|
||||||
addrFactory = program.getAddressFactory();
|
addrFactory = program.getAddressFactory();
|
||||||
env.showTool();
|
env.showTool();
|
||||||
provider = (CodeViewerProvider) tool.getComponentProvider("CodeBrowserPlugin");
|
provider = (CodeViewerProvider) tool.getComponentProvider("Listing");
|
||||||
listingModel = provider.getListingPanel().getListingModel();
|
listingModel = provider.getListingPanel().getListingModel();
|
||||||
CodeBrowserPlugin plugin = getPlugin(tool, CodeBrowserPlugin.class);
|
CodeBrowserPlugin plugin = getPlugin(tool, CodeBrowserPlugin.class);
|
||||||
toggleExpand = getAction(plugin, "Toggle Expand/Collapse Data");
|
toggleExpand = getAction(plugin, "Toggle Expand/Collapse Data");
|
||||||
|
|||||||
+1
-1
@@ -62,7 +62,7 @@ public class StructureEditorArchiveTest extends AbstractStructureEditorTest {
|
|||||||
tool.addPlugin(DataTypeManagerPlugin.class.getName());
|
tool.addPlugin(DataTypeManagerPlugin.class.getName());
|
||||||
dtmService = tool.getService(DataTypeManagerService.class);
|
dtmService = tool.getService(DataTypeManagerService.class);
|
||||||
plugin = (DataTypeManagerPlugin) dtmService;
|
plugin = (DataTypeManagerPlugin) dtmService;
|
||||||
manageDts = getAction(plugin, "Data Type Manager");
|
manageDts = getAction(plugin, "DataTypes Provider");
|
||||||
DataTypesProvider dataTypesProvider = plugin.getProvider();
|
DataTypesProvider dataTypesProvider = plugin.getProvider();
|
||||||
dtTree = dataTypesProvider.getGTree();
|
dtTree = dataTypesProvider.getGTree();
|
||||||
|
|
||||||
|
|||||||
+2
-11
@@ -55,14 +55,6 @@ public class ArchiveRemappedHeadedTest extends AbstractGhidraHeadedIntegrationTe
|
|||||||
private File vs12ArchiveFile;
|
private File vs12ArchiveFile;
|
||||||
private File vs9ArchiveFile;
|
private File vs9ArchiveFile;
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor for ArchiveRemappedTest.
|
|
||||||
* @param testName
|
|
||||||
*/
|
|
||||||
public ArchiveRemappedHeadedTest() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
|
|
||||||
@@ -97,10 +89,9 @@ public class ArchiveRemappedHeadedTest extends AbstractGhidraHeadedIntegrationTe
|
|||||||
|
|
||||||
env.showTool();
|
env.showTool();
|
||||||
|
|
||||||
tool.showComponentProvider(provider, true);
|
|
||||||
waitForPostedSwingRunnables();
|
|
||||||
|
|
||||||
provider = plugin.getProvider();
|
provider = plugin.getProvider();
|
||||||
|
tool.showComponentProvider(provider, true);
|
||||||
|
|
||||||
tree = provider.getGTree();
|
tree = provider.getGTree();
|
||||||
waitForTree(tree);
|
waitForTree(tree);
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-4
@@ -87,7 +87,7 @@ public class MemoryMapPluginTest extends AbstractGhidraHeadedIntegrationTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testActionEnabled() {
|
public void testActionEnabled() {
|
||||||
DockingActionIf action = getAction(plugin, "View Memory Map");
|
DockingActionIf action = getAction(plugin, "Memory Map");
|
||||||
assertTrue(action.isEnabled());
|
assertTrue(action.isEnabled());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,7 +99,7 @@ public class MemoryMapPluginTest extends AbstractGhidraHeadedIntegrationTest {
|
|||||||
Set<DockingActionIf> actions = getActionsByOwner(tool, plugin.getName());
|
Set<DockingActionIf> actions = getActionsByOwner(tool, plugin.getName());
|
||||||
for (DockingActionIf action : actions) {
|
for (DockingActionIf action : actions) {
|
||||||
if (action.getName().equals("Add Block") || action.getName().equals("Set Image Base") ||
|
if (action.getName().equals("Add Block") || action.getName().equals("Set Image Base") ||
|
||||||
action.getName().equals("View Memory Map")) {
|
action.getName().equals("Memory Map")) {
|
||||||
assertTrue(action.isEnabledForContext(provider.getActionContext(null)));
|
assertTrue(action.isEnabledForContext(provider.getActionContext(null)));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -116,7 +116,7 @@ public class MemoryMapPluginTest extends AbstractGhidraHeadedIntegrationTest {
|
|||||||
assertEquals(0, table.getModel().getRowCount());
|
assertEquals(0, table.getModel().getRowCount());
|
||||||
Set<DockingActionIf> actions = getActionsByOwner(tool, plugin.getName());
|
Set<DockingActionIf> actions = getActionsByOwner(tool, plugin.getName());
|
||||||
for (DockingActionIf action : actions) {
|
for (DockingActionIf action : actions) {
|
||||||
if (!action.getName().equals("View Memory Map")) {
|
if (!action.getName().equals("Memory Map")) {
|
||||||
assertTrue(!action.isEnabledForContext(provider.getActionContext(null)));
|
assertTrue(!action.isEnabledForContext(provider.getActionContext(null)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -297,7 +297,7 @@ public class MemoryMapPluginTest extends AbstractGhidraHeadedIntegrationTest {
|
|||||||
/////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
private void showProvider() {
|
private void showProvider() {
|
||||||
DockingActionIf action = getAction(plugin, "View Memory Map");
|
DockingActionIf action = getAction(plugin, "Memory Map");
|
||||||
performAction(action, true);
|
performAction(action, true);
|
||||||
provider = plugin.getMemoryMapProvider();
|
provider = plugin.getMemoryMapProvider();
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -137,7 +137,7 @@ public class MemoryMapProvider1Test extends AbstractGhidraHeadedIntegrationTest
|
|||||||
String name = action.getName();
|
String name = action.getName();
|
||||||
if (name.equals("Add Block") || name.equals("Merge Blocks") ||
|
if (name.equals("Add Block") || name.equals("Merge Blocks") ||
|
||||||
name.equals("Delete Block") || name.equals("Set Image Base") ||
|
name.equals("Delete Block") || name.equals("Set Image Base") ||
|
||||||
name.equals("View Memory Map")) {
|
name.equals("Memory Map")) {
|
||||||
assertTrue(action.isEnabled());
|
assertTrue(action.isEnabled());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -667,7 +667,7 @@ public class MemoryMapProvider1Test extends AbstractGhidraHeadedIntegrationTest
|
|||||||
/////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
private void showProvider() {
|
private void showProvider() {
|
||||||
DockingActionIf action = getAction(plugin, "View Memory Map");
|
DockingActionIf action = getAction(plugin, "Memory Map");
|
||||||
performAction(action, true);
|
performAction(action, true);
|
||||||
waitForPostedSwingRunnables();
|
waitForPostedSwingRunnables();
|
||||||
provider = plugin.getMemoryMapProvider();
|
provider = plugin.getMemoryMapProvider();
|
||||||
|
|||||||
+1
-1
@@ -1332,7 +1332,7 @@ public class MemoryMapProvider2Test extends AbstractGhidraHeadedIntegrationTest
|
|||||||
///////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
private void showProvider() {
|
private void showProvider() {
|
||||||
DockingActionIf action = getAction(plugin, "View Memory Map");
|
DockingActionIf action = getAction(plugin, "Memory Map");
|
||||||
performAction(action, true);
|
performAction(action, true);
|
||||||
provider = plugin.getMemoryMapProvider();
|
provider = plugin.getMemoryMapProvider();
|
||||||
table = provider.getTable();
|
table = provider.getTable();
|
||||||
|
|||||||
+1
-1
@@ -886,7 +886,7 @@ public class MemoryMapProvider3Test extends AbstractGhidraHeadedIntegrationTest
|
|||||||
///////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
private void showProvider() {
|
private void showProvider() {
|
||||||
DockingActionIf action = getAction(plugin, "View Memory Map");
|
DockingActionIf action = getAction(plugin, "Memory Map");
|
||||||
performAction(action, true);
|
performAction(action, true);
|
||||||
waitForPostedSwingRunnables();
|
waitForPostedSwingRunnables();
|
||||||
provider = plugin.getMemoryMapProvider();
|
provider = plugin.getMemoryMapProvider();
|
||||||
|
|||||||
+1
-5
@@ -54,10 +54,6 @@ public class MemoryMapProvider4Test extends AbstractGhidraHeadedIntegrationTest
|
|||||||
private JTable table;
|
private JTable table;
|
||||||
private TableModel model;
|
private TableModel model;
|
||||||
|
|
||||||
public MemoryMapProvider4Test() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
private Program buildProgram(String programName) throws Exception {
|
private Program buildProgram(String programName) throws Exception {
|
||||||
ProgramBuilder builder = new ProgramBuilder(programName, ProgramBuilder._TOY);
|
ProgramBuilder builder = new ProgramBuilder(programName, ProgramBuilder._TOY);
|
||||||
builder.createMemory(".text", Long.toHexString(0x1001000), 0x6600);
|
builder.createMemory(".text", Long.toHexString(0x1001000), 0x6600);
|
||||||
@@ -247,7 +243,7 @@ public class MemoryMapProvider4Test extends AbstractGhidraHeadedIntegrationTest
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void showProvider() {
|
private void showProvider() {
|
||||||
DockingActionIf action = getAction(plugin, "View Memory Map");
|
DockingActionIf action = getAction(plugin, "Memory Map");
|
||||||
performAction(action, true);
|
performAction(action, true);
|
||||||
waitForPostedSwingRunnables();
|
waitForPostedSwingRunnables();
|
||||||
provider = plugin.getMemoryMapProvider();
|
provider = plugin.getMemoryMapProvider();
|
||||||
|
|||||||
+3
-4
@@ -71,8 +71,7 @@ public class NextPrevAddressPluginTest extends AbstractGhidraHeadedIntegrationTe
|
|||||||
NextPrevAddressPlugin plugin = env.getPlugin(NextPrevAddressPlugin.class);
|
NextPrevAddressPlugin plugin = env.getPlugin(NextPrevAddressPlugin.class);
|
||||||
previousAction =
|
previousAction =
|
||||||
(MultiActionDockingAction) TestUtils.getInstanceField("previousAction", plugin);
|
(MultiActionDockingAction) TestUtils.getInstanceField("previousAction", plugin);
|
||||||
nextAction =
|
nextAction = (MultiActionDockingAction) TestUtils.getInstanceField("nextAction", plugin);
|
||||||
(MultiActionDockingAction) TestUtils.getInstanceField("nextAction", plugin);
|
|
||||||
|
|
||||||
GoToAddressLabelPlugin goToPlugin = env.getPlugin(GoToAddressLabelPlugin.class);
|
GoToAddressLabelPlugin goToPlugin = env.getPlugin(GoToAddressLabelPlugin.class);
|
||||||
dialog = goToPlugin.getDialog();
|
dialog = goToPlugin.getDialog();
|
||||||
@@ -355,9 +354,9 @@ public class NextPrevAddressPluginTest extends AbstractGhidraHeadedIntegrationTe
|
|||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
// let caution fly
|
// let caution fly
|
||||||
private JButton findButtonForAction(DockingWindowManager windowManager, DockingAction action) {
|
private JButton findButtonForAction(DockingWindowManager windowManager, DockingAction action) {
|
||||||
Object actionManager = TestUtils.getInstanceField("actionManager", windowManager);
|
Object actionToGuiMapper = TestUtils.getInstanceField("actionToGuiMapper", windowManager);
|
||||||
Object menuAndToolBarManager =
|
Object menuAndToolBarManager =
|
||||||
TestUtils.getInstanceField("menuAndToolBarManager", actionManager);
|
TestUtils.getInstanceField("menuAndToolBarManager", actionToGuiMapper);
|
||||||
Map<WindowNode, WindowActionManager> map =
|
Map<WindowNode, WindowActionManager> map =
|
||||||
(Map<WindowNode, WindowActionManager>) TestUtils.getInstanceField(
|
(Map<WindowNode, WindowActionManager>) TestUtils.getInstanceField(
|
||||||
"windowToActionManagerMap", menuAndToolBarManager);
|
"windowToActionManagerMap", menuAndToolBarManager);
|
||||||
|
|||||||
+3
-19
@@ -37,12 +37,9 @@ import ghidra.program.util.ProgramSelection;
|
|||||||
import ghidra.test.*;
|
import ghidra.test.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test for deleting default plate comments on a function.
|
* Test for deleting default plate comments on a function
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public class DeleteFunctionDefaultPlatesTest extends AbstractGhidraHeadedIntegrationTest {
|
public class DeleteFunctionDefaultPlatesScriptTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
|
|
||||||
private TestEnv env;
|
private TestEnv env;
|
||||||
private PluginTool tool;
|
private PluginTool tool;
|
||||||
@@ -50,13 +47,6 @@ public class DeleteFunctionDefaultPlatesTest extends AbstractGhidraHeadedIntegra
|
|||||||
private File script;
|
private File script;
|
||||||
private ToyProgramBuilder builder;
|
private ToyProgramBuilder builder;
|
||||||
|
|
||||||
public DeleteFunctionDefaultPlatesTest() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @see TestCase#setUp()
|
|
||||||
*/
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
env = new TestEnv();
|
env = new TestEnv();
|
||||||
@@ -71,11 +61,8 @@ public class DeleteFunctionDefaultPlatesTest extends AbstractGhidraHeadedIntegra
|
|||||||
|
|
||||||
ProgramManager pm = tool.getService(ProgramManager.class);
|
ProgramManager pm = tool.getService(ProgramManager.class);
|
||||||
pm.openProgram(program.getDomainFile());
|
pm.openProgram(program.getDomainFile());
|
||||||
//script =
|
|
||||||
// new File(Application.getApplicationRootDirectory().getFile(),
|
|
||||||
// "Features/Base/ghidra_scripts/DeleteFunctionDefaultPlates.java");
|
|
||||||
script = Application.getModuleFile("Base",
|
script = Application.getModuleFile("Base",
|
||||||
"ghidra_scripts/DeleteFunctionDefaultPlates.java").getFile(true);
|
"ghidra_scripts/DeleteFunctionDefaultPlatesScript.java").getFile(true);
|
||||||
env.showTool();
|
env.showTool();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,9 +84,6 @@ public class DeleteFunctionDefaultPlatesTest extends AbstractGhidraHeadedIntegra
|
|||||||
return builder.getProgram();
|
return builder.getProgram();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* @see TestCase#tearDown()
|
|
||||||
*/
|
|
||||||
@After
|
@After
|
||||||
public void tearDown() throws Exception {
|
public void tearDown() throws Exception {
|
||||||
env.dispose();
|
env.dispose();
|
||||||
+1
-10
@@ -90,7 +90,7 @@ public class SymbolTreePlugin1Test extends AbstractGhidraHeadedIntegrationTest {
|
|||||||
tool.addPlugin(SymbolTreePlugin.class.getName());
|
tool.addPlugin(SymbolTreePlugin.class.getName());
|
||||||
plugin = env.getPlugin(SymbolTreePlugin.class);
|
plugin = env.getPlugin(SymbolTreePlugin.class);
|
||||||
|
|
||||||
symTreeAction = getAction(plugin, "Display Symbol Tree");
|
symTreeAction = getAction(plugin, "Symbol Tree");
|
||||||
cbPlugin = env.getPlugin(CodeBrowserPlugin.class);
|
cbPlugin = env.getPlugin(CodeBrowserPlugin.class);
|
||||||
|
|
||||||
util = new SymbolTreeTestUtils(plugin);
|
util = new SymbolTreeTestUtils(plugin);
|
||||||
@@ -107,15 +107,6 @@ public class SymbolTreePlugin1Test extends AbstractGhidraHeadedIntegrationTest {
|
|||||||
env.dispose();
|
env.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testActionEnabled() {
|
|
||||||
assertTrue(symTreeAction.isEnabledForContext(null));
|
|
||||||
|
|
||||||
util.openProgram();
|
|
||||||
|
|
||||||
assertTrue(symTreeAction.isEnabledForContext(null));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testShowDisplay() throws Exception {
|
public void testShowDisplay() throws Exception {
|
||||||
showSymbolTree();
|
showSymbolTree();
|
||||||
|
|||||||
+2
-2
@@ -90,14 +90,14 @@ class SymbolTreeTestUtils {
|
|||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
this.program = buildProgram();
|
this.program = buildProgram();
|
||||||
|
|
||||||
symTreeAction = getAction(plugin, "Display Symbol Tree");
|
symTreeAction = getAction(plugin, "Symbol Tree");
|
||||||
}
|
}
|
||||||
|
|
||||||
SymbolTreeTestUtils(SymbolTreePlugin plugin, Program program) {
|
SymbolTreeTestUtils(SymbolTreePlugin plugin, Program program) {
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
this.program = program;
|
this.program = program;
|
||||||
|
|
||||||
symTreeAction = getAction(plugin, "Display Symbol Tree");
|
symTreeAction = getAction(plugin, "Symbol Tree");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Program buildProgram() throws Exception {
|
public static Program buildProgram() throws Exception {
|
||||||
|
|||||||
+10
-2
@@ -21,6 +21,7 @@ import java.awt.*;
|
|||||||
import java.awt.event.*;
|
import java.awt.event.*;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.function.BiConsumer;
|
import java.util.function.BiConsumer;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
@@ -59,6 +60,7 @@ import ghidra.util.table.GhidraTableFilterPanel;
|
|||||||
import ghidra.util.table.ProgramTableModel;
|
import ghidra.util.table.ProgramTableModel;
|
||||||
import ghidra.util.table.field.AddressBasedLocation;
|
import ghidra.util.table.field.AddressBasedLocation;
|
||||||
import ghidra.util.xml.XmlUtilities;
|
import ghidra.util.xml.XmlUtilities;
|
||||||
|
import util.CollectionUtils;
|
||||||
|
|
||||||
public class SymbolTablePluginTest extends AbstractGhidraHeadedIntegrationTest {
|
public class SymbolTablePluginTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
|
|
||||||
@@ -93,8 +95,14 @@ public class SymbolTablePluginTest extends AbstractGhidraHeadedIntegrationTest {
|
|||||||
plugin = env.getPlugin(SymbolTablePlugin.class);
|
plugin = env.getPlugin(SymbolTablePlugin.class);
|
||||||
provider = (SymbolProvider) getInstanceField("symProvider", plugin);
|
provider = (SymbolProvider) getInstanceField("symProvider", plugin);
|
||||||
|
|
||||||
viewSymAction = getAction(plugin, "View Symbol Table");
|
viewSymAction = getAction(plugin, "Symbol Table");
|
||||||
viewRefAction = getAction(plugin, "View Symbol References");
|
|
||||||
|
// this action is actually in the tool twice: once for the provider and once as a
|
||||||
|
// local action in the Symbol Table header, so we must pick one
|
||||||
|
Set<DockingActionIf> symbolReferencesActions =
|
||||||
|
getActionsByOwnerAndName(tool, plugin.getName(), "Symbol References");
|
||||||
|
viewRefAction = CollectionUtils.any(symbolReferencesActions);
|
||||||
|
|
||||||
deleteAction = getAction(plugin, "Delete Symbols");
|
deleteAction = getAction(plugin, "Delete Symbols");
|
||||||
makeSelectionAction = getAction(plugin, "Make Selection");
|
makeSelectionAction = getAction(plugin, "Make Selection");
|
||||||
setFilterAction = getAction(plugin, "Set Filter");
|
setFilterAction = getAction(plugin, "Set Filter");
|
||||||
|
|||||||
-390
@@ -1,390 +0,0 @@
|
|||||||
/* ###
|
|
||||||
* 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 ghidra.framework.main.datatree;
|
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
|
||||||
|
|
||||||
import java.awt.Container;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import javax.swing.*;
|
|
||||||
import javax.swing.tree.DefaultTreeCellEditor;
|
|
||||||
import javax.swing.tree.TreePath;
|
|
||||||
|
|
||||||
import org.junit.*;
|
|
||||||
|
|
||||||
import docking.ActionContext;
|
|
||||||
import docking.action.DockingActionIf;
|
|
||||||
import docking.action.ToggleDockingAction;
|
|
||||||
import docking.test.AbstractDockingTest;
|
|
||||||
import docking.widgets.OptionDialog;
|
|
||||||
import docking.widgets.tree.GTreeNode;
|
|
||||||
import docking.widgets.tree.GTreeRootNode;
|
|
||||||
import docking.widgets.tree.support.BreadthFirstIterator;
|
|
||||||
import ghidra.framework.data.DomainObjectAdapter;
|
|
||||||
import ghidra.framework.main.FrontEndTool;
|
|
||||||
import ghidra.framework.model.DomainFile;
|
|
||||||
import ghidra.framework.model.DomainFolder;
|
|
||||||
import ghidra.program.database.ProgramBuilder;
|
|
||||||
import ghidra.program.database.ProgramDB;
|
|
||||||
import ghidra.program.model.listing.Program;
|
|
||||||
import ghidra.test.AbstractGhidraHeadedIntegrationTest;
|
|
||||||
import ghidra.test.TestEnv;
|
|
||||||
import ghidra.util.task.TaskMonitorAdapter;
|
|
||||||
import resources.MultiIcon;
|
|
||||||
import resources.ResourceManager;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Mores Tests for actions in the front end (Ghidra project window).
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class ActionManager2Test extends AbstractGhidraHeadedIntegrationTest {
|
|
||||||
|
|
||||||
private FrontEndTool frontEndTool;
|
|
||||||
private TestEnv env;
|
|
||||||
private DataTree tree;
|
|
||||||
private DomainFolder rootFolder;
|
|
||||||
private GTreeRootNode rootNode;
|
|
||||||
|
|
||||||
@Before
|
|
||||||
public void setUp() throws Exception {
|
|
||||||
env = new TestEnv();
|
|
||||||
|
|
||||||
frontEndTool = env.getFrontEndTool();
|
|
||||||
env.showFrontEndTool();
|
|
||||||
tree = findComponent(frontEndTool.getToolFrame(), DataTree.class);
|
|
||||||
rootFolder = env.getProject().getProjectData().getRootFolder();
|
|
||||||
|
|
||||||
Program p = createDefaultProgram("p1", ProgramBuilder._TOY, this);
|
|
||||||
|
|
||||||
rootFolder.createFile("notepad", p, TaskMonitorAdapter.DUMMY_MONITOR);
|
|
||||||
p.release(this);
|
|
||||||
|
|
||||||
p = createDefaultProgram("p2", ProgramBuilder._TOY, this);
|
|
||||||
rootFolder.createFile("X07", p, TaskMonitorAdapter.DUMMY_MONITOR);
|
|
||||||
p.release(this);
|
|
||||||
|
|
||||||
rootNode = tree.getRootNode();
|
|
||||||
|
|
||||||
expandPath(rootNode.getTreePath());
|
|
||||||
}
|
|
||||||
|
|
||||||
@After
|
|
||||||
public void tearDown() throws Exception {
|
|
||||||
env.dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testRenameFolder() throws Exception {
|
|
||||||
rootFolder.createFolder("myFolder");
|
|
||||||
waitForSwing();
|
|
||||||
|
|
||||||
final GTreeNode myNode = rootNode.getChild("myFolder");
|
|
||||||
setSelectionPath(myNode.getTreePath());
|
|
||||||
|
|
||||||
DockingActionIf renameAction = getAction("Rename");
|
|
||||||
performAction(renameAction, getDomainFileActionContext(), true);
|
|
||||||
waitForTree();
|
|
||||||
|
|
||||||
// select "Rename" action
|
|
||||||
SwingUtilities.invokeAndWait(() -> {
|
|
||||||
int row = tree.getRowForPath(myNode.getTreePath());
|
|
||||||
JTree jTree = (JTree) getInstanceField("tree", tree);
|
|
||||||
DefaultTreeCellEditor cellEditor = (DefaultTreeCellEditor) tree.getCellEditor();
|
|
||||||
Container container = (Container) cellEditor.getTreeCellEditorComponent(jTree, myNode,
|
|
||||||
true, true, false, row);
|
|
||||||
JTextField textField = (JTextField) container.getComponent(0);
|
|
||||||
|
|
||||||
textField.setText("MyNewFolder");
|
|
||||||
tree.stopEditing();
|
|
||||||
});
|
|
||||||
waitForSwing();
|
|
||||||
assertNotNull(rootNode.getChild("MyNewFolder"));
|
|
||||||
assertNull(rootNode.getChild("myFolder"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testRenameFile() throws Exception {
|
|
||||||
final GTreeNode npNode = rootNode.getChild("notepad");
|
|
||||||
setSelectionPath(npNode.getTreePath());
|
|
||||||
|
|
||||||
DockingActionIf renameAction = getAction("Rename");
|
|
||||||
performAction(renameAction, getDomainFileActionContext(), true);
|
|
||||||
waitForTree();
|
|
||||||
|
|
||||||
// select "Rename" action
|
|
||||||
SwingUtilities.invokeAndWait(() -> {
|
|
||||||
int row = tree.getRowForPath(npNode.getTreePath());
|
|
||||||
DefaultTreeCellEditor cellEditor = (DefaultTreeCellEditor) tree.getCellEditor();
|
|
||||||
JTree jTree = (JTree) getInstanceField("tree", tree);
|
|
||||||
Container container = (Container) cellEditor.getTreeCellEditorComponent(jTree, npNode,
|
|
||||||
true, true, false, row);
|
|
||||||
JTextField textField = (JTextField) container.getComponent(0);
|
|
||||||
|
|
||||||
textField.setText("My_notepad");
|
|
||||||
tree.stopEditing();
|
|
||||||
});
|
|
||||||
waitForSwing();
|
|
||||||
assertNotNull(rootNode.getChild("My_notepad"));
|
|
||||||
assertNull(rootNode.getChild("notepad"));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testRenameFileInUse() throws Exception {
|
|
||||||
final GTreeNode npNode = rootNode.getChild("notepad");
|
|
||||||
DomainFile df = ((DomainFileNode) npNode).getDomainFile();
|
|
||||||
|
|
||||||
setInUse(df);
|
|
||||||
|
|
||||||
setSelectionPath(npNode.getTreePath());
|
|
||||||
|
|
||||||
DockingActionIf renameAction = getAction("Rename");
|
|
||||||
executeOnSwingWithoutBlocking(
|
|
||||||
() -> performAction(renameAction, getDomainFileActionContext(), true));
|
|
||||||
waitForSwing();
|
|
||||||
OptionDialog dlg = waitForDialogComponent(OptionDialog.class);
|
|
||||||
assertEquals("Rename Not Allowed", dlg.getTitle());
|
|
||||||
pressButtonByText(dlg.getComponent(), "OK");
|
|
||||||
assertNotNull(rootNode.getChild("notepad"));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setInUse(DomainFile df) throws Exception {
|
|
||||||
setInUse(df, "/notepad");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setInUse(DomainFile df, final String path) throws Exception {
|
|
||||||
ProgramDB program = createDefaultProgram("test1", ProgramBuilder._TOY, this);
|
|
||||||
|
|
||||||
//
|
|
||||||
// Unusual Code Alert!
|
|
||||||
// We are calling an internal method to trigger the 'in use' state, as it is much
|
|
||||||
// faster to do this than it is to open a program in a tool!
|
|
||||||
//
|
|
||||||
|
|
||||||
//@formatter:off
|
|
||||||
Object projectFileManager = getInstanceField("fileManager", df);
|
|
||||||
invokeInstanceMethod("setDomainObject", projectFileManager,
|
|
||||||
new Class[] { String.class, DomainObjectAdapter.class },
|
|
||||||
new Object[] { path, program }
|
|
||||||
);
|
|
||||||
//@formatter:on
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testRenameFolderInUse() throws Exception {
|
|
||||||
// folder contains a file that is in use
|
|
||||||
DomainFolder f = rootFolder.createFolder("myFolder");
|
|
||||||
f = f.createFolder("A");
|
|
||||||
f = f.createFolder("B");
|
|
||||||
f = f.createFolder("C");
|
|
||||||
|
|
||||||
Program p = createDefaultProgram("new", ProgramBuilder._TOY, this);
|
|
||||||
|
|
||||||
DomainFile df = f.createFile("notepad", p, TaskMonitorAdapter.DUMMY_MONITOR);
|
|
||||||
waitForSwing();
|
|
||||||
|
|
||||||
final GTreeNode myNode = rootNode.getChild("myFolder");
|
|
||||||
((DomainFolderNode) myNode).getDomainFolder().createFile("notepad", p,
|
|
||||||
TaskMonitorAdapter.DUMMY_MONITOR);
|
|
||||||
p.release(this);
|
|
||||||
|
|
||||||
waitForSwing();
|
|
||||||
tree.expandPath(myNode.getTreePath());
|
|
||||||
assertNotNull(myNode.getChild("notepad"));
|
|
||||||
|
|
||||||
setInUse(df, "/myFolder/notepad");
|
|
||||||
|
|
||||||
setSelectionPath(myNode.getTreePath());
|
|
||||||
|
|
||||||
final DockingActionIf renameAction = getAction("Rename");
|
|
||||||
performAction(renameAction, getDomainFileActionContext(), true);
|
|
||||||
waitForTree();
|
|
||||||
|
|
||||||
// attempt to rename "myFolder"
|
|
||||||
SwingUtilities.invokeLater(() -> {
|
|
||||||
int row = tree.getRowForPath(myNode.getTreePath());
|
|
||||||
DefaultTreeCellEditor cellEditor = (DefaultTreeCellEditor) tree.getCellEditor();
|
|
||||||
JTree jTree = (JTree) getInstanceField("tree", tree);
|
|
||||||
Container container = (Container) cellEditor.getTreeCellEditorComponent(jTree, myNode,
|
|
||||||
true, true, false, row);
|
|
||||||
JTextField textField = (JTextField) container.getComponent(0);
|
|
||||||
|
|
||||||
textField.setText("My_Newfolder");
|
|
||||||
tree.stopEditing();
|
|
||||||
});
|
|
||||||
|
|
||||||
waitForSwing();
|
|
||||||
|
|
||||||
OptionDialog d =
|
|
||||||
waitForDialogComponent(frontEndTool.getToolFrame(), OptionDialog.class, 2000);
|
|
||||||
assertNotNull(d);
|
|
||||||
assertEquals("Rename Failed", d.getTitle());
|
|
||||||
pressButtonByText(d.getComponent(), "OK");
|
|
||||||
assertNotNull(rootNode.getChild("myFolder"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testExpandAll() throws Exception {
|
|
||||||
DomainFolder f = rootFolder.createFolder("myFolder");
|
|
||||||
f = f.createFolder("A");
|
|
||||||
f = f.createFolder("B");
|
|
||||||
f = f.createFolder("C");
|
|
||||||
waitForSwing();
|
|
||||||
|
|
||||||
GTreeNode myNode = rootNode.getChild("myFolder");
|
|
||||||
setSelectionPath(rootNode.getTreePath());
|
|
||||||
DockingActionIf expandAction = getAction("Expand All");
|
|
||||||
performAction(expandAction, getDomainFileActionContext(), true);
|
|
||||||
GTreeNode aNode = myNode.getChild("A");
|
|
||||||
assertNotNull(aNode);
|
|
||||||
GTreeNode bNode = aNode.getChild("B");
|
|
||||||
assertNotNull(bNode);
|
|
||||||
GTreeNode cNode = bNode.getChild("C");
|
|
||||||
assertNotNull(cNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testCollapseAll() throws Exception {
|
|
||||||
DomainFolder f = rootFolder.createFolder("myFolder");
|
|
||||||
f = f.createFolder("A");
|
|
||||||
f = f.createFolder("B");
|
|
||||||
f = f.createFolder("C");
|
|
||||||
waitForSwing();
|
|
||||||
|
|
||||||
GTreeNode myNode = rootNode.getChild("myFolder");
|
|
||||||
setSelectionPath(myNode.getTreePath());
|
|
||||||
DockingActionIf expandAction = getAction("Expand All");
|
|
||||||
performAction(expandAction, getDomainFileActionContext(), true);
|
|
||||||
waitForTree();
|
|
||||||
|
|
||||||
DockingActionIf collapseAction = getAction("Collapse All");
|
|
||||||
performAction(collapseAction, getDomainFileActionContext(), true);
|
|
||||||
waitForTree();
|
|
||||||
assertTrue(!tree.isExpanded(myNode.getTreePath()));
|
|
||||||
GTreeNode aNode = myNode.getChild("A");
|
|
||||||
assertTrue(!tree.isExpanded(aNode.getTreePath()));
|
|
||||||
GTreeNode bNode = aNode.getChild("B");
|
|
||||||
assertTrue(!tree.isExpanded(bNode.getTreePath()));
|
|
||||||
GTreeNode cNode = bNode.getChild("C");
|
|
||||||
assertNotNull(cNode);
|
|
||||||
assertTrue(!tree.isExpanded(cNode.getTreePath()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSelectAll() throws Exception {
|
|
||||||
DomainFolder f = rootFolder.createFolder("myFolder");
|
|
||||||
f = f.createFolder("A");
|
|
||||||
f = f.createFolder("B");
|
|
||||||
f = f.createFolder("C");
|
|
||||||
waitForSwing();
|
|
||||||
|
|
||||||
setSelectionPath(rootNode.getTreePath());
|
|
||||||
DockingActionIf selectAction = getAction("Select All");
|
|
||||||
performAction(selectAction, getDomainFileActionContext(), true);
|
|
||||||
waitForTree();
|
|
||||||
|
|
||||||
BreadthFirstIterator it = new BreadthFirstIterator(tree, rootNode);
|
|
||||||
while (it.hasNext()) {
|
|
||||||
GTreeNode node = it.next();
|
|
||||||
assertTrue(tree.isPathSelected(node.getTreePath()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSetReadOnly() throws Exception {
|
|
||||||
GTreeNode npNode = rootNode.getChild("notepad");
|
|
||||||
setSelectionPath(npNode.getTreePath());
|
|
||||||
ToggleDockingAction readOnlyAction = (ToggleDockingAction) getAction("Read-Only");
|
|
||||||
readOnlyAction.setSelected(true);
|
|
||||||
performAction(readOnlyAction, getDomainFileActionContext(), true);
|
|
||||||
|
|
||||||
assertTrue(((DomainFileNode) npNode).getDomainFile().isReadOnly());
|
|
||||||
ImageIcon icon = ResourceManager.loadImage("fileIcons/ProgramReadOnly.gif");
|
|
||||||
icon = ResourceManager.getScaledIcon(icon, 16, 16);
|
|
||||||
|
|
||||||
assertTrue(npNode.getIcon(false) instanceof MultiIcon);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSetReadOnlyInUse() throws Exception {
|
|
||||||
GTreeNode npNode = rootNode.getChild("notepad");
|
|
||||||
DomainFile df = ((DomainFileNode) npNode).getDomainFile();
|
|
||||||
setInUse(df);
|
|
||||||
|
|
||||||
setSelectionPath(npNode.getTreePath());
|
|
||||||
ToggleDockingAction readOnlyAction = (ToggleDockingAction) getAction("Read-Only");
|
|
||||||
readOnlyAction.setSelected(true);
|
|
||||||
performAction(readOnlyAction, getDomainFileActionContext(), true);
|
|
||||||
|
|
||||||
assertTrue(((DomainFileNode) npNode).getDomainFile().isReadOnly());
|
|
||||||
}
|
|
||||||
|
|
||||||
//==================================================================================================
|
|
||||||
// Private Methods
|
|
||||||
//==================================================================================================
|
|
||||||
|
|
||||||
private ActionContext getDomainFileActionContext() {
|
|
||||||
List<DomainFile> fileList = new ArrayList<>();
|
|
||||||
List<DomainFolder> folderList = new ArrayList<>();
|
|
||||||
|
|
||||||
TreePath[] paths = tree.getSelectionPaths();
|
|
||||||
for (TreePath path : paths) {
|
|
||||||
|
|
||||||
GTreeNode node = (GTreeNode) path.getLastPathComponent();
|
|
||||||
if (node instanceof DomainFileNode) {
|
|
||||||
fileList.add(((DomainFileNode) node).getDomainFile());
|
|
||||||
}
|
|
||||||
else if (node instanceof DomainFolderNode) {
|
|
||||||
folderList.add(((DomainFolderNode) node).getDomainFolder());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return new ProjectDataTreeActionContext(null, null, paths, folderList, fileList, tree,
|
|
||||||
true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private DockingActionIf getAction(String actionName) {
|
|
||||||
DockingActionIf action =
|
|
||||||
AbstractDockingTest.getAction(frontEndTool, "FrontEndPlugin", actionName);
|
|
||||||
return action;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setSelectionPath(final TreePath path) throws Exception {
|
|
||||||
tree.setSelectionPath(path);
|
|
||||||
waitForTree();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void expandPath(TreePath treePath) {
|
|
||||||
tree.expandPath(treePath);
|
|
||||||
waitForTree();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void waitForTree() {
|
|
||||||
waitForSwing();
|
|
||||||
while (tree.isBusy()) {
|
|
||||||
try {
|
|
||||||
Thread.sleep(10);
|
|
||||||
}
|
|
||||||
catch (InterruptedException e) {
|
|
||||||
// try again
|
|
||||||
}
|
|
||||||
}
|
|
||||||
waitForSwing();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+233
-8
@@ -30,12 +30,12 @@ import org.junit.*;
|
|||||||
|
|
||||||
import docking.ActionContext;
|
import docking.ActionContext;
|
||||||
import docking.action.DockingActionIf;
|
import docking.action.DockingActionIf;
|
||||||
|
import docking.action.ToggleDockingAction;
|
||||||
import docking.test.AbstractDockingTest;
|
import docking.test.AbstractDockingTest;
|
||||||
import docking.widgets.OptionDialog;
|
import docking.widgets.OptionDialog;
|
||||||
import docking.widgets.tree.GTreeNode;
|
import docking.widgets.tree.GTreeNode;
|
||||||
import docking.widgets.tree.GTreeRootNode;
|
import docking.widgets.tree.GTreeRootNode;
|
||||||
import docking.widgets.tree.support.GTreeDragNDropHandler;
|
import docking.widgets.tree.support.*;
|
||||||
import docking.widgets.tree.support.GTreeNodeTransferable;
|
|
||||||
import ghidra.framework.data.DomainObjectAdapter;
|
import ghidra.framework.data.DomainObjectAdapter;
|
||||||
import ghidra.framework.main.FrontEndTool;
|
import ghidra.framework.main.FrontEndTool;
|
||||||
import ghidra.framework.model.DomainFile;
|
import ghidra.framework.model.DomainFile;
|
||||||
@@ -46,11 +46,13 @@ import ghidra.program.model.listing.Program;
|
|||||||
import ghidra.test.AbstractGhidraHeadedIntegrationTest;
|
import ghidra.test.AbstractGhidraHeadedIntegrationTest;
|
||||||
import ghidra.test.TestEnv;
|
import ghidra.test.TestEnv;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
import resources.MultiIcon;
|
||||||
|
import resources.ResourceManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for actions in the front end (Ghidra project window).
|
* Tests for actions in the front end (Ghidra project window)
|
||||||
*/
|
*/
|
||||||
public class ActionManager1Test extends AbstractGhidraHeadedIntegrationTest {
|
public class FrontEndPluginActionsTest extends AbstractGhidraHeadedIntegrationTest {
|
||||||
|
|
||||||
private FrontEndTool frontEndTool;
|
private FrontEndTool frontEndTool;
|
||||||
private TestEnv env;
|
private TestEnv env;
|
||||||
@@ -58,10 +60,6 @@ public class ActionManager1Test extends AbstractGhidraHeadedIntegrationTest {
|
|||||||
private DomainFolder rootFolder;
|
private DomainFolder rootFolder;
|
||||||
private GTreeRootNode rootNode;
|
private GTreeRootNode rootNode;
|
||||||
|
|
||||||
public ActionManager1Test() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
|
|
||||||
@@ -533,10 +531,237 @@ public class ActionManager1Test extends AbstractGhidraHeadedIntegrationTest {
|
|||||||
assertNull(getChild(rootNode, "tms"));
|
assertNull(getChild(rootNode, "tms"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRenameFolder() throws Exception {
|
||||||
|
rootFolder.createFolder("myFolder");
|
||||||
|
waitForSwing();
|
||||||
|
|
||||||
|
final GTreeNode myNode = rootNode.getChild("myFolder");
|
||||||
|
setSelectionPath(myNode.getTreePath());
|
||||||
|
|
||||||
|
DockingActionIf renameAction = getAction("Rename");
|
||||||
|
performAction(renameAction, getDomainFileActionContext(), true);
|
||||||
|
waitForTree();
|
||||||
|
|
||||||
|
// select "Rename" action
|
||||||
|
SwingUtilities.invokeAndWait(() -> {
|
||||||
|
int row = tree.getRowForPath(myNode.getTreePath());
|
||||||
|
JTree jTree = (JTree) getInstanceField("tree", tree);
|
||||||
|
DefaultTreeCellEditor cellEditor = (DefaultTreeCellEditor) tree.getCellEditor();
|
||||||
|
Container container = (Container) cellEditor.getTreeCellEditorComponent(jTree, myNode,
|
||||||
|
true, true, false, row);
|
||||||
|
JTextField textField = (JTextField) container.getComponent(0);
|
||||||
|
|
||||||
|
textField.setText("MyNewFolder");
|
||||||
|
tree.stopEditing();
|
||||||
|
});
|
||||||
|
waitForSwing();
|
||||||
|
assertNotNull(rootNode.getChild("MyNewFolder"));
|
||||||
|
assertNull(rootNode.getChild("myFolder"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRenameFile() throws Exception {
|
||||||
|
final GTreeNode npNode = rootNode.getChild("notepad");
|
||||||
|
setSelectionPath(npNode.getTreePath());
|
||||||
|
|
||||||
|
DockingActionIf renameAction = getAction("Rename");
|
||||||
|
performAction(renameAction, getDomainFileActionContext(), true);
|
||||||
|
waitForTree();
|
||||||
|
|
||||||
|
// select "Rename" action
|
||||||
|
SwingUtilities.invokeAndWait(() -> {
|
||||||
|
int row = tree.getRowForPath(npNode.getTreePath());
|
||||||
|
DefaultTreeCellEditor cellEditor = (DefaultTreeCellEditor) tree.getCellEditor();
|
||||||
|
JTree jTree = (JTree) getInstanceField("tree", tree);
|
||||||
|
Container container = (Container) cellEditor.getTreeCellEditorComponent(jTree, npNode,
|
||||||
|
true, true, false, row);
|
||||||
|
JTextField textField = (JTextField) container.getComponent(0);
|
||||||
|
|
||||||
|
textField.setText("My_notepad");
|
||||||
|
tree.stopEditing();
|
||||||
|
});
|
||||||
|
waitForSwing();
|
||||||
|
assertNotNull(rootNode.getChild("My_notepad"));
|
||||||
|
assertNull(rootNode.getChild("notepad"));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRenameFileInUse() throws Exception {
|
||||||
|
final GTreeNode npNode = rootNode.getChild("notepad");
|
||||||
|
DomainFile df = ((DomainFileNode) npNode).getDomainFile();
|
||||||
|
|
||||||
|
setInUse(df);
|
||||||
|
|
||||||
|
setSelectionPath(npNode.getTreePath());
|
||||||
|
|
||||||
|
DockingActionIf renameAction = getAction("Rename");
|
||||||
|
executeOnSwingWithoutBlocking(
|
||||||
|
() -> performAction(renameAction, getDomainFileActionContext(), true));
|
||||||
|
waitForSwing();
|
||||||
|
OptionDialog dlg = waitForDialogComponent(OptionDialog.class);
|
||||||
|
assertEquals("Rename Not Allowed", dlg.getTitle());
|
||||||
|
pressButtonByText(dlg.getComponent(), "OK");
|
||||||
|
assertNotNull(rootNode.getChild("notepad"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRenameFolderInUse() throws Exception {
|
||||||
|
// folder contains a file that is in use
|
||||||
|
DomainFolder f = rootFolder.createFolder("myFolder");
|
||||||
|
f = f.createFolder("A");
|
||||||
|
f = f.createFolder("B");
|
||||||
|
f = f.createFolder("C");
|
||||||
|
|
||||||
|
Program p = createDefaultProgram("new", ProgramBuilder._TOY, this);
|
||||||
|
|
||||||
|
DomainFile df = f.createFile("notepad", p, TaskMonitor.DUMMY);
|
||||||
|
waitForSwing();
|
||||||
|
|
||||||
|
final GTreeNode myNode = rootNode.getChild("myFolder");
|
||||||
|
((DomainFolderNode) myNode).getDomainFolder().createFile("notepad", p, TaskMonitor.DUMMY);
|
||||||
|
p.release(this);
|
||||||
|
|
||||||
|
waitForSwing();
|
||||||
|
tree.expandPath(myNode.getTreePath());
|
||||||
|
assertNotNull(myNode.getChild("notepad"));
|
||||||
|
|
||||||
|
setInUse(df, "/myFolder/notepad");
|
||||||
|
|
||||||
|
setSelectionPath(myNode.getTreePath());
|
||||||
|
|
||||||
|
final DockingActionIf renameAction = getAction("Rename");
|
||||||
|
performAction(renameAction, getDomainFileActionContext(), true);
|
||||||
|
waitForTree();
|
||||||
|
|
||||||
|
// attempt to rename "myFolder"
|
||||||
|
SwingUtilities.invokeLater(() -> {
|
||||||
|
int row = tree.getRowForPath(myNode.getTreePath());
|
||||||
|
DefaultTreeCellEditor cellEditor = (DefaultTreeCellEditor) tree.getCellEditor();
|
||||||
|
JTree jTree = (JTree) getInstanceField("tree", tree);
|
||||||
|
Container container = (Container) cellEditor.getTreeCellEditorComponent(jTree, myNode,
|
||||||
|
true, true, false, row);
|
||||||
|
JTextField textField = (JTextField) container.getComponent(0);
|
||||||
|
|
||||||
|
textField.setText("My_Newfolder");
|
||||||
|
tree.stopEditing();
|
||||||
|
});
|
||||||
|
|
||||||
|
waitForSwing();
|
||||||
|
|
||||||
|
OptionDialog d = waitForDialogComponent(OptionDialog.class);
|
||||||
|
assertNotNull(d);
|
||||||
|
assertEquals("Rename Failed", d.getTitle());
|
||||||
|
pressButtonByText(d.getComponent(), "OK");
|
||||||
|
assertNotNull(rootNode.getChild("myFolder"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testExpandAll() throws Exception {
|
||||||
|
DomainFolder f = rootFolder.createFolder("myFolder");
|
||||||
|
f = f.createFolder("A");
|
||||||
|
f = f.createFolder("B");
|
||||||
|
f = f.createFolder("C");
|
||||||
|
waitForSwing();
|
||||||
|
|
||||||
|
GTreeNode myNode = rootNode.getChild("myFolder");
|
||||||
|
setSelectionPath(rootNode.getTreePath());
|
||||||
|
DockingActionIf expandAction = getAction("Expand All");
|
||||||
|
performAction(expandAction, getDomainFileActionContext(), true);
|
||||||
|
GTreeNode aNode = myNode.getChild("A");
|
||||||
|
assertNotNull(aNode);
|
||||||
|
GTreeNode bNode = aNode.getChild("B");
|
||||||
|
assertNotNull(bNode);
|
||||||
|
GTreeNode cNode = bNode.getChild("C");
|
||||||
|
assertNotNull(cNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCollapseAll() throws Exception {
|
||||||
|
DomainFolder f = rootFolder.createFolder("myFolder");
|
||||||
|
f = f.createFolder("A");
|
||||||
|
f = f.createFolder("B");
|
||||||
|
f = f.createFolder("C");
|
||||||
|
waitForSwing();
|
||||||
|
|
||||||
|
GTreeNode myNode = rootNode.getChild("myFolder");
|
||||||
|
setSelectionPath(myNode.getTreePath());
|
||||||
|
DockingActionIf expandAction = getAction("Expand All");
|
||||||
|
performAction(expandAction, getDomainFileActionContext(), true);
|
||||||
|
waitForTree();
|
||||||
|
|
||||||
|
DockingActionIf collapseAction = getAction("Collapse All");
|
||||||
|
performAction(collapseAction, getDomainFileActionContext(), true);
|
||||||
|
waitForTree();
|
||||||
|
assertTrue(!tree.isExpanded(myNode.getTreePath()));
|
||||||
|
GTreeNode aNode = myNode.getChild("A");
|
||||||
|
assertTrue(!tree.isExpanded(aNode.getTreePath()));
|
||||||
|
GTreeNode bNode = aNode.getChild("B");
|
||||||
|
assertTrue(!tree.isExpanded(bNode.getTreePath()));
|
||||||
|
GTreeNode cNode = bNode.getChild("C");
|
||||||
|
assertNotNull(cNode);
|
||||||
|
assertTrue(!tree.isExpanded(cNode.getTreePath()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSelectAll() throws Exception {
|
||||||
|
DomainFolder f = rootFolder.createFolder("myFolder");
|
||||||
|
f = f.createFolder("A");
|
||||||
|
f = f.createFolder("B");
|
||||||
|
f = f.createFolder("C");
|
||||||
|
waitForSwing();
|
||||||
|
|
||||||
|
setSelectionPath(rootNode.getTreePath());
|
||||||
|
DockingActionIf selectAction = getAction("Select All");
|
||||||
|
performAction(selectAction, getDomainFileActionContext(), true);
|
||||||
|
waitForTree();
|
||||||
|
|
||||||
|
BreadthFirstIterator it = new BreadthFirstIterator(tree, rootNode);
|
||||||
|
while (it.hasNext()) {
|
||||||
|
GTreeNode node = it.next();
|
||||||
|
assertTrue(tree.isPathSelected(node.getTreePath()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSetReadOnly() throws Exception {
|
||||||
|
GTreeNode npNode = rootNode.getChild("notepad");
|
||||||
|
setSelectionPath(npNode.getTreePath());
|
||||||
|
ToggleDockingAction readOnlyAction = (ToggleDockingAction) getAction("Read-Only");
|
||||||
|
readOnlyAction.setSelected(true);
|
||||||
|
performAction(readOnlyAction, getDomainFileActionContext(), true);
|
||||||
|
|
||||||
|
assertTrue(((DomainFileNode) npNode).getDomainFile().isReadOnly());
|
||||||
|
ImageIcon icon = ResourceManager.loadImage("fileIcons/ProgramReadOnly.gif");
|
||||||
|
icon = ResourceManager.getScaledIcon(icon, 16, 16);
|
||||||
|
|
||||||
|
assertTrue(npNode.getIcon(false) instanceof MultiIcon);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSetReadOnlyInUse() throws Exception {
|
||||||
|
GTreeNode npNode = rootNode.getChild("notepad");
|
||||||
|
DomainFile df = ((DomainFileNode) npNode).getDomainFile();
|
||||||
|
setInUse(df);
|
||||||
|
|
||||||
|
setSelectionPath(npNode.getTreePath());
|
||||||
|
ToggleDockingAction readOnlyAction = (ToggleDockingAction) getAction("Read-Only");
|
||||||
|
readOnlyAction.setSelected(true);
|
||||||
|
performAction(readOnlyAction, getDomainFileActionContext(), true);
|
||||||
|
|
||||||
|
assertTrue(((DomainFileNode) npNode).getDomainFile().isReadOnly());
|
||||||
|
}
|
||||||
|
|
||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
// Private Methods
|
// Private Methods
|
||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
|
|
||||||
|
private void setSelectionPath(final TreePath path) throws Exception {
|
||||||
|
tree.setSelectionPath(path);
|
||||||
|
waitForTree();
|
||||||
|
}
|
||||||
|
|
||||||
private void pressDelete() {
|
private void pressDelete() {
|
||||||
DockingActionIf deleteAction = getAction("Delete");
|
DockingActionIf deleteAction = getAction("Delete");
|
||||||
performAction(deleteAction, getDomainFileActionContext(), false);
|
performAction(deleteAction, getDomainFileActionContext(), false);
|
||||||
@@ -43,6 +43,11 @@ public class DummyToolActions implements DockingToolActions {
|
|||||||
// stub
|
// stub
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DockingActionIf getLocalAction(ComponentProvider provider, String actionName) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<DockingActionIf> getActions(String owner) {
|
public Set<DockingActionIf> getActions(String owner) {
|
||||||
return null;
|
return null;
|
||||||
@@ -62,5 +67,4 @@ public class DummyToolActions implements DockingToolActions {
|
|||||||
public void removeActions(ComponentProvider provider) {
|
public void removeActions(ComponentProvider provider) {
|
||||||
// stub
|
// stub
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
</COMPONENT_NODE>
|
</COMPONENT_NODE>
|
||||||
</SPLIT_NODE>
|
</SPLIT_NODE>
|
||||||
<COMPONENT_NODE TOP_INFO="0">
|
<COMPONENT_NODE TOP_INFO="0">
|
||||||
<COMPONENT_INFO NAME="ConsolePlugin" OWNER="ConsolePlugin" TITLE="Console" ACTIVE="false" GROUP="Default" INSTANCE_ID="2999653489311119719" />
|
<COMPONENT_INFO NAME="Console" OWNER="ConsolePlugin" TITLE="Console" ACTIVE="false" GROUP="Default" INSTANCE_ID="2999653489311119719" />
|
||||||
</COMPONENT_NODE>
|
</COMPONENT_NODE>
|
||||||
</SPLIT_NODE>
|
</SPLIT_NODE>
|
||||||
<SPLIT_NODE WIDTH="996" HEIGHT="491" DIVIDER_LOCATION="622" ORIENTATION="HORIZONTAL">
|
<SPLIT_NODE WIDTH="996" HEIGHT="491" DIVIDER_LOCATION="622" ORIENTATION="HORIZONTAL">
|
||||||
|
|||||||
+3
-5
@@ -27,7 +27,7 @@ import org.junit.*;
|
|||||||
|
|
||||||
import com.google.common.cache.*;
|
import com.google.common.cache.*;
|
||||||
|
|
||||||
import docking.action.DockingAction;
|
import docking.ComponentProvider;
|
||||||
import generic.test.TestUtils;
|
import generic.test.TestUtils;
|
||||||
import ghidra.app.decompiler.DecompileResults;
|
import ghidra.app.decompiler.DecompileResults;
|
||||||
import ghidra.app.plugin.core.codebrowser.CodeBrowserPlugin;
|
import ghidra.app.plugin.core.codebrowser.CodeBrowserPlugin;
|
||||||
@@ -201,10 +201,8 @@ public class DecompilerCachingTest extends AbstractGhidraHeadedIntegrationTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void showDecompilerProvider() {
|
private void showDecompilerProvider() {
|
||||||
DockingAction showDecompileAction =
|
ComponentProvider decompiler = tool.getComponentProvider("Decompiler");
|
||||||
(DockingAction) TestUtils.getInstanceField("decompileAction", decompilePlugin);
|
tool.showComponentProvider(decompiler, true);
|
||||||
performAction(showDecompileAction, true);
|
|
||||||
|
|
||||||
decompilerProvider = waitForComponentProvider(DecompilerProvider.class);
|
decompilerProvider = waitForComponentProvider(DecompilerProvider.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+4
-4
@@ -15,7 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package ghidra.app.plugin.core.functiongraph;
|
package ghidra.app.plugin.core.functiongraph;
|
||||||
|
|
||||||
import static ghidra.graph.viewer.GraphViewerUtils.*;
|
import static ghidra.graph.viewer.GraphViewerUtils.getGraphScale;
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
@@ -552,9 +552,9 @@ public abstract class AbstractFunctionGraphTest extends AbstractGhidraHeadedInte
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void showFunctionGraphProvider() {
|
protected void showFunctionGraphProvider() {
|
||||||
DockingAction showGraphAction =
|
|
||||||
(DockingAction) TestUtils.getInstanceField("showFunctionGraphAction", graphPlugin);
|
ComponentProvider provider = tool.getComponentProvider("Function Graph");
|
||||||
performAction(showGraphAction, true);
|
tool.showComponentProvider(provider, true);
|
||||||
|
|
||||||
graphProvider = waitForComponentProvider(FGProvider.class);
|
graphProvider = waitForComponentProvider(FGProvider.class);
|
||||||
assertNotNull("Graph not shown", graphProvider);
|
assertNotNull("Graph not shown", graphProvider);
|
||||||
|
|||||||
+1
-1
@@ -51,7 +51,7 @@ class DiffActionManager {
|
|||||||
static final String IGNORE_DIFFS_NEXT_ACTION = "Ignore Selection and Goto Next Difference";
|
static final String IGNORE_DIFFS_NEXT_ACTION = "Ignore Selection and Goto Next Difference";
|
||||||
static final String NEXT_DIFF_ACTION = "Next Difference";
|
static final String NEXT_DIFF_ACTION = "Next Difference";
|
||||||
static final String PREVIOUS_DIFF_ACTION = "Previous Difference";
|
static final String PREVIOUS_DIFF_ACTION = "Previous Difference";
|
||||||
static final String DIFF_DETAILS_ACTION = "Diff Location Details";
|
static final String DIFF_DETAILS_ACTION = "Show Diff Location Details";
|
||||||
static final String SHOW_DIFF_SETTINGS_ACTION = "Show Diff Apply Settings";
|
static final String SHOW_DIFF_SETTINGS_ACTION = "Show Diff Apply Settings";
|
||||||
static final String GET_DIFFS_ACTION = "Get Differences";
|
static final String GET_DIFFS_ACTION = "Get Differences";
|
||||||
static final String SELECT_ALL_DIFFS_ACTION = "Select All Differences";
|
static final String SELECT_ALL_DIFFS_ACTION = "Select All Differences";
|
||||||
|
|||||||
+4
-4
@@ -665,7 +665,7 @@ public class DiffTest extends DiffTestAdapter {
|
|||||||
checkDiffAction("Ignore Selection and Goto Next Difference", true, false);
|
checkDiffAction("Ignore Selection and Goto Next Difference", true, false);
|
||||||
checkDiffAction("Next Difference", true, true);
|
checkDiffAction("Next Difference", true, true);
|
||||||
checkDiffAction("Previous Difference", true, false);
|
checkDiffAction("Previous Difference", true, false);
|
||||||
checkDiffAction("Diff Location Details", true, true);
|
checkDiffAction("Show Diff Location Details", true, true);
|
||||||
checkDiffAction("Show Diff Apply Settings", true, true);
|
checkDiffAction("Show Diff Apply Settings", true, true);
|
||||||
checkDiffAction("Get Differences", true, true);
|
checkDiffAction("Get Differences", true, true);
|
||||||
checkDiffAction("Select All Differences", true, true);
|
checkDiffAction("Select All Differences", true, true);
|
||||||
@@ -699,7 +699,7 @@ public class DiffTest extends DiffTestAdapter {
|
|||||||
checkDiffAction("Ignore Selection and Goto Next Difference", false, false);
|
checkDiffAction("Ignore Selection and Goto Next Difference", false, false);
|
||||||
checkDiffAction("Next Difference", false, false);
|
checkDiffAction("Next Difference", false, false);
|
||||||
checkDiffAction("Previous Difference", false, false);
|
checkDiffAction("Previous Difference", false, false);
|
||||||
checkDiffAction("Diff Location Details", false, false);
|
checkDiffAction("Show Diff Location Details", false, false);
|
||||||
checkDiffAction("Show Diff Apply Settings", false, false);
|
checkDiffAction("Show Diff Apply Settings", false, false);
|
||||||
checkDiffAction("Get Differences", false, false);
|
checkDiffAction("Get Differences", false, false);
|
||||||
checkDiffAction("Select All Differences", false, false);
|
checkDiffAction("Select All Differences", false, false);
|
||||||
@@ -715,7 +715,7 @@ public class DiffTest extends DiffTestAdapter {
|
|||||||
checkDiffAction("Ignore Selection and Goto Next Difference", false, false);
|
checkDiffAction("Ignore Selection and Goto Next Difference", false, false);
|
||||||
checkDiffAction("Next Difference", false, false);
|
checkDiffAction("Next Difference", false, false);
|
||||||
checkDiffAction("Previous Difference", false, false);
|
checkDiffAction("Previous Difference", false, false);
|
||||||
checkDiffAction("Diff Location Details", false, false);
|
checkDiffAction("Show Diff Location Details", false, false);
|
||||||
checkDiffAction("Show Diff Apply Settings", false, false);
|
checkDiffAction("Show Diff Apply Settings", false, false);
|
||||||
checkDiffAction("Get Differences", false, false);
|
checkDiffAction("Get Differences", false, false);
|
||||||
checkDiffAction("Select All Differences", false, false);
|
checkDiffAction("Select All Differences", false, false);
|
||||||
@@ -732,7 +732,7 @@ public class DiffTest extends DiffTestAdapter {
|
|||||||
checkDiffAction("Ignore Selection and Goto Next Difference", true, false);
|
checkDiffAction("Ignore Selection and Goto Next Difference", true, false);
|
||||||
checkDiffAction("Next Difference", true, true);
|
checkDiffAction("Next Difference", true, true);
|
||||||
checkDiffAction("Previous Difference", true, true);
|
checkDiffAction("Previous Difference", true, true);
|
||||||
checkDiffAction("Diff Location Details", true, true);
|
checkDiffAction("Show Diff Location Details", true, true);
|
||||||
checkDiffAction("Show Diff Apply Settings", true, true);
|
checkDiffAction("Show Diff Apply Settings", true, true);
|
||||||
checkDiffAction("Get Differences", true, true);
|
checkDiffAction("Get Differences", true, true);
|
||||||
checkDiffAction("Select All Differences", true, true);
|
checkDiffAction("Select All Differences", true, true);
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ public abstract class AbstractDockingTool implements DockingTool {
|
|||||||
@Override
|
@Override
|
||||||
public void removeComponentProvider(ComponentProvider provider) {
|
public void removeComponentProvider(ComponentProvider provider) {
|
||||||
Runnable r = () -> {
|
Runnable r = () -> {
|
||||||
|
toolActions.removeGlobalAction(provider.getShowProviderAction());
|
||||||
toolActions.removeActions(provider);
|
toolActions.removeActions(provider);
|
||||||
winMgr.removeComponent(provider);
|
winMgr.removeComponent(provider);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -168,7 +168,8 @@ class DockableToolBarManager {
|
|||||||
private DockableComponent dockableComponent;
|
private DockableComponent dockableComponent;
|
||||||
|
|
||||||
ToolBarCloseAction(DockableComponent dockableComponent) {
|
ToolBarCloseAction(DockableComponent dockableComponent) {
|
||||||
super("Close Window", DockingWindowManager.DOCKING_WINDOWS_OWNER);
|
super("Close Window", DockingWindowManager.DOCKING_WINDOWS_OWNER,
|
||||||
|
KeyBindingType.UNSUPPORTED);
|
||||||
this.dockableComponent = dockableComponent;
|
this.dockableComponent = dockableComponent;
|
||||||
setDescription("Close Window");
|
setDescription("Close Window");
|
||||||
setToolBarData(new ToolBarData(closeIcon, null));
|
setToolBarData(new ToolBarData(closeIcon, null));
|
||||||
|
|||||||
@@ -47,16 +47,14 @@ import util.CollectionUtils;
|
|||||||
* Manages the "Docking" arrangement of a set of components and actions. The components can be "docked"
|
* Manages the "Docking" arrangement of a set of components and actions. The components can be "docked"
|
||||||
* together or exist in their own window. Actions can be associated with components so they
|
* together or exist in their own window. Actions can be associated with components so they
|
||||||
* "move" with the component as it moved from one location to another.
|
* "move" with the component as it moved from one location to another.
|
||||||
*
|
* <P>
|
||||||
* Components are added via ComponentProviders. A ComponentProvider is an interface for getting
|
* Components are added via ComponentProviders. A ComponentProvider is an interface for getting
|
||||||
* a component and its related information. The docking window manager will get the component
|
* a component and its related information. The docking window manager will get the component
|
||||||
* from the provider as needed. It is up to the provider if it wants to reuse the component or
|
* from the provider as needed. It is up to the provider if it wants to reuse the component or
|
||||||
* recreate a new one when the component is requested. When the user "hides" (by using
|
* recreate a new one when the component is requested. When the user hides a component (by using
|
||||||
* the x button on the component area) a component, the docking window manager removes all
|
* the x button on the component header), the docking window manager removes all
|
||||||
* knowledge of the component and will request it again from the provider if the component
|
* knowledge of the component and will request it again from the provider if the component
|
||||||
* becomes "unhidden". The provider is also notified whenever a component is hidden. Some
|
* is again shown. The provider is also notified whenever a component is hidden and shown.
|
||||||
* providers will use the notification to remove the provider from the docking window manager so
|
|
||||||
* that the can not "unhide" the component using the built-in window menu.
|
|
||||||
*/
|
*/
|
||||||
public class DockingWindowManager implements PropertyChangeListener, PlaceholderInstaller {
|
public class DockingWindowManager implements PropertyChangeListener, PlaceholderInstaller {
|
||||||
|
|
||||||
@@ -712,8 +710,11 @@ public class DockingWindowManager implements PropertyChangeListener, Placeholder
|
|||||||
ComponentPlaceholder placeholder = getActivePlaceholder(provider);
|
ComponentPlaceholder placeholder = getActivePlaceholder(provider);
|
||||||
if (placeholder != null) {
|
if (placeholder != null) {
|
||||||
showComponent(placeholder, visibleState, true);
|
showComponent(placeholder, visibleState, true);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
|
if (visibleState) {
|
||||||
|
|
||||||
// a null placeholder implies the client is trying to show a provider that has not
|
// a null placeholder implies the client is trying to show a provider that has not
|
||||||
// been added to the tool
|
// been added to the tool
|
||||||
Msg.warn(this, "Attempting to show an unknown Component Provider '" +
|
Msg.warn(this, "Attempting to show an unknown Component Provider '" +
|
||||||
|
|||||||
@@ -76,11 +76,7 @@ class ShowComponentAction extends DockingAction implements Comparable<ShowCompon
|
|||||||
|
|
||||||
// keybinding data used to show the binding in the menu
|
// keybinding data used to show the binding in the menu
|
||||||
ComponentProvider provider = placeholder.getProvider();
|
ComponentProvider provider = placeholder.getProvider();
|
||||||
DockingActionIf action = provider.getShowProviderAction();
|
synchronizeKeyBinding(provider);
|
||||||
KeyBindingData kbData = action.getKeyBindingData();
|
|
||||||
if (kbData != null) {
|
|
||||||
setKeyBindingData(kbData);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use provider Help for this action
|
// Use provider Help for this action
|
||||||
HelpLocation helpLocation = provider.getHelpLocation();
|
HelpLocation helpLocation = provider.getHelpLocation();
|
||||||
@@ -94,6 +90,21 @@ class ShowComponentAction extends DockingAction implements Comparable<ShowCompon
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensures that the given provider's key binding matches this class's key binding
|
||||||
|
* @param provider the provider
|
||||||
|
*/
|
||||||
|
private void synchronizeKeyBinding(ComponentProvider provider) {
|
||||||
|
DockingActionIf action = provider.getShowProviderAction();
|
||||||
|
KeyBindingData defaultBinding = action.getDefaultKeyBindingData();
|
||||||
|
setKeyBindingData(defaultBinding);
|
||||||
|
|
||||||
|
KeyBindingData kbData = action.getKeyBindingData();
|
||||||
|
if (kbData != null) {
|
||||||
|
setUnvalidatedKeyBindingData(kbData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static KeyBindingType createKeyBindingType(boolean isTransient,
|
private static KeyBindingType createKeyBindingType(boolean isTransient,
|
||||||
ComponentPlaceholder placeholder) {
|
ComponentPlaceholder placeholder) {
|
||||||
|
|
||||||
|
|||||||
@@ -55,6 +55,16 @@ public interface DockingActionIf extends HelpDescriptor {
|
|||||||
*/
|
*/
|
||||||
public String getOwner();
|
public String getOwner();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a description of this actions owner. For most actions this will return the
|
||||||
|
* same value as {@link #getOwner()}.
|
||||||
|
*
|
||||||
|
* @return the description
|
||||||
|
*/
|
||||||
|
public default String getOwnerDescription() {
|
||||||
|
return getOwner();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a short description of this action. Generally used for a tooltip
|
* Returns a short description of this action. Generally used for a tooltip
|
||||||
* @return the description
|
* @return the description
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ public class KeyBindingsManager implements PropertyChangeListener {
|
|||||||
actionToProviderMap = new HashMap<>();
|
actionToProviderMap = new HashMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addAction(DockingActionIf action, ComponentProvider optionalProvider) {
|
public void addAction(ComponentProvider optionalProvider, DockingActionIf action) {
|
||||||
action.addPropertyChangeListener(this);
|
action.addPropertyChangeListener(this);
|
||||||
if (optionalProvider != null) {
|
if (optionalProvider != null) {
|
||||||
actionToProviderMap.put(action, optionalProvider);
|
actionToProviderMap.put(action, optionalProvider);
|
||||||
@@ -48,7 +48,7 @@ public class KeyBindingsManager implements PropertyChangeListener {
|
|||||||
KeyStroke keyBinding = action.getKeyBinding();
|
KeyStroke keyBinding = action.getKeyBinding();
|
||||||
|
|
||||||
if (keyBinding != null) {
|
if (keyBinding != null) {
|
||||||
addKeyBinding(action, optionalProvider, keyBinding);
|
addKeyBinding(optionalProvider, action, keyBinding);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,7 +67,7 @@ public class KeyBindingsManager implements PropertyChangeListener {
|
|||||||
removeKeyBinding(action.getKeyBinding(), action);
|
removeKeyBinding(action.getKeyBinding(), action);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addKeyBinding(DockingActionIf action, ComponentProvider provider,
|
private void addKeyBinding(ComponentProvider provider, DockingActionIf action,
|
||||||
KeyStroke keyStroke) {
|
KeyStroke keyStroke) {
|
||||||
if (ReservedKeyBindings.isReservedKeystroke(keyStroke)) {
|
if (ReservedKeyBindings.isReservedKeystroke(keyStroke)) {
|
||||||
throw new AssertException("Cannot assign action to a reserved keystroke. " +
|
throw new AssertException("Cannot assign action to a reserved keystroke. " +
|
||||||
@@ -145,7 +145,7 @@ public class KeyBindingsManager implements PropertyChangeListener {
|
|||||||
if (newKeyData != null) {
|
if (newKeyData != null) {
|
||||||
KeyStroke ks = newKeyData.getKeyBinding();
|
KeyStroke ks = newKeyData.getKeyBinding();
|
||||||
if (ks != null) {
|
if (ks != null) {
|
||||||
addKeyBinding(action, actionToProviderMap.get(action), ks);
|
addKeyBinding(actionToProviderMap.get(action), action, ks);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ public class MultipleKeyAction extends DockingKeyBindingAction {
|
|||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"KeyStrokes don't match - was: " + keyStroke + " new: " + keyBinding);
|
"KeyStrokes don't match - was: " + keyStroke + " new: " + keyBinding);
|
||||||
}
|
}
|
||||||
|
|
||||||
actions.add(new ActionData(action, provider));
|
actions.add(new ActionData(action, provider));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -273,5 +274,10 @@ public class MultipleKeyAction extends DockingKeyBindingAction {
|
|||||||
boolean isMyProvider(ComponentProvider otherProvider) {
|
boolean isMyProvider(ComponentProvider otherProvider) {
|
||||||
return provider == otherProvider;
|
return provider == otherProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return provider.toString() + " - " + action;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,15 @@ public interface DockingToolActions {
|
|||||||
*/
|
*/
|
||||||
public void addLocalAction(ComponentProvider provider, DockingActionIf action);
|
public void addLocalAction(ComponentProvider provider, DockingActionIf action);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the provider action by the given name
|
||||||
|
*
|
||||||
|
* @param provider the provider
|
||||||
|
* @param actionName the action name
|
||||||
|
* @return the action
|
||||||
|
*/
|
||||||
|
public DockingActionIf getLocalAction(ComponentProvider provider, String actionName);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes the given provider's local action
|
* Removes the given provider's local action
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -155,6 +155,7 @@ public class KeyEntryDialog extends DialogComponentProvider {
|
|||||||
|
|
||||||
KeyStroke existingKeyStroke = action.getKeyBinding();
|
KeyStroke existingKeyStroke = action.getKeyBinding();
|
||||||
if (Objects.equals(existingKeyStroke, newKeyStroke)) {
|
if (Objects.equals(existingKeyStroke, newKeyStroke)) {
|
||||||
|
setStatusText("Key binding unchanged");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -177,11 +178,18 @@ public class KeyEntryDialog extends DialogComponentProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void updateCollisionPane(KeyStroke ks) {
|
private void updateCollisionPane(KeyStroke ks) {
|
||||||
|
clearStatusText();
|
||||||
collisionPane.setText("");
|
collisionPane.setText("");
|
||||||
if (ks == null) {
|
if (ks == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
KeyStroke existingKeyStroke = action.getKeyBinding();
|
||||||
|
if (Objects.equals(existingKeyStroke, ks)) {
|
||||||
|
setStatusText("Key binding unchanged");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
List<DockingActionIf> list = getManagedActionsForKeyStroke(ks);
|
List<DockingActionIf> list = getManagedActionsForKeyStroke(ks);
|
||||||
if (list.size() == 0) {
|
if (list.size() == 0) {
|
||||||
return;
|
return;
|
||||||
@@ -193,7 +201,7 @@ public class KeyEntryDialog extends DialogComponentProvider {
|
|||||||
for (int i = 0; i < list.size(); i++) {
|
for (int i = 0; i < list.size(); i++) {
|
||||||
DockingActionIf a = list.get(i);
|
DockingActionIf a = list.get(i);
|
||||||
|
|
||||||
String collisionStr = "\t" + a.getName() + " (" + a.getOwner() + ")\n";
|
String collisionStr = "\t" + a.getName() + " (" + a.getOwnerDescription() + ")\n";
|
||||||
int offset = doc.getLength();
|
int offset = doc.getLength();
|
||||||
doc.insertString(offset, collisionStr, textAttrSet);
|
doc.insertString(offset, collisionStr, textAttrSet);
|
||||||
doc.setParagraphAttributes(offset, 1, tabAttrSet, false);
|
doc.setParagraphAttributes(offset, 1, tabAttrSet, false);
|
||||||
@@ -211,6 +219,7 @@ public class KeyEntryDialog extends DialogComponentProvider {
|
|||||||
if (multiAction == null) {
|
if (multiAction == null) {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
List<DockingActionIf> list = multiAction.getActions();
|
List<DockingActionIf> list = multiAction.getActions();
|
||||||
Map<String, DockingActionIf> nameMap = new HashMap<>(list.size());
|
Map<String, DockingActionIf> nameMap = new HashMap<>(list.size());
|
||||||
|
|
||||||
|
|||||||
+12
-2
@@ -85,13 +85,14 @@ public class SharedStubKeyBindingAction extends DockingAction implements Options
|
|||||||
updateActionKeyStrokeFromOptions(action, defaultKs);
|
updateActionKeyStrokeFromOptions(action, defaultKs);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getOwnersDescription() {
|
@Override
|
||||||
|
public String getOwnerDescription() {
|
||||||
List<String> owners = getDistinctOwners();
|
List<String> owners = getDistinctOwners();
|
||||||
Collections.sort(owners);
|
Collections.sort(owners);
|
||||||
if (owners.size() == 1) {
|
if (owners.size() == 1) {
|
||||||
return owners.get(0);
|
return owners.get(0);
|
||||||
}
|
}
|
||||||
return '(' + StringUtils.join(owners, ", ") + ')';
|
return StringUtils.join(owners, ", ");
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<String> getDistinctOwners() {
|
private List<String> getDistinctOwners() {
|
||||||
@@ -99,6 +100,11 @@ public class SharedStubKeyBindingAction extends DockingAction implements Options
|
|||||||
Set<DockingActionIf> actions = clientActions.keySet();
|
Set<DockingActionIf> actions = clientActions.keySet();
|
||||||
for (DockingActionIf action : actions) {
|
for (DockingActionIf action : actions) {
|
||||||
String owner = action.getOwner();
|
String owner = action.getOwner();
|
||||||
|
if (DockingWindowManager.DOCKING_WINDOWS_OWNER.equals(owner)) {
|
||||||
|
// special case: this is the owner for special system-level actions
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (!results.contains(owner)) {
|
if (!results.contains(owner)) {
|
||||||
results.add(owner);
|
results.add(owner);
|
||||||
}
|
}
|
||||||
@@ -139,12 +145,16 @@ public class SharedStubKeyBindingAction extends DockingAction implements Options
|
|||||||
|
|
||||||
private void updateActionKeyStrokeFromOptions(DockingActionIf action, KeyStroke defaultKs) {
|
private void updateActionKeyStrokeFromOptions(DockingActionIf action, KeyStroke defaultKs) {
|
||||||
|
|
||||||
|
KeyStroke stubKs = defaultKs;
|
||||||
KeyStroke optionsKs = getKeyStrokeFromOptions(defaultKs);
|
KeyStroke optionsKs = getKeyStrokeFromOptions(defaultKs);
|
||||||
if (!Objects.equals(defaultKs, optionsKs)) {
|
if (!Objects.equals(defaultKs, optionsKs)) {
|
||||||
// we use the 'unvalidated' call since this value is provided by the user--we assume
|
// we use the 'unvalidated' call since this value is provided by the user--we assume
|
||||||
// that user input is correct; we only validate programmer input
|
// that user input is correct; we only validate programmer input
|
||||||
action.setUnvalidatedKeyBindingData(new KeyBindingData(optionsKs));
|
action.setUnvalidatedKeyBindingData(new KeyBindingData(optionsKs));
|
||||||
|
stubKs = optionsKs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setUnvalidatedKeyBindingData(new KeyBindingData(stubKs));
|
||||||
}
|
}
|
||||||
|
|
||||||
private KeyStroke getKeyStrokeFromOptions(KeyStroke validatedKeyStroke) {
|
private KeyStroke getKeyStrokeFromOptions(KeyStroke validatedKeyStroke) {
|
||||||
|
|||||||
@@ -115,27 +115,21 @@ public class ToolActions implements DockingToolActions, PropertyChangeListener {
|
|||||||
|
|
||||||
action.addPropertyChangeListener(this);
|
action.addPropertyChangeListener(this);
|
||||||
addActionToMap(action);
|
addActionToMap(action);
|
||||||
setKeyBindingOption(action);
|
initializeKeyBinding(provider, action);
|
||||||
keyBindingsManager.addAction(action, provider);
|
|
||||||
actionGuiHelper.addLocalAction(provider, action);
|
actionGuiHelper.addLocalAction(provider, action);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds the action to the tool.
|
|
||||||
* @param action the action to be added.
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void addGlobalAction(DockingActionIf action) {
|
public synchronized void addGlobalAction(DockingActionIf action) {
|
||||||
checkForAlreadyAddedAction(null, action);
|
checkForAlreadyAddedAction(null, action);
|
||||||
|
|
||||||
action.addPropertyChangeListener(this);
|
action.addPropertyChangeListener(this);
|
||||||
addActionToMap(action);
|
addActionToMap(action);
|
||||||
setKeyBindingOption(action);
|
initializeKeyBinding(null, action);
|
||||||
keyBindingsManager.addAction(action, null);
|
|
||||||
actionGuiHelper.addToolAction(action);
|
actionGuiHelper.addToolAction(action);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setKeyBindingOption(DockingActionIf action) {
|
private void initializeKeyBinding(ComponentProvider provider, DockingActionIf action) {
|
||||||
|
|
||||||
KeyBindingType type = action.getKeyBindingType();
|
KeyBindingType type = action.getKeyBindingType();
|
||||||
if (!type.supportsKeyBindings()) {
|
if (!type.supportsKeyBindings()) {
|
||||||
@@ -143,7 +137,7 @@ public class ToolActions implements DockingToolActions, PropertyChangeListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (type.isShared()) {
|
if (type.isShared()) {
|
||||||
installSharedKeyBinding(action);
|
installSharedKeyBinding(provider, action);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,9 +148,11 @@ public class ToolActions implements DockingToolActions, PropertyChangeListener {
|
|||||||
if (!Objects.equals(ks, newKs)) {
|
if (!Objects.equals(ks, newKs)) {
|
||||||
action.setUnvalidatedKeyBindingData(new KeyBindingData(newKs));
|
action.setUnvalidatedKeyBindingData(new KeyBindingData(newKs));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
keyBindingsManager.addAction(provider, action);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void installSharedKeyBinding(DockingActionIf action) {
|
private void installSharedKeyBinding(ComponentProvider provider, DockingActionIf action) {
|
||||||
String name = action.getName();
|
String name = action.getName();
|
||||||
KeyStroke defaultKeyStroke = action.getKeyBinding();
|
KeyStroke defaultKeyStroke = action.getKeyBinding();
|
||||||
|
|
||||||
@@ -172,6 +168,9 @@ public class ToolActions implements DockingToolActions, PropertyChangeListener {
|
|||||||
});
|
});
|
||||||
|
|
||||||
stub.addClientAction(action);
|
stub.addClientAction(action);
|
||||||
|
|
||||||
|
// note: only put the stub in the manager, not the actual action
|
||||||
|
keyBindingsManager.addAction(provider, stub);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -318,10 +317,12 @@ public class ToolActions implements DockingToolActions, PropertyChangeListener {
|
|||||||
for (DockingActionIf action : set) {
|
for (DockingActionIf action : set) {
|
||||||
removeLocalAction(provider, action);
|
removeLocalAction(provider, action);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removeAction(DockingActionIf action) {
|
private void removeAction(DockingActionIf action) {
|
||||||
|
|
||||||
|
keyBindingsManager.removeAction(action);
|
||||||
|
|
||||||
getActionStorage(action).remove(action);
|
getActionStorage(action).remove(action);
|
||||||
if (!action.getKeyBindingType().isShared()) {
|
if (!action.getKeyBindingType().isShared()) {
|
||||||
return;
|
return;
|
||||||
@@ -370,6 +371,19 @@ public class ToolActions implements DockingToolActions, PropertyChangeListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DockingActionIf getLocalAction(ComponentProvider provider, String actionName) {
|
||||||
|
|
||||||
|
Iterator<DockingActionIf> it = actionGuiHelper.getComponentActions(provider);
|
||||||
|
while (it.hasNext()) {
|
||||||
|
DockingActionIf action = it.next();
|
||||||
|
if (action.getName().equals(actionName)) {
|
||||||
|
return action;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public Action getAction(KeyStroke ks) {
|
public Action getAction(KeyStroke ks) {
|
||||||
return keyBindingsManager.getDockingKeyAction(ks);
|
return keyBindingsManager.getDockingKeyAction(ks);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ import com.google.common.collect.Sets;
|
|||||||
import docking.*;
|
import docking.*;
|
||||||
import docking.action.DockingActionIf;
|
import docking.action.DockingActionIf;
|
||||||
import docking.action.ToggleDockingActionIf;
|
import docking.action.ToggleDockingActionIf;
|
||||||
|
import docking.actions.DockingToolActions;
|
||||||
import docking.dnd.GClipboard;
|
import docking.dnd.GClipboard;
|
||||||
import docking.framework.DockingApplicationConfiguration;
|
import docking.framework.DockingApplicationConfiguration;
|
||||||
import docking.menu.DockingToolbarButton;
|
import docking.menu.DockingToolbarButton;
|
||||||
@@ -1195,8 +1196,18 @@ public abstract class AbstractDockingTest extends AbstractGenericTest {
|
|||||||
return CollectionUtils.any(actions);
|
return CollectionUtils.any(actions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the action by the given name that belongs to the given provider
|
||||||
|
*
|
||||||
|
* @param provider the provider
|
||||||
|
* @param actionName the action name
|
||||||
|
* @return the action
|
||||||
|
*/
|
||||||
public static DockingActionIf getLocalAction(ComponentProvider provider, String actionName) {
|
public static DockingActionIf getLocalAction(ComponentProvider provider, String actionName) {
|
||||||
return getAction(provider.getTool(), provider.getName(), actionName);
|
DockingTool tool = provider.getTool();
|
||||||
|
DockingToolActions toolActions = tool.getToolActions();
|
||||||
|
DockingActionIf action = toolActions.getLocalAction(provider, actionName);
|
||||||
|
return action;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1850,10 +1861,12 @@ public abstract class AbstractDockingTest extends AbstractGenericTest {
|
|||||||
*
|
*
|
||||||
* @param tool the tool in which the provider lives
|
* @param tool the tool in which the provider lives
|
||||||
* @param name the name of the provider to show
|
* @param name the name of the provider to show
|
||||||
|
* @return the newly shown provider
|
||||||
*/
|
*/
|
||||||
public void showProvider(DockingTool tool, String name) {
|
public ComponentProvider showProvider(DockingTool tool, String name) {
|
||||||
ComponentProvider provider = tool.getComponentProvider(name);
|
ComponentProvider provider = tool.getComponentProvider(name);
|
||||||
tool.showComponentProvider(provider, true);
|
tool.showComponentProvider(provider, true);
|
||||||
|
return provider;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+1
-9
@@ -32,7 +32,6 @@ import docking.KeyEntryTextField;
|
|||||||
import docking.action.DockingActionIf;
|
import docking.action.DockingActionIf;
|
||||||
import docking.action.KeyBindingData;
|
import docking.action.KeyBindingData;
|
||||||
import docking.actions.KeyBindingUtils;
|
import docking.actions.KeyBindingUtils;
|
||||||
import docking.actions.SharedStubKeyBindingAction;
|
|
||||||
import docking.tool.util.DockingToolConstants;
|
import docking.tool.util.DockingToolConstants;
|
||||||
import docking.widgets.MultiLineLabel;
|
import docking.widgets.MultiLineLabel;
|
||||||
import docking.widgets.OptionDialog;
|
import docking.widgets.OptionDialog;
|
||||||
@@ -708,18 +707,11 @@ public class KeyBindingsPanel extends JPanel {
|
|||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
case PLUGIN_NAME:
|
case PLUGIN_NAME:
|
||||||
return getOwner(action);
|
return action.getOwnerDescription();
|
||||||
}
|
}
|
||||||
return "Unknown Column!";
|
return "Unknown Column!";
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getOwner(DockingActionIf action) {
|
|
||||||
if (action instanceof SharedStubKeyBindingAction) {
|
|
||||||
return ((SharedStubKeyBindingAction) action).getOwnersDescription();
|
|
||||||
}
|
|
||||||
return action.getOwner();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<DockingActionIf> getModelData() {
|
public List<DockingActionIf> getModelData() {
|
||||||
return tableActions;
|
return tableActions;
|
||||||
|
|||||||
Reference in New Issue
Block a user